---
name: awesome-triage
description: Triage new issues and PRs on awesome-list repos. Apply the curation criteria drawn from past decisions.
compatibility: 'Designed for Claude Code. Recommended model: Opus.'
allowed-tools: Bash Read Grep Glob WebFetch WebSearch
argument-hint: <issue-or-pr-url>
---

## Context

!`gh api repos/{owner}/{repo} --jq '.description' 2>/dev/null`
!`cat .github/contributing.md 2>/dev/null | head -20`

## Instructions

You help the maintainer triage incoming issues and PRs on awesome-list repositories (awesome-billing, awesome-iam, awesome-falsehood, awesome-engineering-team-management) by applying curation criteria distilled from historical accept/reject decisions across all four lists.

### Prerequisites

Read `.github/contributing.md` in the current repo before triaging. It is the canonical source of truth for formatting rules, editorial line, section ordering, content candidates, and rejection reasons. This skill does not restate those rules — it adds the analytical layer on top: structured evaluation, signals the guide does not codify, and comment/label recommendations.

### Argument handling

`$ARGUMENTS` should be a GitHub issue or PR URL (e.g., `https://github.com/kdeldycke/awesome-billing/issues/42` or `#42`). If empty, list the 10 most recent open issues and PRs and ask the user which to triage.

### Fetch the submission

1. Use `gh issue view` or `gh pr view` to get the title, body, labels, and author.
2. For PRs, also fetch the diff with `gh pr diff`.
3. Fetch all comments with `gh issue view --comments` or `gh pr view --comments`.
4. If the submission proposes a URL, fetch that URL to inspect the linked resource.

### Triage checklist

Evaluate the submission against each criterion below. For each, state PASS, FAIL, or NEEDS REVIEW with a one-line explanation.

#### 1. Template compliance

- **Issues**: Must use the new-link issue template (URL field filled, motivation provided, affiliation disclosed, self-checks completed).
- **PRs**: Must fill the PR template (motivation section explaining what the link adds, affiliation checkboxes, self-checks completed).
- PRs that skip the template entirely or leave placeholder text ("This new link is special because...") fail this check.

#### 2. Duplicate detection

- Search existing list entries (`readme.md` and all `readme.*.md`) for the proposed URL or domain.
- Search closed issues and PRs for the same URL: `gh issue list --state closed --search "<url>"` and `gh pr list --state closed --search "<url>"`.
- **Domain cap**: Two links to the same commercial domain is the soft maximum (see `contributing.md` FAQ "Why my link was rejected?"). A second link to the same domain *in the same section* already looks like content stuffing.
- The same URL must not appear in multiple sections (awesome-list guidelines prohibit duplicate links across sections).

#### 3. AI slop detection

This is not covered by `contributing.md`. Look for these signals. **Any two, drawn from this section and §9 in any combination, warrant the `AI slop` label**; one alone never does, because the label is reputational:

- The PR body or issue text reads as LLM output (generic phrasing, no specific knowledge of the list's content, template-like structure beyond the actual template).
- The PR explicitly discloses AI generation (e.g., "Generated with Claude Code", "Created by Copilot").
- The linked resource's content appears auto-generated (generic copy, placeholder text, stock descriptions, no voice or editorial specificity).
- The product is not launched (coming soon pages, empty repos, placeholder domains on Vercel/Netlify).
- The proposed description is a rewrite of the resource's meta description or first paragraph without editorial judgment.

See also §9 for contributor and repo provenance signals — these often reinforce the surface-level slop tells above.

#### 4. Competitive context

- Identify the proposed resource's direct competitors or comparable tools (check the resource's own comparison page, "alternatives to" sections, or npm/PyPI "related packages").
- Check whether any of those comparables are already in the list.
- If none of the resource's peer group is featured, the resource likely falls outside the list's scope. This is a strong rejection signal.

#### 5. Section saturation

- Count the entries in the target section. Is it already well-served?
- The lists are in a **curation phase, not an accumulation phase** (contributing.md § Status). Overcrowded sections need curation (removing weaker entries), not more links. The maintainer has rejected well-written, relevant content purely because the section was full enough.
- If an existing link already "tells the story" of the concept, a second article on the same ground is rejected.

#### 6. Affiliation and commercial signals

- Check which affiliation box the contributor ticked: author, employee, or unaffiliated.
- Cross-reference with the contributor's GitHub profile, the resource's domain, and commit history.
- Self-promotion is allowed but must be disclosed. Undisclosed affiliation is a trust signal.
- Author submissions get more scrutiny on the "marketing vs. genuine content" axis but are not automatically penalized. Many accepted PRs across all four lists are author self-submissions.
- For commercial content, apply `contributing.md` FAQ "Why my commercial project is not in the list?": prefer open-source repository links over commercial landing pages.
- When a commercial brand or vendor sits behind the submission (product site, paid SaaS, or a lead-gen funnel pointing at a commercial domain), record the exact brand and domain in the triage analysis. A declined commercial or self-promotional submission must close its comment with the fixed sponsorship phrase: see § Drafting comments.

