Every block below is real output from the scripts in the skill, run against a real 6.1 source tree and a 7.0 tree. The fact gate catches a made-up CONFIG_*. The diff gate stops a change that grew past what was asked. The regression test proves the gate can tell good from bad. The learn validator refuses a rule with no executable check. Version drift flags an API that vanished between kernels.
下面每一块都是 skill 里脚本的真实输出,对着一棵真实 6.1 源码树和一棵 7.0 树跑出来的。事实检查抓出编造的 CONFIG_*。diff 检查拦下改超了要求范围的改动。回归测试证明检查真能分好坏。学习验证器拒掉没有可执行检查的规则。版本漂移标出在内核之间消失的 API。
It's a skill, not a doc you read. You describe the task; it routes to the right subsystem modules, writes the code in kernel idiom, and ends with a [CLAIMS] block you verify against your own kernel tree.
它是个 skill,不是给你翻的文档。你描述任务,它路由到对应子系统模块、按内核地道写法出代码,末尾带一个 [CLAIMS] 块,你拿自己的内核树验。
Bind your tree once. Ask in plain language. The skill pulls the device-tree, interrupts and memory modules, writes the driver, and emits the claims below — every symbol then checked against your kernel (all 10 resolve here on a 7.0 tree). 绑一次树。用大白话问。skill 拉起设备树、中断、内存模块,写出驱动并给出下面的 claims——每个符号再拿你的内核核一遍(这里在 7.0 树上 10 个全过)。
# one-time: bind your kernel tree (per-machine, never in the repo) $ node ~/.claude/skills/linux-kernel-dev/scripts/kernel-tree.mjs add /path/to/your/kernel --default # in Claude Code, just describe the task: you ▸ write a platform driver for this SoC's ethernet MAC — get the registers and IRQ from the device tree, receive with NAPI, transmit with DMA # the skill loads device-tree + interrupts + memory, writes the driver, # and ends the answer with a [CLAIMS] block: [CLAIMS] api: platform_driver, devm_platform_ioremap_resource, platform_get_irq, request_threaded_irq, netif_napi_add, napi_schedule, dma_map_single symbol: net_device, napi_struct, sk_buff [/CLAIMS] # verify every cited API exists in YOUR kernel version: $ node ~/.claude/skills/linux-kernel-dev/scripts/fact_gate.mjs answer.md --tree /path/to/your/kernel ✓ symbol: platform_driver ✓ symbol: netif_napi_add ✓ symbol: dma_map_single … (10 symbols) [fact-check] clean — all 10 claim(s) resolved (exit 0) # then the kernel's own checkpatch, and build: $ bash ~/.claude/skills/linux-kernel-dev/scripts/checkpatch_gate.sh --tree /path/to/your/kernel my.patch
Already linked into ~/.claude/skills/? Then it's live in Claude Code — just start describing kernel work. The forty-three subsystem modules (interrupts / scheduler / memory / locking / runtime-pm / dma-mapping / filesystems / device tree / i2c / spi / gpio / usb / phy / mailbox / clocks / pinctrl / regulators / regmap / reset / pwm / clk-provider / pinctrl-driver / regulator-driver / networking / audio / camera / iio / thermal / watchdog / rtc / hwmon / led / input / power-supply / cpufreq / cpuidle / devfreq / dmaengine / dmaengine-provider / nvmem / mmc / mtd / iommu, plus a build reference) load only when your task hits them.
已经链到 ~/.claude/skills/ 了?那它在 Claude Code 里就是活的——直接描述内核活儿即可。四十三个子系统模块(中断 / 调度 / 内存 / 并发加锁 / 运行时电源 / DMA 映射 / 文件系统 / 设备树 / i2c / spi / gpio / usb / phy / 邮箱 / 时钟 / 引脚 / 供电 / regmap / 复位 / pwm / 写时钟控制器 / 写引脚控制器 / 写稳压器驱动 / 网络 / 音频 / camera / iio / 温控 / 看门狗 / rtc / hwmon / led / 输入 / 电源 / CPU 调频 / CPU 空闲 / 设备调频 / dmaengine / 写DMA控制器 / nvmem / mmc / mtd / iommu,外加一份构建参考)只在你的任务命中时才加载。
The answer carried a [CLAIMS] block. fact_gate.mjs greps each cited symbol / CONFIG / compatible against the real tree. The real ones pass; the invented ones are flagged on the spot. Exit code 1 means a content failure (a hallucination), not a broken gate.
答案带了 [CLAIMS] 块。fact_gate.mjs 把引用的每个符号 / CONFIG / compatible 拿真树 grep。真的过、编的当场标出。退出码 1 表示内容出错(幻觉),不是检查坏。
$ node scripts/fact_gate.mjs answer.md --tree linux-6.1 [fact-check] tree: linux-6.1 (--tree) ✓ config: CONFIG_OF ✗ HALLUCINATION config: CONFIG_THIS_DOES_NOT_EXIST_XYZZY ✓ symbol: devm_kzalloc ✗ HALLUCINATION symbol: devm_kzalloc_turbocharged ✓ symbol: platform_get_irq ✓ compatible: simple-bus ✗ HALLUCINATION compatible: vendor,totally-made-up-zzz [fact-check] FAIL — 3 claim(s) not found in tree (exit 1)
Every claim a module makes passes three tiers of sourcing — and they are not equally strong, so here is the honest boundary. 每个模块的每条断言都过三层来源 —— 三层强度不一样,所以这里把可信边界说清楚。
Every API / symbol / CONFIG is grepped against a real kernel source tree — it must resolve, and every deliberately-wrong corruption must not. Reproducible, this is the fact gate.每个 API / 符号 / CONFIG 都对真内核源码树 grep —— 必须查得到,故意写错的必须查不到。可复现,这就是事实检查。
Signatures, struct fields and the gotchas come from the kernel's own headers (include/linux/*.h) and Documentation/ — each module cites its source at the top.函数签名、结构字段、那些"坑"来自内核自己的头文件(include/linux/*.h)和 Documentation/ —— 每个模块顶部都标了出处。
A kernel knowledge base seeds which APIs a subsystem has — then every entry is cross-checked against the tree, which catches stale or renamed APIs (e.g. an _apply_state that got renamed).一个内核知识库提供"该讲哪些 API"的起点 —— 但每条都再拿真树复核,揪出过时/改名的 API(比如某个被改了名的 _apply_state)。
The honest boundary. Existence is machine-proven and reproducible. Semantics are read from authoritative headers / docs (cited), not runtime-tested. Coverage = the kernel versions you bind — version-sensitive notes say "check against your target tree." Re-verify any claim yourself: fact_gate.mjs <answer> --tree <your tree>.
诚实的边界。存在性是机器证明、可复现;语义是读权威头文件 / 文档写的(标了出处),不是运行时跑过验证;覆盖 = 你绑定的内核版本 —— 版本敏感处都标了"按目标树核"。任意一条都可自行复验:fact_gate.mjs <答案> --tree <你的树>。
No reimplemented linter — the gate wraps the checkpatch.pl that ships inside the bound tree, so the style rules track the kernel version exactly. Missing SPDX, spaces-for-tabs — caught.
不另写 linter——检查直接包装绑定树里自带的 checkpatch.pl,风格规则跟内核版本完全一致。缺 SPDX、用空格当 tab——都抓得到。
$ bash scripts/checkpatch_gate.sh bad.c --tree linux-6.1 [checkpatch-gate] linux-6.1/scripts/checkpatch.pl on bad.c bad.c:1: WARNING: Missing or malformed SPDX-License-Identifier tag in line 1 bad.c:3: WARNING: please, no spaces at the start of a line total: 0 errors, 2 warnings, 4 lines checked [checkpatch-gate] FAIL — checkpatch reported issues (exit 1)
Two kinds of damage survive a hunk-by-hunk read, because every hunk looks reasonable alone: the change grew past what was asked (a variable renamed in passing, an include block resorted), and things nobody asked for got added (one more module_param, a wrapper with a single call site). The other gates miss this by construction — checkpatch judges single lines, the fact gate judges symbols. None of them asks where this change should have stopped. Without --scope it reports skipped, never clean: with no declared boundary there is nothing to have crossed, and silence would read as approval.
有两类问题逐个 hunk 读 diff 时看不出来,因为每个 hunk 单看都合理:改超了要求的范围(顺手改的变量名、重排的 include),和加了没人要的东西(多一个 module_param、一层只有一个调用点的包装)。别的检查天生管不到这个——checkpatch 看单行,事实检查看符号,没有一条问「这次改动该到哪为止」。不给 --scope 时报 skipped 而不是 clean:没声明范围就无从判断越没越界,这种情况下沉默等于说没问题。
$ node scripts/diff_discipline.mjs --diff bsp-fix.patch --scope 'drivers/i2c/**' === diff discipline: 3 file(s), 2 area(s), 3 finding(s) ERROR out-of-scope drivers/spi/spi-bar.c:10 no --scope pattern covers this file WARN speculative-knob drivers/i2c/busses/i2c-foo.c adds module parameter "foo_retries" -- who sets it, and what breaks if it is wrong? WARN reformat-only drivers/i2c/busses/i2c-foo.h:12 2 line(s) differ only in whitespace The test is per line: can you point at the request that made this line necessary? "while I was in there" is not such a reason -- revert it. (exit 1)
Each case carries a known-good answer (gold) and deliberate corruptions. The runner asserts gold resolves and every corruption is caught — a self-degradation check. Coverage is tracked: if too few cases actually ran against a tree, the whole run is marked untrustworthy. 每条用例带一个正确答案(gold)和故意改坏的版本。runner 断言 gold 全过、且每个坏版本都被抓——自降解校准。覆盖率也记:真跑过检查的用例太少,整轮标为不可信。
$ node scripts/regression_test.mjs --tree linux-6.1 [regression] cases 3 · ran 3 · coverage 100% · tree linux-6.1 ✓ KV-001 gold✓ calibration✓ ✓ KV-002 gold✓ calibration✓ ✓ KV-003 gold✓ calibration✓ [regression] objective pass 3 · calibration fail 0 (exit 0)
When a trap is solved, /kernel-learn mints an atomic triple — a rule with an embedded [CLAIMS] check, a frozen case that fails before / passes after, and a registration. The validator is deterministic: a rule with a real check is accepted; a prose-only rule is rejected.
解决一个坑后,/kernel-learn 产出原子三件套——带 [CLAIMS] 检查的规则、一条建前 fail/建后 pass 的冻结用例、一次注册。验证器是确定性的:带真检查的规则收下,纯散文的规则拒掉。
$ node scripts/kernel_learn_validate.mjs --case KV-001 --rule rule-good.md --tree linux-6.1 [kernel-learn-validate] ✓ triple valid (gold resolves + traps all caught) — ok to land + register (exit 0) $ node scripts/kernel_learn_validate.mjs --case KV-001 --rule rule-no-check.md --tree linux-6.1 [kernel-learn-validate] triple invalid: ✗ rule text has no embedded [CLAIMS] block (no executable check → rejected) (exit 1)
After the objective checks settle the facts, seven fresh-context critics each score one axis — correctness, safety, design, testing, complexity, coding-style, completeness (aligned with Google's review dimensions). Safety carries the most weight and an error there fails the answer outright — in kernel code a sleep-in-spinlock is not a style nit. 客观检查把事实定下后,七个 fresh-context 打分员各评一轴——正确性、安全、设计、测试、复杂度、编码风格、完整性(对应 Google 的 review 维度)。safety 权重最大,这一轴出 error 直接判 fail——内核里持 spinlock 睡眠不是小毛病。
The panel was run for real on tests/eval/demo-answer.md — a platform sensor-driver probe with deliberate defects. Each critic scored its one axis in a fresh context; the numbers below are their actual verdicts, not mock-ups.
打分面板真的对 tests/eval/demo-answer.md(一个故意留缺陷的平台传感器驱动 probe)跑了一遍。每个 critic 在独立上下文里只评自己那一轴;下面是它们的真实裁决,不是摆拍。
Real APIs (fact-gate clean), but two runtime bugs and two unchecked NULL returns.API 都真(fact-gate 干净),但两个运行时 bug + 两处返回值没查 NULL。
A sleeping call (devm_ioremap_resource) inside spin_lock_irqsave — Forbidden #1. Vetoes the answer.spin_lock_irqsave 里调睡眠函数 devm_ioremap_resource——Forbidden #1 原子态睡眠,一票否决。
A temperature sensor that binds to no framework (hwmon/thermal/iio); the read is dead state.温度传感器没绑任何框架(hwmon/thermal/iio),读到的值成死状态。
KUnit was feasible (the conversion is pure) but there are zero tests, and unchecked returns leave no error path to test.换算是纯逻辑、本可 KUnit,却零测试;返回值没查也让错误路径无从测起。
Short and flat; one dense line fuses an MMIO read, a magic-number conversion, and an assignment.短而扁平;一行把 MMIO 读、魔数换算、赋值挤在一起。
Would pass checkpatch — SPDX, tabs, K&R, devm. Two lines hit 95 cols (over 80 preferred, under the 100 wall).能过 checkpatch——SPDX、tab、K&R、devm。两行 95 列(超 80 首选,未到 100 告警线)。
Task scope covered, CLAIMS clean, but all three fallible calls go unchecked — the failure branch is missing.任务范围覆盖、CLAIMS 干净,但三个会失败的调用全没查——失败分支整条缺失。
This is the whole point: a 53.9 average would look like a "needs work" pass, but a sleep-in-spinlock is a crash — so safety's veto is what actually protects the kernel. 这正是重点:53.9 的均分看着像"还行、待改",但 spinlock 里睡眠是会崩的——safety 的一票否决才是真正护住内核的那道闸。
Point the detector at two version trees and it runs the gold claims against each, then reports what changed. ion_alloc resolves in 6.1 but not 7.0 — flagged ROTTED, machine-found. That is the signal to version-tag the knowledge instead of letting it rot silently.
把检测器对准两棵版本树,它在每棵上跑 gold 断言,再报出变化。ion_alloc 在 6.1 查得到、7.0 查不到——标 ROTTED,机器找出来的。这就是信号:该给这条知识注明它适用哪些内核版本,而不是让它悄悄过期。
$ node scripts/version_drift.mjs --trees linux-6.1,linux-7.0 [version_drift] trees: 6.1.141 → 7.0.0 (old → new) 1 drift found — version-tag the matching knowledge: ⚠ ROTTED symbol:ion_alloc [ 6.1.141:✓ 7.0.0:✗ ] (exit 1)
It's a multi-file skill (SKILL.md + scripts/ + references/) — install the whole directory, not just SKILL.md, then restart Claude Code. Binding a kernel tree is what turns on fact-gate verification against your exact version.
它是多文件 skill(SKILL.md + scripts/ + references/)——装整个目录,不是只 SKILL.md,然后重启 Claude Code。绑内核树是为了让 fact-gate 能对你的确切版本验证。
# 1. install the skill — link the folder into Claude Code, then restart it $ ln -s /path/to/sky-skills/skills/linux-kernel-dev ~/.claude/skills/linux-kernel-dev (or copy the whole dir — it's multi-file, not just SKILL.md) # 2. bind your kernel source tree (per-machine; turns on fact-gate) $ node ~/.claude/skills/linux-kernel-dev/scripts/kernel-tree.mjs add /path/to/your/kernel --default # 3. confirm it's wired $ node ~/.claude/skills/linux-kernel-dev/scripts/kernel-tree.mjs list linux 7.0 /path/to/your/kernel (default) # now in Claude Code, just describe kernel work — modules load on demand.
Nothing here is mocked. Bind a kernel tree and the same checks run against your exact version. 这里没有一处是假的。绑一棵内核树,同样的检查就对着你的确切版本跑。