Capabilities · real output能力 · 真实输出

Not a promise.
Here is it running.
不是承诺。
这是它真在跑。

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。

Watch it catch a hallucination看它抓幻觉 The architecture看架构
6
Components组件
·
7
Scoring axes打分轴
·
100%
Case coverage用例覆盖
·
3
Hallucinations caught抓到幻觉
How you use it你怎么用它

One sentence in Claude Code → verified kernel code.在 Claude Code 里一句话 → 验过的内核代码。

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] 块,你拿自己的内核树验。

How you use it — five steps 1 Describe task描述任务 2 Load modules加载子系统模块 3 Answer + [CLAIMS]答案 + [CLAIMS] 4 Verify vs your tree对你的树验证 5 checkpatch + buildcheckpatch + 编译
Steps 1–3 happen in your Claude Code chat. Steps 4–5 are deterministic commands you run locally — the answer is checked against your tree, not taken on faith. 第 1–3 步在你的 Claude Code 对话里发生。第 4–5 步是你本地跑的确定性命令——答案拿你的树核过,不是听它一面之词。
Worked example · a NIC driver实操 · 一个网卡驱动

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,外加一份构建参考)只在你的任务命中时才加载。

01 · Objective check01 · 客观检查

The fact gate catches a made-up CONFIG.事实检查当场抓出编造的 CONFIG。

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)
Where the facts come from事实怎么验证的

Names are machine-proven; usage is sourced from authoritative headers & docs.名字的真假是机器证明的;用法的对错是读权威源写的。

Every claim a module makes passes three tiers of sourcing — and they are not equally strong, so here is the honest boundary. 每个模块的每条断言都过三层来源 —— 三层强度不一样,所以这里把可信边界说清楚。

1 · Existence — machine-verified1 · 存在性 —— 机器验证

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 —— 必须查得到,故意写错的必须查不到。可复现,这就是事实检查。

2 · Semantics — authoritative source2 · 语义 —— 权威源

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/ —— 每个模块顶部都标了出处。

3 · Coverage — seeded, then checked3 · 覆盖 —— 起点 + 复核

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 <你的树>

02 · Coding style02 · 代码风格

checkpatch runs your kernel's own rules.checkpatch 跑你内核自己的规则。

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)
03 · Change boundary03 · 改动边界

It reads the diff as a whole, not hunk by hunk.它把 diff 当整体看,不是一个 hunk 一个 hunk 看。

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)
04 · Regression + self-degradation04 · 回归 + 自降解校准

It proves the gate can tell good from bad.它证明检查真能分好坏。

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)
05 · Learning loop05 · 学习循环

No executable check, no rule.没有可执行检查,就不准建规则。

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)
06 · Scoring panel06 · 打分面板

Seven specialists, safety weighted highest.七个专家,safety 权重最高。

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 睡眠不是小毛病。

Scoring panel axis weights: correctness 28, safety 22, design 13, testing 12, complexity 9, coding-style 8, completeness 8 correctness · 28% safety · 22% design · 13% testing · 12% complexity · 9% style · 8% complete · 8% overall = .28·correctness + .22·safety + .13·design + .12·testing + .09·complexity + .08·coding-style + .08·completeness safety error → fail, regardless of totalsafety 出 error → 直接 fail,不看总分
Axis weights. Each critic runs in a fresh context and scores only its lane; an aggregator blends them, with a safety veto. 各轴权重。每个打分员在独立上下文里只评自己那一轴;汇总器加权合成,safety 有一票否决。
07 · Scored, for real07 · 真打一次分

Seven critics, one answer, real scores.七个 critic,评同一个答案,真实分数。

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 在独立上下文里只评自己那一轴;下面是它们的真实裁决,不是摆拍。

# tests/eval/demo-answer.md — sensor_probe() 节选 s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); // 返回值没查 NULL spin_lock_init(&s->lock); spin_lock_irqsave(&s->lock, flags); s->base = devm_ioremap_resource(&pdev->dev, res); // 睡眠调用在 spinlock 里! s->last = readl(s->base) * 9 / 5 + 32; // 读+换算挤一行;IS_ERR 没查 spin_unlock_irqrestore(&s->lock, flags); return 0; // 无错误路径

correctness

48
weight 28%

Real APIs (fact-gate clean), but two runtime bugs and two unchecked NULL returns.API 都真(fact-gate 干净),但两个运行时 bug + 两处返回值没查 NULL。

safety VETO

22
weight 22% · 一票否决

A sleeping call (devm_ioremap_resource) inside spin_lock_irqsave — Forbidden #1. Vetoes the answer.spin_lock_irqsave 里调睡眠函数 devm_ioremap_resource——Forbidden #1 原子态睡眠,一票否决。

design

60
weight 13%

A temperature sensor that binds to no framework (hwmon/thermal/iio); the read is dead state.温度传感器没绑任何框架(hwmon/thermal/iio),读到的值成死状态。

testing

70
weight 12%

KUnit was feasible (the conversion is pure) but there are zero tests, and unchecked returns leave no error path to test.换算是纯逻辑、本可 KUnit,却零测试;返回值没查也让错误路径无从测起。

complexity

80
weight 9%

Short and flat; one dense line fuses an MMIO read, a magic-number conversion, and an assignment.短而扁平;一行把 MMIO 读、魔数换算、赋值挤在一起。

coding-style

88
weight 8%

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 告警线)。

completeness

65
weight 8%

Task scope covered, CLAIMS clean, but all three fallible calls go unchecked — the failure branch is missing.任务范围覆盖、CLAIMS 干净,但三个会失败的调用全没查——失败分支整条缺失。

weighted = .28·48 + .22·22 + .13·60 + .12·70 + .09·80 + .08·88 + .08·65 = 53.9
but safety error → overall FAIL (veto, regardless of total)但 safety 出 error → 总评 FAIL(一票否决,不看总分)

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 的一票否决才是真正护住内核的那道闸。

08 · Version drift08 · 版本漂移

It found ion_alloc vanished between 6.1 and 7.0.它发现 ion_alloc 在 6.1 到 7.0 之间没了。

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)
Quickstart三步装好

Get it running in three commands.三条命令装好。

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.

Bring your own tree and run it.自带内核树,跑跑看。

Nothing here is mocked. Bind a kernel tree and the same checks run against your exact version. 这里没有一处是假的。绑一棵内核树,同样的检查就对着你的确切版本跑。

Browse the scripts看脚本 Back to architecture回到架构