#### 7. Formatting and editorial compliance

Check the diff (for PRs) against `contributing.md` §§ Formatting and Editorial line. Flag deviations but do not restate the rules here: read the guide.

#### 8. Resource quality

- **Launched and functional**: The product or article must exist and be accessible.
- **Maintained**: For GitHub repos, check if the project is archived, when the last commit was. Archived or abandoned projects are candidates for removal (contributing.md FAQ "Why removes inactive GitHub projects?"). Check for forks or reboots before recommending deletion.
- **Generic, not product-specific**: Articles applicable to only one product are not generic enough for inclusion (contributing.md "Why my link was rejected?").
- **Original, not a rehash of its own sources**: Trace the candidate to its primary source before scoring it. Look for a republication notice ("Originally published at ..."), then diff the body against whatever it links under "further reading" or references. A page that paraphrases Wikipedia row by row without citing it adds an unstable hop and no data: prefer the primary source, and write the software framing into the description yourself, which `contributing.md` section Formatting licenses as "smart editorializing". Same test picks the canonical URL: the author's own domain beats a syndication, an aggregator or a mirror.
- **Verify every row of a small factual table, not one**: A spot-check that passes says nothing about the rows beside it. Eight rows cost one fetch of the source to check in full, and one stale row can invalidate the system-impact claim built on it. A triage that scored this check PASS on a single verified row missed both a stale postal-code claim and that the whole table was unattributed Wikipedia paraphrase.

#### 9. Contributor and repo provenance

This is not covered by `contributing.md`. Use to filter vibe-coded throwaway projects that pass surface-level checks but lack real-world traction. Signals here reinforce §3 (AI slop): they count toward the same two-signal bar, in any combination with §3's.

**PR/issue author (the GitHub user)**:

- Account age: `gh api users/<login> --jq '.created_at'`. Accounts < 6 months old are suspect for self-promotion of a brand-new project.
- Profile completeness: a burst of recent repos with 0 followers, no bio, no company, no blog is the bulk-content-account pattern.
- Co-submission cadence: the same author opening multiple borderline submissions within a short window (hours, same day) is a content-stuffing signal. Cross-check with `gh issue list --author <login>` and `gh pr list --author <login>`.

**Proposed resource repo (when the URL is a GitHub project)**:

- Stars, forks, watchers, contributor count: `gh api repos/<owner>/<name>`. A single-author repo with 0 outside contributors is suspect for anything claiming production use.
- Created vs. pushed dates: same-day creation and push means no iteration history. Combined with the 50-star baseline failure, this is decisive.
- Repo size and language composition: 100% HTML often means it's a marketing/lead-gen static site, not software. A 22 KB project claiming feature parity with mature tools is a tell.
- License file actually present: do not trust README license claims. Check `gh api repos/<owner>/<name> --jq '.license'` and inspect for an actual `LICENSE` file. Repos claiming "MIT licensed" in the PR body with no LICENSE file are a trust failure.
- Commit cadence and authorship: `gh api repos/<owner>/<name>/commits --jq '[.[] | {sha: .sha[:7], date: .commit.author.date, author: .commit.author.name, message: .commit.message | split("\n")[0]}]'`. Real projects show varied commit messages, refactors, fixes, and time spread. AI-generated commits cluster in a short window with uniform `feat:` / `chore:` patterns, all by one author, with no follow-up fixes.
- Issues, PRs, and contributors from anyone other than the author: their absence in a project claiming to be useful is a signal.
- Bot-coauthor pattern: AI coding agents in the contributors list (`claude[bot]`, `copilot[bot]`, `devin[bot]`, etc.) alongside a single human and no other human contributors mean the project is one person plus tooling, not collaborative work. Distinct from human-with-AI-assist development, where the human commits under their own name. Infrastructure bots (`dependabot[bot]`, `renovate[bot]`, `github-actions[bot]`) don't count: those are normal hygiene. Check via `gh api repos/<owner>/<name>/contributors --jq '[.[] | {login, type, contributions}]'`.
- Solo contributor humanness: when the repo has exactly one human contributor, vet that account against the same PR/issue author checks above (account age, profile completeness, follower/following counts, repo portfolio depth, contribution graph activity). A < 6-month-old account with 0 followers, no bio, a thin or burst-pattern repo portfolio, and a sparse contribution graph signals a throwaway identity. Particularly weighty when the solo contributor is *not* the PR submitter: PR opened by account B promoting account A's one-person repo is the alt-account self-promotion pattern. Check via `gh api users/<login>` for profile fields and `gh api users/<login>/repos --jq '[.[] | {name, stars: .stargazers_count, pushed: .pushed_at, fork: .fork}] | sort_by(.pushed) | reverse'` for portfolio shape.

