Skip to main content

changelog

NumSharp's release-notes authoring + large-range commit-sweep playbook - how to write a changelog in the house style AND how to work through a few-hundred-commit range without missing or mis-stating anything. Use this whenever you write or refresh a release changelog (`docs/releases/RELEASE_<version>.md`), sweep a commit range for changes not yet in the changelog ("go over the commits and find what's unhandled"), decide whether a commit deserves a line, dedup many commits into one feature line, or verify a changelog is complete AND factually true. Trigger on: "changelog", "release notes", "write up the changelog", "CHANGELOG_STYLE", "RELEASE_x.y.z", "what's new since <version>", "go over the commits in batches", "find unhandled changes", "which commits are missing from the changelog", "sweep the commits", "master..<branch>", "categorize / dedup the commits", "did we cover every commit". Reach for it before hand-writing a changelog from `git log` or claiming a range is "fully covered".

Source facts

Repository
SciSharp/NumSharp
Last source activity
August 24, 2026 at 15:30
Detected SKILL.md language
English
Stars
1,484
Forks
205

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
5 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
changelog
description
NumSharp's release-notes authoring + large-range commit-sweep playbook - how to write a changelog in the house style AND how to work through a few-hundred-commit range without missing or mis-stating anything. Use this whenever you write or refresh a release changelog (`docs/releases/RELEASE_<version>.md`), sweep a commit range for changes not yet in the changelog ("go over the commits and find what's unhandled"), decide whether a commit deserves a line, dedup many commits into one feature line, or verify a changelog is complete AND factually true. Trigger on: "changelog", "release notes", "write up the changelog", "CHANGELOG_STYLE", "RELEASE_x.y.z", "what's new since <version>", "go over the commits in batches", "find unhandled changes", "which commits are missing from the changelog", "sweep the commits", "master..<branch>", "categorize / dedup the commits", "did we cover every commit". Reach for it before hand-writing a changelog from `git log` or claiming a range is "fully covered".
# NumSharp Changelog Authoring & Large-Range Commit Sweep ## Mental model (why this exists) A changelog is **derived from commits but is NOT a commit log.** It is organized by *feature*, one line per feature, with rigorous deduplication - many commits collapse to one line, and most commits produce **no** line at all. Getting that right over a few-hundred-commit range is a *process* problem, not a writing problem. **Two authorities, split by concern:** - **`references/CHANGELOG_STYLE.md`** owns the **FORMAT** - the section taxonomy, the one-line bullet shape, API back-ticking ("color"), the `xLOW->xHIGH` performance notation, the §7A New NuGet Packages / §7B Dashboards elaboration, and the §-numbered rules. **Read it first and follow it verbatim; never restate its rules from memory.** - **This skill** owns the **PROCESS** - how to enumerate the range, read every commit, bucket each one, dedup, write only the lines that are owed, and prove the result is both complete and true. A release changelog lives at `docs/releases/RELEASE_<version>.md`, derived from the release's commit range - usually `master..<branch>` (or `<prev-tag>..<branch>`). ## The two jobs (same engine) - **(A) Author / refresh** a changelog for a range from scratch. - **(B) Sweep** a range against an *existing* changelog - "find every commit whose change isn't represented yet." (The 0.70.0 journey3 sweep: 294 commits, 20 batches → 7 edits.) Both run the identical engine: **read every commit body, bucket each commit, then emit changelog lines only for the `UNHANDLED` bucket** (job A starts from an empty changelog; job B starts from a mostly-full one). Job B additionally **fact-checks the lines already there** (see accuracy below - this is where you catch a "fixed X" that should read "found and pinned X"). ## The core technique - the 5-bucket triage Read **every** commit body - subject *and* body (CHANGELOG_STYLE §1: "Never write a line from the subject alone; the body carries the parity claims, measured ratios, and breaking-change notes"). Put each commit in **exactly one** bucket: | Bucket | Meaning | Produces a line? | |--------|---------|:----------------:| | **1. Cited** | Its short hash already appears in the changelog. | No - done. | | **2. Folded** | Its substance belongs to a feature already listed (a follow-up `fix`/audit/test-wiring of an in-range feature). CHANGELOG_STYLE §10.4: never emit "fixed the thing I just added." | No - fold its hash onto the feature's line if it carries weight. | | **3. Package-internal** | It develops a NuGet package (OpenBLAS / pythonnet). It folds into that package's **§7A** elaboration, which carries **no hashes**. | No - but confirm the §7A section already names the capability it adds. | | **4. Excluded** | Docs-only, skill/website, chore/rename, `.git-blame-ignore-revs`, CI/signing, benchmark-infra, test/oracle-infra, internal refactor with no observable effect, merge (CHANGELOG_STYLE §11). | No. | | **5. UNHANDLED** | A genuine user-facing change (a `feat`/`fix`/breaking/`perf`-with-a-ratio) not represented anywhere. | **Yes** - write/insert one line in its section. | **Only bucket 5 gets a line.** The whole skill is: sort every commit into these five, cleanly. The hard-case decision rules (the ones that cost real judgement) are in **`references/triage-taxonomy.md`** - read it before ruling on any `perf`, any `!` breaking commit, or any `fix` bundled inside a feature commit. The traps that recur: - A `fix`/`feat` whose subject looks new but is a **follow-up** to an in-range feature → **Folded**. - A fix to **pre-existing** (shipped-before-this-range) behavior → its **own Parity line** (§10.5), *even when bundled in a commit cited for something else* (the `take`/`put` index-validation case). - A `perf` commit with **no NPY/NS ratio** in the body → **not** Performance (§8); if it's also bit-identical/no-behavior-change → **Excluded**. - A `perf` that merely **restores a degraded cell to parity** (not "beats NumPy") → not a Performance win. - A `refactor!`/`feat!` breaking an API that **never shipped in a release** → **not** user-facing breaking (a rename/removal within the same dev cycle). - **Compile-time-only** changes (ValueTuple field casing) with no runtime effect and no caller → **Excluded**. **Exposing internal types** as public → not a NumPy-surface feature → **Excluded**. - **Examples/demo** project work → **Excluded** (not shipped library API). ## Sweep procedure (brief) The full mechanical procedure - commands, the `dump_batch` helper, batch sizing, the Windows path trap - is in **`references/sweep-procedure.md`**. In brief: 1. **Range + count.** `git log --oneline master..<branch> | wc -l`. Confirm the target release file. 2. **Extract cited hashes** from the existing changelog: `grep -oE '`[0-9a-f]{8}`' docs/releases/RELEASE_<v>.md | tr -d '`' | sort -u`. 3. **Numbered oldest-first list** and the **uncited subset** (candidates to scrutinise), but plan to read **all** bodies anyway - the cited ones are where you fact-check existing lines. 4. **Batch by ~15 commits** (≈20 batches for a few-hundred-commit range). **Dump each batch's full bodies to a file in your session scratchpad** (not `/tmp` - the Read tool can't see Git-Bash `/tmp` on Windows), then Read the file. One batch ≈ 1-2 Read pages. 5. **Per batch: bucket every commit; update the changelog when the batch yields an UNHANDLED item, else continue.** State the verdict for each commit so the reasoning is auditable. 6. After the last batch, **verify accuracy** (below) and re-grep to confirm every new hash resolves. ## Verify the changelog is TRUE, not just complete Completeness is half the job; the other half is that **every claim traces to a commit body or a committed artifact**. Full checklist in **`references/verify-accuracy.md`**. The load-bearing ones: - **Every number** (coverage %, parity counts, `xN` ratios, size limits) must be quoted from a body, and must be the **final** value if it moved across the range (a coverage headline climbs commit-by-commit; cite the last one). - **"Fixed" vs "surfaced/pinned."** A commit that *finds* bugs and carves them to `[OpenBugs]` did **not fix** them. This is the single highest-value fact-check on an existing changelog. - **§7A package sections** must name every served function/mode/verb, spelled as the **real API** - read the seam / grep the surface, don't trust the prose (verify e.g. that a verb like `FromArrayLike` actually exists). - **Dedup correctness:** a "fixed the thing I just added" line is a defect - collapse it into the feature's line describing the *final* behavior. ## Critical gotchas (learned the hard way) - **The Read tool needs Windows paths; Git-Bash `/tmp` is invisible to it.** Dump commit bodies to the session **scratchpad** directory (the harness gives you one) and Read *that*. - **Bash output over ~60 KB is truncated to a file.** Either read the saved tool-result file, or - better - write the dump straight to a scratchpad file and Read it. Don't try to eyeball 15 long bodies from one Bash call's stdout. - **Oldest-first ordering** (`git log --reverse`) makes batches read as the journey's progression and makes "folded follow-up" obvious (the fix comes *after* the feat it patches). - **`§7A` carries no hashes.** Package-internal commits are handled by the package *section*, not by a per-commit line - so a package rename, delivery-model rework, or dtype-map fix is "handled" the moment the §7A elaboration is accurate. Your job for those is to *audit the section*, not add lines. - **The uncited set is a focusing tool, not a filter.** Most uncited commits are Excluded/Folded; the few genuine UNHANDLED items hide among them. But still read the *cited* bodies too - that's how you catch a wrong number or a "fixed" that should be "pinned." - **Don't inflate Performance.** A ratio only earns a Performance line if the body measures it and it is `>1` (or an honest `xLOW->xHIGH` spanning a sub-1 low). Parity-for-speed trades and restore-to-parity fixes are not Performance (§8, §13). ## References - `references/sweep-procedure.md` - the mechanical batch sweep: commands, the `dump_batch` helper, batch sizing, the scratchpad/Windows-path workflow, re-verification. - `references/triage-taxonomy.md` - the 5 buckets in full, every hard-case decision rule with a worked example from the 0.70.0 sweep, and the "which section does this feature go in" map. - `references/verify-accuracy.md` - the fact-check checklist: numbers, "fixed vs pinned", §7A/§7B audits, dedup correctness, and the final re-grep. - `references/CHANGELOG_STYLE.md` - **the format authority.** Section taxonomy, bullet shape, API color, hash placement, `xLOW->xHIGH`, §7A/§7B, the amendment log. Always defer to it for *how a line looks*.
View on GitHub