📎 Backport opencode skills from staging

This commit is contained in:
Andrey Antukh
2026-05-19 17:47:00 +02:00
parent 405a73e8ba
commit 0b0bd72dce
4 changed files with 301 additions and 22 deletions

View File

@@ -45,12 +45,12 @@ python3 tools/gh.py issues "2.16.0" --state all
python3 tools/gh.py issues "2.16.0" --exclude "release blocker,no changelog"
```
**Label exclusion rules:**
- `release blocker` — Internal release-blocking bugs not relevant to end users
- `no changelog` — Chore/refactor work that doesn't need a changelog entry
**Exclusion rules:**
- `no changelog` label — Chore/refactor work that doesn't need a changelog entry
- `Task` issue type — Internal chores are not user-facing; filter these out after fetching
The script outputs JSON with each entry containing `number`, `title`, `state`,
`labels`, and `closing_prs` (the PRs that fix each issue).
`issue_type`, `labels`, and `closing_prs` (the PRs that fix each issue).
### 3. Identify missing entries (optional)
@@ -84,15 +84,27 @@ The `prs` command returns JSON with `number`, `title`, `body`, `state`,
`merged_at`, `author`, `labels`, and `closing_issues`. PRs are fetched in
batches of 50 via GraphQL to stay within API limits.
### 5. Categorize entries
### 5. Categorize entries — strictly by issue type, never by labels or emoji
Check the labels on each issue to determine which section it belongs to:
Use the **Issue Type** field (GitHub's native issue type, exposed as
`issue_type` in the `gh.py` JSON output) to determine which section an entry
belongs to.
| Label / Title prefix | Changelog section |
|----------------------|-------------------|
| `bug` label or `:bug:` title prefix | `### :bug: Bugs fixed` |
| `enhancement` label or `:sparkles:` prefix | `### :sparkles: New features & Enhancements` |
| No label | Infer from title convention, default to bug fix |
> **⚠️ CRITICAL: Never use labels or title emoji prefixes for categorization.**
> Labels like `bug` and `enhancement`, as well as title prefixes like `:bug:`
> and `:sparkles:`, are frequently inaccurate, missing, or contradictory to the
> actual issue type. The `issue_type` field from `gh.py` is the single source
> of truth.
| `issue_type` value | Changelog section |
|--------------------|-------------------|
| `Bug` | `### :bug: Bugs fixed` |
| `Feature` or `Enhancement` | `### :sparkles: New features & Enhancements` |
| `Task` | **Exclude** — internal chores are not user-facing |
| `null` (not set) | Check labels as a fallback: `bug` label → bugs, otherwise enhancements |
The `gh.py` issues command already includes `issue_type` in every entry's
output. **No separate GraphQL query is needed.**
**Community contribution attribution:** If the issue or its fix PR has the
`community contribution` label, add an attribution `(by @<github_username>)`
@@ -205,6 +217,7 @@ Read the top of `CHANGES.md` and confirm:
can find the code changes.
- **Latest version first.** New sections are inserted at the top of the
changelog, below the `# CHANGELOG` header.
- **Issue Type determines section — exclusively.** Use the `issue_type` field from `gh.py` output (Bug → `:bug:`, Feature/Enhancement → `:sparkles:`). **Do not** use labels (`bug`, `enhancement`) or title emoji prefixes (`:bug:`, `:sparkles:`) — they are frequently wrong or contradictory. The `issue_type` is the single source of truth.
- **User-facing descriptions.** Write from the user's perspective — describe
what broke and what was fixed, not internal implementation details.
- **Community attribution.** When the issue or fix PR has the
@@ -213,8 +226,9 @@ Read the top of `CHANGES.md` and confirm:
issue author) for the attribution.
- **Only closed issues.** An issue must have `state: "closed"` to appear in
the changelog. Open unresolved issues are omitted.
- **Excluded labels.** Issues with `release blocker` or `no changelog` labels
must be excluded from the changelog.
- **Excluded issues.** Issues with `no changelog` label must be excluded.
Issues with `issue_type: "Task"` must also be excluded — they are internal
chores, not user-facing changes.
- **Multiple PRs per issue.** If multiple PRs fix the same issue, list them
comma-separated inline: `(PR: [#A](url), [#B](url))`.
- **Duplicate removal.** If an entry already exists in a prior version section,