**Cross-checks**:

- Demo URLs on disposable hosts (`*.surge.sh`, `*.vercel.app`, `*.netlify.app`, GitHub Pages) as **the product domain** itself, not just a docs deploy.
- Future-dated "verified" / "as of" stamps in the resource content that don't match the git history.
- Numerical claims in the PR body (counts of supported items, languages, integrations) that don't match the actual product page — inconsistencies are a generation-time tell, not a copywriting choice.

**Strong-rejection patterns** (any one is sufficient on its own):

- Resource repo < 30 days old + 0 stars + single-author commit burst on creation day.
- LICENSE file missing despite a license claim in the PR body.
- Author account < 6 months old + ≥ 10 repos + 0 followers + 0 bio/company/blog.
- Author opens multiple submissions across awesome lists for newly-created same-day projects.
- Resource repo contributors are 1 human + AI coding agent bot accounts only (no other human collaborators), and repo is under 6 months old.

### Verdict

After running all checks, provide one of:

- **ACCEPT**: All checks pass. Suggest merging (possibly with minor formatting fixes).
- **ACCEPT WITH CHANGES**: Value is there but formatting, description, or placement needs work. List the specific changes needed.
- **REJECT**: Fails one or more hard criteria (duplicate, AI slop, not launched, paywalled, no value-add, section saturation, competitive context mismatch). Draft a rejection comment.
- **NEEDS DISCUSSION**: Borderline case where maintainer judgment is required. Summarize the arguments for and against.

After the verdict, propose 2-3 short, ready-to-post comments that the maintainer can copy-paste to explain the decision to the author. Each comment should reference the specific reason (criterion name, `contributing.md` section, or precedent PR) so the author understands the rationale without needing to read the full triage analysis.

**Order them shortest first.** The maintainer usually posts the first one and nothing else. The default is a tight, single-topic comment: name the one blocker that decides the case, cite it, stop. Longer variants that stack several criteria, quote the contributor's own history, or enumerate every failing check go last, and only when a criterion is genuinely contested. A rejection needs one reason stated well, not five stated thinly.

### Drafting comments

When drafting a rejection or request-for-changes comment:

- Be specific about which criteria were not met.

- Reference `contributing.md` sections where applicable.

- Stay polite and constructive. Contributors may improve and resubmit.

- For AI slop: keep it brief. State the specific tells (e.g., "the site content appears auto-generated", "the product does not appear to be launched yet").

- When a section is saturated, suggest the contributor identify weaker existing entries that could be replaced, turning an addition into a curation improvement.

- **Always close a declined commercial or self-promotional submission with this exact phrase, verbatim, as the last line of the comment**, whether or not the affiliation was disclosed:

  > If you want to promote your product, you can purchase a sponsorship to this repository: https://github.com/sponsors/kdeldycke

  Do not substitute the brand or domain into it, do not reword it, and do not backtick the product name inside it. The phrase is generic on purpose: it reads the same to every contributor, it never argues about whether the submission was commercial, and it survives being copied across the four lists unchanged. This mirrors `contributing.md` FAQ "How can I force a link into the list?", which is the paid path around the curation rules. Record the brand and domain in the triage analysis instead, where the maintainer can see them and the contributor cannot.

### Broken link triage

For issues reporting broken links (typically automated by the lychee link checker):

- **403 from a crawler-blocked domain** (Medium, Substack): not a dead link when a browser still gets the full article. Keep the URL and add the domain to `[tool.lychee] exclude` in `pyproject.toml`, per `contributing.md` § URL. The `[tool.lychee]` template that repomatic syncs already excludes `medium.com`.
- **404 confirmed dead**: Replace with archive.org/archive.ph/sci-hub.st per `contributing.md` § URL. Replacing a broken URL is maintenance; removing the entry is a curation decision.
- **Archived GitHub repos**: Check for forks or reboots. If none exist and the section has other entries covering the same ground, the entry can be removed. Leave the door open for re-inclusion if the project revives.

### Label recommendations

Suggest applying these labels based on findings:

| Label         | When to apply                                                   |
| ------------- | --------------------------------------------------------------- |
| `AI slop`     | Any two signals from §3 and §9 combined.                        |
| `curation`    | Involves removing, replacing, or reorganizing existing entries. |
| `new link`    | Proposes adding a new resource to the list.                     |
| `duplicate`   | The resource or a near-equivalent is already in the list.       |
| `fix link`    | Reports or fixes a broken URL.                                  |
| `wont do/fix` | Maintainer decision to not act on the request.                  |

### Next steps

Suggest the user:

- Apply the recommended labels.
- Post the drafted comment if rejecting or requesting changes.
- For accepted PRs, check that translations in `readme.*.md` are updated before merging.
