Skip to content
Back to skills

Kernel Watch Triage

ASecurity

Guides triaging a kernel-sound-watch hit comment on the "Kernel sound-tree watch" issue (#40) — the weekly workflow's per-tag report of `.github/kernel-watchlist.txt` grep hits against a new tiwai/sound pull tag. Load this when asked to "analyse/check the latest kernel watchlist hit", when a kernel-sound-watch comment needs a verdict, or before appending a `### Triage` section to one. Covers reading the commit range cheaply, judging a hit against the watch that fired it, verifying claims agai...

  • 141 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
researchpythongobashgitapi

Works with

  • api

Security analysis

A100/100

Scanned October 6, 2026

npx -y skills add antoinecellerier/speaker-tuning-to-easyeffects --skill kernel-watch-triage --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Kernel Watch Triage?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Kernel Watch Triage
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/antoinecellerier-kernel-watch-triage/badge)](https://www.skillsdirectory.com/skills/antoinecellerier-kernel-watch-triage)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: kernel-watch-triage
description: >-
  Guides triaging a kernel-sound-watch hit comment on the "Kernel
  sound-tree watch" issue (#40) — the weekly workflow's per-tag report of
  `.github/kernel-watchlist.txt` grep hits against a new tiwai/sound pull
  tag. Load this when asked to "analyse/check the latest kernel watchlist
  hit", when a kernel-sound-watch comment needs a verdict, or before
  appending a `### Triage` section to one. Covers reading the commit range
  cheaply, judging a hit against the watch that fired it, verifying claims
  against the kernel source rather than the changelog, and the blast-radius
  checks on our own tables.
---

# Triaging a kernel-sound-watch hit

The output is a `### Triage (YYYY-MM-DD)` section appended to the hit comment
itself, in the format under "Record the verdict" below. That edit is the whole
point: nothing else distinguishes an unassessed hit from a cleared one. The
workflow never re-reads hit comments, so editing them is safe.

This is bookkeeping, not a reply: no draft-for-review cycle. The citation
rules in `/issue-replies` still apply: external SHAs need explicit markdown
URLs to `github.com/torvalds/linux`, and only this repo's SHAs auto-link.

Copy this checklist and tick items off. Each maps to a section below.

```
Triage progress:
- [ ] 1. Read the commit range — fetch the tags into the local clone
- [ ] 2. Re-grep every watch term over full messages, zeros included
- [ ] 3. Read each hit's diff; verify what its message claims
- [ ] 4. Resolve PCI vs codec SSID for any tested device involved
- [ ] 5. Skim the non-hit subjects for a class nothing watches yet
- [ ] 6. Check the blast radius on our own tables
- [ ] 7. Append the Triage section; touch the watchlist only if something moved
```

## Read the range once

The comment already carries the grep hits, a `scan_sound_tag.py` commit scan,
and the full pull text folded below. It carries no commit *body* or diff, and
that is what you fetch.

- Use the local `torvalds/linux` clone at `~/src/linux`, and fetch the
  range into it yourself. Pull tags live in tiwai's tree and may not be
  merged to mainline yet, so the clone carries tiwai's tree as its `sound`
  remote:

  ```bash
  git -C ~/src/linux fetch sound \
    refs/tags/<base>:refs/tags/<base> refs/tags/<tag>:refs/tags/<tag>
  ```

  It only adds refs and objects, so the working tree and `master` are left
  alone. Run it in the background: `git.kernel.org` ignores `--filter`, so
  the range's objects arrive in full. Then `git log`/`grep` over the range is
  instant, and `git show` fetches any older blob it lacks from `origin`.
- If the remote is missing, add it once. `git fetch` over HTTPS works on
  `git.kernel.org`; only its web pages sit behind an anti-bot wall.

  ```bash
  git -C ~/src/linux remote add sound \
    https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
  git -C ~/src/linux config remote.sound.tagOpt --no-tags
  ```

- Use the googlesource HTTP mirror only when git fetch fails, with one range
  request and not one per commit.
  `<mirror>/+log/<base>..<tag>?format=JSON&n=10000` returns every commit with
  its full message, as `tools/scan_sound_tag.py` does.

## Attribute every hit to its watch before judging it

`.github/kernel-watchlist.txt` groups terms under `# watch:` headers naming
the issue or the standing lesson that owns them. Find the header whose term
fired, and let it decide what "relevant" means. A commit that matched
`ideapad` but limits *mic* boost is a clear pass. Say so rather than listing
it unexplained.

Re-run the grep yourself over the range's full messages, per term, and record
the count for every term, zeros included. The comment names hit commits
without saying which term matched, and a term can fire from a `Fixes:` line or
a body mention rather than the subject. The re-grep turns "no commit
touches #39" into "`tas2781` fired, but only via two Lenovo ALC287 quirks".

Give a verdict for **every** watch, including the silent ones, such as
"untouched; ids byte-identical to the previous tag". A reader has to be able
to tell a checked watch from a forgotten one.

## Read the diff, not the changelog

A commit message can claim more than the diff delivers. `7e77c09e23da` says it
reorders two Lenovo quirk entries "restoring internal speaker functionality".
The diff swaps two adjacent entries carrying the *same* fixup, so no machine's
behaviour changes.

Check any ordering or matching claim against `snd_hda_pick_fixup` in
`sound/hda/common/auto_parser.c`:

- It makes one pass over the table, and the first match wins. Each entry is
  compared against the codec SSID when its `match_codec_ssid` flag is set,
  and against the PCI SSID otherwise. `HDA_CODEC_QUIRK` sets the flag, and
  `SND_PCI_QUIRK` does not. A codec-SSID sweep runs afterwards as a fallback.
- So two entries with different ids and the same fixup cannot differ in
  effect. Ordering only matters where the fixups differ.
- Since 7.1, a PCI SSID with either half zero, such as `17aa:0000` under SOF,
  skips the PCI comparison entirely. Every entry there, `SND_PCI_QUIRK`
  included, is then compared against the **codec** SSID. So a PCI-keyed entry
  *can* match such a machine, on its codec id.

## Resolve SSIDs both ways

PCI SSID ≠ codec SSID, and a machine collides with a different quirk under
each. Pull the pair from the device report before claiming a tested device is
or isn't affected, and say which id you matched on. `--speaker-info` names
both: `Codec subsystem:` under `HDA codecs`, and `Controller subsystem:` under
`PCI audio subsystem`. The README tested table's hidden codec and subsystem
comment on each device row may hold either.

## Sweep what the grep did not hit

Skim all subjects in the range for a shape we have no term for: a new
smart-amp part, a new speaker-path failure mode, a first machine on a platform
we watch. The comment's folded "Speaker-path commits" list matches subject
lines only, and the watchlist only knows the classes we already track. An
unwatched class first appears this way, which is why the watch reads commits
at all rather than the pull text alone.

## Check the blast radius on our side

For anything that touches a speaker path, ask which of our surfaces should
have carried it:

- `lib/data/speaker_pin_quirks.py` holds pin-*adding* fixups only.
  `tools/update_speaker_pin_quirks.py` regenerates it weekly, taking
  membership from `HDA_FIXUP_PINS` tables plus the hand-verified
  `_FUNC_FIXUP_PINS` allowlist of `HDA_FIXUP_FUNC` helpers. A new pin-writing
  helper is **silently missed**, because the updater's own guard only catches
  *renames* of listed ones. Audit the allowlist against upstream while you are
  in the tree:

  ```bash
  python3 - <<'PY'
  import re
  src = open('sound/hda/codecs/realtek/alc269.c').read()
  found = {m.group(1) for m in re.finditer(
      r'^static void (\w+)\(struct hda_codec \*codec,.*?\n\}\n', src, re.S|re.M)
      if re.search(r'0x9017[0-9a-f]{4}', m.group(0))}
  print(sorted(found))  # compare against _FUNC_FIXUP_PINS
  PY
  ```

- `lib/hardware/amps.py` `_AMP_FAMILIES`: check for a missing *amplifier*,
  the AW88399 shape. Its membership bar is `r-smart-amp-families` in
  `docs/research/hardware-and-drivers.md`.
- `lib/data/speaker_route_quirks.py` holds fixups that reroute one speaker pin
  off a widget with no volume amplifier: `snd_hda_override_conn_list` with no
  pincfg write, plus `alc289_fixup_asus_ga401`'s `preferred_dacs`.
  `tools/update_speaker_route_quirks.py` regenerates it weekly the same way,
  taking membership from the hand-verified `_FUNC_FIXUP_ROUTES` allowlist
  only. It has the same one-sided guard, so a new routing helper is silently
  missed too. Audit while you are in the tree:

  ```bash
  python3 - <<'PY'
  import re
  src = open('sound/hda/codecs/realtek/alc269.c').read()
  found = {m.group(1) for m in re.finditer(
      r'^static void (\w+)\(struct hda_codec \*codec,.*?\n\}\n', src, re.S|re.M)
      if 'snd_hda_override_conn_list' in m.group(0)
      and not re.search(r'0x9017[0-9a-f]{4}', m.group(0))}
  print(sorted(found))  # compare against _FUNC_FIXUP_ROUTES + its
  PY                    # recorded exclusions
  ```

  `preferred_dacs`-only helpers don't show up in that sweep. All five in
  mainline were hand-read 2026-09-01, and every one but GA401 was excluded.
  The membership bar and each exclusion's reason are in
  `docs/research/hardware-and-drivers.md`, `r-speaker-dac-misrouted`. Re-read a
  helper only when the range you are triaging adds or edits one.
- `_FILE_MOVES` in `tools/update_speaker_pin_quirks.py`: both tables carry a
  `commit=` link resolved by GitHub's blame, which follows a rename but not a
  split. A commit in the range that moves or splits
  `sound/hda/codecs/realtek/alc269.c` needs a new hop there. Without one, the
  symptom is the updater's mass-edit rail refusing that commit, never a wrong
  link: a stderr warning names it, and new rows are left `commit=""`.
- README tested table: grep the SSIDs in the range against it.

## Record the verdict

- Append the `### Triage (YYYY-MM-DD)` section to the hit comment with
  `gh api -X PATCH repos/<owner>/<repo>/issues/comments/<id> -F body=@file`.
  Keep the visible part short, because the issue accumulates one per tag:
  1. One bold verdict line.
  2. Findings that need action or change a watched or tested device, if any.
     Give each one bullet of a few sentences, with its commit link. This
     includes problems the check exposed in our own data.
  3. A table with one row per watch: watch, commit count, and a verdict of
     about a dozen words. Zero-hit watches can share a row that names each one.
  4. Everything else in a `<details><summary>Evidence</summary>` block: per-term
     counts, match paths, the sweep, and the blast-radius checks.
  5. The Claude footer.
- Touch `.github/kernel-watchlist.txt` only if the triage opened or closed
  an investigation, in the commit that does so. Don't add a term already
  covered by a broader one in the file: `alc287`
  already hits most Lenovo quirks. A redundant term doubles every future hit
  comment.
- Triage alone gets no CHANGELOG entry, because `.claude/rules/changelog.md`
  excludes research-log notes. A code fix the triage prompts is judged on its
  own merits.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…