Rules and skills that teach AI agents how to contribute to open source projects without being the villain.
95
91%
Does it follow best practices?
Impact
96%
3.55xAverage score across 20 eval scenarios
Advisory
Suggest reviewing before use
Analyze an open source project to understand its contribution norms before any code is written. This skill produces a report for the contributor — not a PR, not code, just intelligence.
Helper script path: bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh
Every helper command prints exactly one JSON envelope on stdout:
{"command": "<name>", "ok": <bool>, "data": <object|null>, "warnings": [...], "errors": [...]}. Read fields from data. If ok is false, treat the command as failed and surface the messages in errors to the contributor; do not synthesize the missing payload from prior knowledge. Pay attention to anything in warnings (e.g., the check-claim deprecation notice).
Confirm the task involves contributing to an external open source project (GitHub URL, "submit a PR", "contribute a fix", etc.). If internal or personal project — skip this skill entirely.
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh repo-scan OWNER/REPORead each category from data. Two shapes apply:
data.policy_files, data.agent_instructions, data.conventions, data.build_meta — each expose {found, missing} against a fixed expected list. Note both.data.pr_templates, data.issue_templates, data.test_fixtures, data.ci_workflows — each expose {found} only. There is no enumerated set of "expected" templates or workflow paths to be missing from, so missing would be meaningless. Treat an empty found as "absent".Proceed to Step 2.
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh ai-policy OWNER/REPOThe script returns data.files — an array with one entry per policy file (AI_POLICY.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md), each carrying found and content. Read every entry whose found is true and determine the project's AI stance. Look for explicit negatives alongside "AI": "do not", "cannot", "banned", "prohibited", "not allowed", "not accepted." Check for hard-stop consequences: "PRs will be closed", "contributions rejected", "account suspended." If you find these, that's a ban. Look for disclosure language: "must disclose", "required to disclose", "include what tool." Check for conditional restrictions: "AI not allowed on good-first-issue", "AI only with full human review." Absence of any AI mention means no policy — NOT a ban. Then act:
contribution_blocked.md in the workspace root — containing the policy text that bans AI, the consequences the policy states (PRs closed, etc.), the suggestion that the contributor can still contribute without AI, and any other guidance the policy itself offers. The file is the deliverable. Do NOT end this session without writing the file.Run ALL three commands — these are not optional:
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh issue OWNER/REPO ISSUE_NUMBERbash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh issue-comments OWNER/REPO ISSUE_NUMBERbash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh related-prs OWNER/REPO ISSUE_NUMBERAfter running issue-comments, answer this question before anything else: Is this issue claimed by another contributor? A claim is any comment expressing intent to work on the issue ("I'll take this", "claiming this", "I've started a branch", "PR in progress", or equivalents in any language).
If ANYONE has claimed it: STOP writing code for this issue, then proceed immediately to produce the redirect deliverable. Run issues-open to list alternatives and run disclosure-format OWNER/REPO to capture the exact disclosure template. Then write redirect_report.md in the workspace root — containing: who claimed the original issue (username + date + quoted comment), warning about competing PR etiquette, the list of alternative open issues with numbers, titles, and labels, the project's AI disclosure format (or voluntary template if no policy). If the project has no AI policy, include the voluntary disclosure template instead. The file is the deliverable. Do NOT end this session without writing the file.
If NOT claimed, continue with remaining checks:
redirect_report.md in the workspace root — containing the restriction (with the policy quote), why the restriction exists, alternative open issues the contributor CAN work on with AI, and non-AI guidance for the restricted issue (approach hints from the issue, referenced code files, relevant conventions from recon). The file is the deliverable.bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh disclosure-format OWNER/REPOSave the exact template for the PR description. If no policy, recommend voluntary disclosure.
Run ALL commands:
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh conventions-config OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh contributing-requirements OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh commit-conventions OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh branch-conventions OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh pr-stats OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh codeowners OWNER/REPObash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh legal OWNER/REPOAfter running all of the above, synthesize across the responses:
legal.data: read dco_file, signed_off_count / signed_off_total, license, and ci_workflows to determine whether DCO is enforced and what license applies.contributing-requirements.data (found, content): the full CONTRIBUTING.md text when present. Look for imperative language: "you must", "required", "must include", "always", "do not." These indicate hard requirements. Softer language ("we recommend", "we appreciate", "consider") indicates preferences, not requirements. Then note action items:git commit -s to add Signed-off-by, and that the agent cannot sign for them — this is a legal attestation that only the contributor can make.conventions-config.data.editorconfig.found or conventions-config.data.pre_commit_config.found is true: note in the recon report that the contribution must follow the configured settings exactly (indent_size, line_length, hooks).commit-conventions.data (format, signed_off_required, examples) and branch-conventions.data (dominant, issue_numbers_in_branch, examples) in the recon report so downstream skills (preflight) apply them when the contribution is created. The recon report should specify them precisely; recon does not create commits or branches itself.make lint, npm run lint), add this to the action items the recon report enumerates for the contributor and downstream skills. Both tests AND linters must pass before submission.Read each file the contribution depends on using the file command — pass the path verbatim from the relevant repo-scan found array:
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh file OWNER/REPO <path>Specifically read and act on:
If the contributor needs alternatives (claimed issue, restricted issue, or rejected direction):
bash .tessl/tiles/tessl-labs/good-oss-citizen/skills/recon/scripts/bash/github.sh issues-open OWNER/REPOPresent each open issue with its number, title, labels, and assignment status (read from data.issues[]).
Compile findings into a structured report following the template in skills/recon/REPORT_TEMPLATE.md. The template enumerates ten sections; under each, summarize the relevant fields from each command's data payload — never paste the raw envelope JSON. The report's audience is the contributor (and downstream skills), not a machine.
If Step 2 triggered the AI-ban hard stop, you have already written contribution_blocked.md — finish here.
If Step 3 triggered a claimed-issue or restricted-label hard stop, you have already written redirect_report.md — finish here.
Otherwise, proceed immediately to the propose skill:
Skill(skill: "propose")
Do not end the session here — propose will select the venue (PR / issue / discussion / RFC) and draft the proposal. Recon alone is not a complete deliverable unless a hard-stop fired.