Add advanced eBPF tutorials 51–54 and tutorial agent skills (#220)

* Add targeted TCP connection quarantine tool

* Document TCP quarantine workflow

* Refresh package indexes before CI install

* Document TCP quarantine namespace scope

* Require BPF events for TCP iterator

* Add production fsession latency tracer

* Document fsession latency workflow

* Reject empty fsession CLI values

* Preserve successful fsession exit status

* Document fsession deadline regression test

* Drain fsession events before summary

* Document fsession PID and shutdown semantics

* Simplify fsession polling control flow

* Add bounded BPF egress pacer tutorial

* Test queued packet cleanup on signal

* Document the BPF egress pacer

* Polish and review the BPF egress pacer

* Refactor egress pacer option parsing

* Add executable image inspector lesson

* Build the exec image inspector in CI

* Document executable image inspection

* Handle re-exec chains in the image inspector

* Polish exec image inspector guidance

* Reduce exec inspector wait complexity

* Rewrite the egress pacer tutorial

* Rewrite the exec image inspector tutorial

* Polish the exec image inspector tutorial

* Correct the egress pacer tutorial

* Make the exec tutorial Chinese natural

* Fix egress tutorial prose checks

* Finish the exec tutorial style pass

* Clarify exec tutorial runtime evidence

* Polish exec tutorial scope wording

* Rewrite the egress pacer tutorial for readers

* Regenerate tutorial indexes

* Teach the egress pacer component by component

* Use standard Markdown in the egress tutorial

* Strengthen the egress pacer tutorial narrative

* jiji

* Use positive framing in the egress tutorial

* Rewrite the exec image inspector tutorial

* Rewrite the TCP quarantine tutorial

* Add the egress pacer lifecycle diagram

* Refresh TCP tutorial indexes

* Add the exec image inspection flow diagram

* Use one source directory link

* Rewrite the fsession latency tutorial

* Add fsession feature background

* Add BPF qdisc feature background

* Add TCP iterator feature background

* Add exec inspection feature background

* Require feature background in tutorial openings

* Polish fsession background prose

* Simplify repository tutorial skills

* Update exec inspector tooling revisions

* Restructure tutorials 51-54 following advanced guideline

- Update SKILL.md with strict section ordering and "why" requirements
- Rewrite README.zh.md for tutorials 51-54:
  - Add background sections explaining why traditional approaches fail
  - Move compilation/execution sections after code analysis
  - Add high-level mechanism explanation before code
  - Use paragraph style instead of bullet lists

* Consolidate skill guidelines and remove duplicates

- Update write-bpf-production-tutorial skill to reference 47, 48, 49
- Add structure requirements section with "Why" section emphasis
- Remove duplicate advanced-tutorial-guidelines.md (use scripts/guideline_advance.md instead)

* Rewrite English READMEs 51-54 to match Chinese structure

Restructure all four English tutorials to match their Chinese counterparts:
- Add "Why this approach is needed" sections explaining traditional limitations
- Add high-level mechanism sections before code
- Move compilation/execution sections after code analysis
- Add environment requirements tables
- Use consistent section ordering across all tutorials

* Regenerate TOC after tutorial title changes

Run generate_toc.py to sync SUMMARY and README files with
updated tutorial titles from the restructuring.

* Regenerate compatibility tables after title changes

---------

Co-authored-by: LinuxDev9002 <i@littlefisher.me>
This commit is contained in:
云微
2026-07-19 19:34:09 -07:00
committed by GitHub
parent d055a0833f
commit ca1267d82a
57 changed files with 9014 additions and 385 deletions

View File

@@ -1,70 +1,104 @@
---
name: bpf-tutorial-writing-style
description: Repository-local prose and bilingual checklist for drafting, rewriting, or reviewing advanced bpf-developer-tutorial README.md and README.zh.md files. Use to match the readable voice of 49-hid and the useful depth of 47-cuda-events while preserving implementation facts, complete source, commands, evidence, caveats, and references.
description: Style checklist for English and Chinese bpf-developer-tutorial README files. Use while drafting or reviewing a tutorial so it reads like the established series, preserves technical detail, and presents complete source clearly.
---
# BPF Tutorial Writing Style
Use this Skill for writing quality only. Use `$write-bpf-production-tutorial` for build, KVM, exact-source checks, and PR steps.
Read the complete guidelines first:
- [Advanced tutorial guideline](https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/scripts/guideline_advance.md) for tutorials 40+
- [Basic tutorial guideline](https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/scripts/guideline_basic.md) for tutorials 0-39
Read all three references before drafting or reviewing:
Then read the English and Chinese versions of `47-cuda-events`, `48-energy`, and `49-hid` as style references. Learn their teaching rhythm and level of detail without copying their topic or wording.
1. [Advanced tutorial guidelines](https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/.agents/skills/bpf-tutorial-writing-style/references/advanced-tutorial-guidelines.md) contains the complete project-provided requirements and must remain intact.
2. [Repository house style](https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/.agents/skills/bpf-tutorial-writing-style/references/repository-house-style.md) explains how to learn from existing tutorials without copying their defects.
3. [Prose and bilingual checklist](https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/.agents/skills/bpf-tutorial-writing-style/references/prose-and-bilingual-checklist.md) carries the relevant eunomia.dev writing discipline into this repository.
## Document Structure (strictly follow guideline)
Also read the English and Chinese versions of `47-cuda-events` and `49-hid` in full. Existing lessons are examples of rhythm, depth, and teaching order, not templates. Verified code, real output, primary sources, and the user's requirements remain authoritative.
For advanced tutorials (40+), follow this exact section order:
## Write for a reader
1. **Title**: `# eBPF 教程:[Topic Description]` or `# eBPF Tutorial by Example: [Topic Description]`
Start with a short, truthful scene the reader can picture. Show one observable problem or useful action, then raise the technical question that the lesson will answer. Keep one example, packet, event, task, device interaction, or failure as the thread through the article, so the opening scene returns naturally when the code and output are explained.
2. **Introduction**: Brief intro with a concrete problem scenario. Highlight significance and what readers will learn. Link to complete source once here.
Treat the scene as a teaching device, not a license to write fiction. Do not invent a named operator, customer, outage, deployment, benchmark, urgency, or result. If the implementation is a bounded lab tool, make the scene a bounded lab situation and let the real mechanism make it interesting.
3. **Background / Why This Approach**:
- Explain WHY this approach is needed
- List traditional/alternative approaches and their limitations (e.g., killing process, firewall rules, user-space tools)
- Explain what eBPF/the new kernel feature enables that traditional approaches cannot
- State when the feature entered Linux (kernel version + commit if relevant)
Use oral English, familiar words, and connected sentences. Write natural Chinese independently from the same facts. Chinese punctuation should be restrained: prefer one or two connected sentences that carry one technical thought over a row of short, period-heavy statements. Prefer causal explanation over inventories. A paragraph should tell the reader what happens, why it happens, and what that enables.
4. **High-Level Mechanism**:
- Explain HOW the eBPF feature/tool works at a high level BEFORE showing code
- Describe the overall flow: what happens in kernel, what happens in user space, how they interact
- Use diagrams for complex flows with branches, waits, ownership transfers, or 3+ dependent states
Prefer positive, concrete statements throughout the tutorial. Explain what the hook, program, loader, command, or test does and which scope it covers. Rewrite `not`, `do not`, `cannot`, `will not`, `不要`, `不能`, `不会`, `并非`, and `别` whenever the same fact has an accurate positive form, and remove every double negative. Keep at most one compact boundary paragraph near the end, limited to two sentences, instead of distributing failure, limitation, and safety warnings through the article.
5. **Code Implementation**:
- First introduce the overall processing logic
- Show complete source code for each component (header, BPF program, user-space loader)
- After each complete code block, explain the key parts with paragraph style (not bullet lists)
- Focus on logic and advanced features, not basic syntax
Keep the actor close to the action. Start important sentences with a concrete component, use active voice when ownership matters, connect short facts through cause and effect, and give `this`, `it`, `这` and `它` an unmistakable referent. Put the claim before detailed evidence, use verbs instead of abstract noun phrases, and end a sentence on the new fact the reader should remember.
6. **Additional Concepts** (if needed): Deeper explanation of specific features, edge cases, or semantics
Do not write like a paper, specification, PR description, release note, test log, or compliance report. Build and KVM evidence belongs in compilation and execution, where it should support a claim instead of becoming the article's main plot.
7. **Compilation and Execution** (AFTER code, not before):
- Build commands
- Run commands with examples
- Expected output with explanation
- Environment requirements table (kernel version, config, privileges, architecture)
## Draw the relationship when prose starts carrying a graph
8. **Summary**: Key points, scope boundaries, future extensions
Use a small technical diagram when the running example crosses at least three dependent states, branches and later rejoins, waits and retries, transfers ownership, or connects one component to several consumers. The diagram should let the reader see a relationship that would otherwise require rereading a paragraph. Keep a simple linear filter, a single hook, or a two-step command in prose.
9. **Call to Action**: Repository and website invitation (as blockquote)
Build diagrams from verified code and tests. Prefer code identifiers and short labels, one clear direction, restrained color, and enough whitespace to read the figure at ordinary README width. Introduce the figure with the concrete packet, event, task, or device interaction already used in the story, then explain the decisive branch or ownership change after the image. A diagram supports the narrative; it does not replace the source walkthrough.
10. **References**: Links to kernel commits, upstream selftests, documentation
Keep the editable DOT, Mermaid, or SVG source beside the rendered PNG. Use descriptive alt text and a canonical absolute GitHub target for the image. A language-neutral figure can serve both README files when code identifiers carry the flow; prose-heavy labels call for matched Chinese and English assets.
## Tell one useful story
## Keep the source readable
- Open with a concrete situation that the example can reproduce and the question it answers.
- Near the first mention of eBPF, use one natural sentence to say what eBPF is and why it fits this problem.
- Introduce the relevant kernel subsystem and new feature when the running example needs them. State when the feature entered Linux and what it enabled.
- Follow one packet, event, task, or device interaction through kernel space and user space. Explain what happens, why it happens, and what the next step enables.
- Present the whole flow before detailed code. A small diagram helps when the reader must track a branch, wait, retry, ownership transfer, or at least three dependent states.
Include complete core source exactly as implemented. Teach one component at a time: introduce its role, present its source inline, and immediately explain the important logic before moving on. Do not hide source in `<details>` and do not separate a long source dump from all of its explanation.
## Explain the "Why" thoroughly
Do not simplify code, insert ellipses, or rewrite comments. Present complete source in ordinary Markdown fenced code blocks without HTML synchronization markers, then verify it against the real file.
This is critical. The Background section must explain:
- What problem you're solving
- What traditional approaches exist (killing process, firewall rules, user-space tools like `ss --kill`, sampling, etc.)
- Why each traditional approach doesn't work well (race conditions, incomplete coverage, performance overhead, etc.)
- What the eBPF approach enables that wasn't possible before
Place one complete-source callout near the opening and link only the lesson's GitHub directory. Let the directory serve as the entry point for source, build files, fixtures, and tests, while later component sections name individual files beside their complete code blocks.
Example pattern for the "Why" section:
> **杀掉进程**是最直接的想法,但一个进程往往维护着多条连接,杀进程会中断所有业务流量。
> **防火墙规则**可以阻止新连接,但对已建立的连接无能为力。
> **用户态工具**如 `ss --kill` 依赖 `/proc/net/tcp` 遍历和注入 RST 报文,但这种方式有竞态问题。
> **内核态方案**才能真正解决这个问题。BPF 迭代器可以在持有适当锁的情况下遍历内核的套接字表...
Use canonical GitHub absolute URLs for every other Markdown link, even when the target belongs to the current lesson. Never use `./`, `../`, or another host. If no stable GitHub URL exists, leave the text unlinked. This rule overrides link patterns in older lessons and the website call to action in the advanced guidelines.
## Sound like a tutorial
Keep local infrastructure private. Do not name workspace paths, shared lab repositories, VM instances, copy routes, caches, or agent trace locations in a tutorial or PR description. Retain only public reproducibility facts such as architecture, kernel version and commit, configuration, commands, and captured output.
- Use familiar words, direct verbs, and connected paragraphs. Attraction comes from the problem and mechanism rather than promotional language.
- Prefer positive descriptions of what the example does. Put remaining limits and safety boundaries in one short paragraph near the end.
- Use prose for the main explanation and lists for genuinely parallel items.
- Keep each paragraph focused on one job. Connect facts through cause, sequence, or contrast instead of listing them like a specification.
- Write Chinese naturally from the same facts instead of translating English sentence by sentence. Use restrained punctuation and spaces between Chinese text and Latin letters or numbers.
- Keep technical names, code identifiers, commands, numbers, output, versions, and references exact.
## Keep scope honest
Use this Chinese paragraph only as a voice reference for connected rhythm, restrained symbols, and technical density:
Describe what the implementation actually provides. A bounded lab command is a bounded lab command. Do not inflate it into a daemon, controller, production scheduler, security product, or operational platform.
> libbpf 是一个 C/C++ 的 eBPF 用户态加载和控制库,随着内核一起分发,几乎已经成为 eBPF 用户态事实上的 API 标准,libbpf 也支持 CO-RE(Compile Once – Run Everywhere) 的解决方案,即预编译的 bpf 代码可以在不同内核版本上正常工作,而无需为每个特定内核重新编译。
State requirements and explain cleanup through the normal lifecycle. Collect failure conditions, limitations, and safety boundaries into one compact paragraph of at most two sentences near the end. Move low-level kernel provenance into a compact requirements or reproducibility note.
## Teach from complete source
## Final reader check
- Introduce one component, show its complete source in an ordinary Markdown fence, then explain the important logic before moving to the next component.
- Keep source byte-exact. Preserve comments and commands; use focused excerpts only after the complete block.
- Use neither `<details>` nor HTML synchronization markers.
- Link to the complete lesson once through its GitHub directory. Avoid an opening catalog of individual files.
- Every Markdown link uses an absolute `https://github.com/...` target. Omit a link when no stable GitHub target exists.
- Public prose contains no local path, shared test repository, VM name, copy route, cache, prompt, model, agent, or trace detail.
Read the finished lesson in order once. The reader should be able to answer:
## Finish the lesson
- What concrete problem does this lesson solve?
- How does one packet or event move through kernel and user space?
- Which eBPF mechanism makes that possible?
- Which code deserves close attention?
- How do I build, run, and recognize success?
- What does the captured output prove?
- Where does the example stop?
- Show copyable build and run commands, representative real output, and what that output proves.
- State kernel, configuration, privilege, architecture, and hardware requirements that affect the example (use a table).
- End with a compact scope boundary, summary, repository invitation, and primary references.
- Keep the English and Chinese files aligned on structure, facts, source, commands, output, limits, and references while allowing each language to sound natural.
Revise if the reader instead encounters a code wall, repeated disclaimers, a validation transcript, dense spec-sheet paragraphs, literal Chinese translation, or a scenario larger than the tool. This reader check is a judgment pass, not a reason to add reviewers or models.
The final read should answer: what problem is solved, how one event moves through the system, which eBPF mechanism makes it possible, which code matters, how to run it, what success looks like, and where the example stops.

View File

@@ -1,80 +0,0 @@
# Blog Guidelines for Advanced eBPF Tutorials
This document outlines the key patterns and requirements for writing advanced eBPF tutorials. Advanced tutorials focus on complex eBPF programs, tools, or features that extend beyond basic concepts. They require a deeper understanding of eBPF and kernel interactions.
The audience for advanced tutorials includes developers, system administrators, and security professionals with intermediate to advanced eBPF knowledge. The goal is to provide in-depth explanations of advanced eBPF topics and practical examples that readers can apply in real-world scenarios.
The key point in tone: Using oral English, clear and simple words and short sentence, make it attractive and easy to read, do not make it like a paper. Not too much fancy words, try to be attracive.
You should also include all the details and information I provide to you. do not simplify or change any of them, you just need to regorganize them in a more attractive way as a tutorial blog.
## starting with a clear and descriptive title
Begin with a clear and descriptive title:
```
# eBPF Tutorial by Example: [Advanced Topic]
```
Kick off with a brief intro to the advanced eBPF topic you're covering, and the example or tool you'll discuss. Highlight its significance and how it extends beyond basic concepts. Let readers know what they'll learn and why it's important.
## Incroduction to the concept, tool and Background
(Come up with a better session title)
Provide an overview of the specific eBPF programs, tools, or features you'll discuss. Explain their purpose, use cases, and the key eBPF features or kernel events involved. Focus on aspects that are crucial for advanced understanding.
## High-Level Code Analysis
Dive into the kernel-mode eBPF code and user-space code, focusing on high-level concepts rather than basic syntax.
Always include the full code as it is first. then break down the key parts.
Try to avoid using too much list, make it more like a story.
Follow the steps:
1. First, introduce The overall processing logic in both kernel and user space.
2. Then break down the kernel-mode eBPF code, include
- How the eBPF program is structured.
- Key eBPF functionalities utilized.
- How the code interacts with kernel events.
Do not make them a list, make them some paragraphs, you can also quote some code snippets to explain the key parts of the code if needed, focus on the logic and features used in advanced eBPF development. Don't make it too long, but make sure it is informative enough and you explain everything a advanced eBPF developer wants to know.
3. Then briefly explain the user-space code
Aim to help readers grasp how the code works without getting bogged down in basic details.
## Any more detailed concepts or features explanation
If there are other information or features that are important to understand the code, you can add them here.
## 5. Compilation and Execution
Provide instructions on compiling and running the eBPF programs, noting any advanced configurations or dependencies. Include commands and what readers should expect as output. Typically, you can run `make` in the relevant directory in the tutorial repository to build the code.
Include links to complete source code and resources:
- **Repository:** <https://github.com/eunomia-bpf/bpf-developer-tutorial>
## 6. Summary and Call to Action
Wrap up by summarizing the key points. Emphasize the advanced concepts covered and encourage readers to apply this knowledge. Invite them to explore more examples and tutorials, as one paragraph:
> If you'd like to dive deeper into eBPF, check out our tutorial repository at <https://github.com/eunomia-bpf/bpf-developer-tutorial>.
## reference
You should include the important references and resources that used in the tutorial. If this is from other sources like kernel sample or tools, make sure to include them here and clearly mention them in the tutorial.
## Additional Guidelines
- **Clarity:** Use simple language and short sentences to explain complex ideas. But the information should be complete and detailed.
- **Focus on Advanced Concepts:** Assume readers have basic eBPF knowledge; skip elementary explanations.
- **Engagement:** Encourage readers to think critically and engage with the material.
- **Consistency:** Keep a consistent style and formatting throughout.
- **Code Formatting:** Ensure code snippets are well-formatted and highlight key parts. Do not change or simplify any of the code and commands, keep them as they are.
- **Proofreading:** Double-check for errors and ensure technical accuracy.
- **Accessibility:** Make the content valuable for readers with advanced expertise, avoiding unnecessary simplifications.

View File

@@ -1,119 +0,0 @@
# Prose and bilingual checklist
This checklist carries the relevant eunomia.dev writing discipline into advanced eBPF tutorials. It is self-contained and does not depend on a global or external Skill.
Use it as a reader-focused editing guide, not as a reason to add review rounds. Technical fidelity is mandatory. Numeric paragraph ranges and stylistic labels are diagnostic signals that still require judgment.
## Fidelity is the first gate
- **Must fix:** Any code, command, captured output, number, version, requirement, limitation, negative result, cleanup behavior, reference, or scope-bearing qualifier from the supplied material is missing or changed.
- Preserve technical names and project names. Do not replace them with vague pronouns across paragraphs.
- Treat numbers as claims. State what was measured, under which conditions, and what the result does or does not prove.
- Avoid absolute words such as “always,” “never,” “cannot,” and “impossible” unless the implementation or a primary source proves the boundary.
- Do not invent output, benchmark numbers, PIDs, paths, errors, production uses, or performance conclusions.
- Reorganize for teaching, but do not simplify away technical information. During a rewrite, compare the final text against the entry version from the end backwards and account for every removed paragraph.
- Preserving a fact does not require repeating it. Put each requirement, failure behavior, cleanup rule, and limitation at the one point where it helps the reader most.
## Voice and argument
- Use oral, direct English with familiar words and short connected sentences. Write as an experienced developer explaining a working tool, not as a paper, merge report, release note, or test log.
- Open with a short, truthful story or concrete scenario that the implementation can reproduce. Show an observable symptom, action, packet, event, task, device interaction, or failure, then raise the technical question instead of answering everything in the first paragraph.
- Carry the same concrete thread into the mechanism, code, and output sections. The opening should pay off when the reader sees where the event goes and how the result is produced.
- Do not fabricate a persona, customer, production incident, deployment, benchmark, urgency, or result. Avoid “In this tutorial, we will explore,” generic eBPF history, product promotion, and an abstract-style contribution list.
- Let each section answer the question raised by the previous one. A useful progression is problem, background, whole-system flow, complete code, focused walkthrough, deeper concept, compilation and execution, limits, summary, and references.
- Give each paragraph one primary job. If a paragraph establishes context, explains a mechanism, reports evidence, and states a limitation at once, split it.
- Prefer active voice and concrete actors. Name the hook, BPF program, map, callback, loader, fixture, command, or kernel rather than using “it,” “this,” “the approach,” or “the result.”
- Replace spec-sheet prose with causal explanation. If three neighboring sentences can be reordered without changing the paragraph, connect each fact to what it enables or why it matters.
- Avoid fancy or promotional words, clickbait, exclamation marks, vague superlatives, hollow calls to action, and self-praise. Attraction should come from a concrete problem and a mechanism the reader can reuse.
- Do not overuse lists. Use prose for the implementation story and lists only when parallel items become easier to scan.
- Do not let provenance become the plot. Kernel commits, guest versions, CI details, and test matrices belong in a compact reproducibility note unless the lesson is specifically about them.
- Match the scenario to the tool. A small fixture, lab command, or feature demonstration can be valuable without being described as a production service.
## Diagram decision and presentation
- Add a diagram when it makes a real relationship visible: three or more dependent state changes, a branch/retry loop, ownership transfer, or one component feeding several later actions.
- Keep a simple linear filter, single attach point, or two-step command in prose. The figure count follows teaching value rather than article length.
- Derive every node, edge, label, and branch from implementation or test evidence. A diagram carries technical claims and receives the same fidelity review as prose.
- Prefer a reviewable DOT, Mermaid, or SVG source and commit it beside the rendered PNG. Use deterministic rendering so another agent can reproduce the asset after a code change.
- Use short labels, code identifiers, one dominant reading direction, restrained color, and text that remains legible at README width.
- Introduce the packet, event, task, or device interaction before the figure. Explain the important branch, retry, or ownership change immediately after it.
- Use descriptive alt text and a canonical absolute GitHub image target. Keep both README files aligned on the same figure and conclusion; use paired assets when language-specific labels materially help readers.
- Update the diagram in the same change whenever implementation or prose changes its state sequence, ownership, branch condition, or cleanup path.
## Positive and concrete sentences
- Use a positive statement of behavior or scope. Write “The loader observes one child that it creates” instead of “The loader does not monitor every exec on the system.” Write “The example implements one aggregate FIFO” instead of opening with the scheduler policies it lacks.
- Rewrite `not`, `do not`, `does not`, `cannot`, `will not`, `不要`, `不能`, `不会`, `并非` and `别` whenever an accurate positive form exists. Remove double negatives and paragraphs built from consecutive negative sentences.
- Keep the supported scope exact while using positive wording. “The example focuses on one child” describes the implemented behavior without implying that system-wide monitoring already exists.
- Collect failure conditions, unsupported behavior, limitations, and safety boundaries near the end in one paragraph of at most two sentences. The main narrative should stay with the working path.
- Start important sentences with a concrete actor such as the hook, BPF program, map, callback, loader, fixture, kernel, or command. Keep that subject close to its verb and prefer active voice when ownership or sequencing matters.
- Connect three or more short declarative sentences through cause, contrast, or sequence. A pair of short sentences can create emphasis, while a longer note-like run should become a causal paragraph.
- Give vague referents a name. Replace an unclear `this`, `it`, `they`, `这`, `它` or `这种方式` with the component or mechanism it denotes.
- Put the claim or practical meaning before a block of numbers, counters, or output. The reader should know what the evidence demonstrates before reading the evidence.
- Prefer direct verbs over nominalizations and filler. Use “the callback reads,” “the loader attaches,” and “the test verifies” instead of “performs a read,” “conducts attachment,” or “provides verification.”
- Place known context near the sentence opening and the new result near the end. This topic-to-stress order helps adjacent sentences form one path instead of a fact catalog.
Treat this wording as a negative example:
> 这个例子故意只做聚合 FIFO,没有 class、公平调度、ECN、burst 控制。用它做实验可以,但别往物理网卡上挂,也别当生产调度器。
The paragraph defines the example through missing features and repeated warnings, so the useful mechanism disappears behind negation. Rewrite it around the implemented path and a concrete learning setting:
> 这个例子用一条聚合 FIFO 展示 skb 所有权、发送时序和 qdisc 清理,适合在 veth、TAP 或 IFB 这类受控接口上观察完整流程,更完整的调度器可以在此基础上加入 class、公平调度、ECN 和 burst 控制。
Apply the same repair in English. Replace a paragraph built from “no classes,” “not production,” and “do not attach” with the mechanism the reader can run, the controlled setting that fits it, and the natural extensions that follow.
## Paragraph and sentence checks
- English paragraphs usually work best at 40–90 words. Inspect every paragraph above 110 words. Three consecutive paragraphs above 90 words are **Must fix**.
- Chinese paragraphs usually work best at 120–260 Chinese characters. Inspect every paragraph above 320 characters. Three consecutive paragraphs above 260 characters are **Must fix**.
- The ranges are diagnostic tripwires, not quotas. Short transitions and longer indivisible mechanism explanations are allowed.
- Keep a sentence's subject near its verb. Split long modifiers, dangling introductions, and sentences that make the reader hold several clauses before reaching the action.
- Avoid weak openings such as “It is,” “There is,” and “This is” when a concrete subject is available.
- Do not stack three or more short note-like sentences. Connect cause, mechanism, and consequence.
- Avoid a pair of neighboring negative sentences when positive wording can carry the same facts. Reserve the compact final boundary paragraph for the remaining limits.
- Cut filler such as “in order to,” “utilize,” “it is important to note that,” “due to the fact that,” “in terms of,” and “with respect to.” Prefer direct verbs.
- Do not use spaced English em dashes (` — `) or Chinese em dashes (`——`) in prose.
- Do not join independent clauses with semicolons. Use two sentences or a conjunction.
- Use colons only to introduce a list, code block, or table. Rewrite claim-colon-evidence and Chinese noun-phrase-colon openings as sentences.
## Code and evidence presentation
- Present full core source exactly as it exists before excerpting it again for explanation. Use ordinary Markdown fenced code blocks with no HTML markers, then require the workflow Skill's read-only `--check` mode to pass against the complete source inventory. Never silently shorten functions, replace blocks with ellipses, translate comments, or “clean up” commands.
- Teach one component at a time. Introduce the file's role, present its complete source inline, and immediately explain the parts that matter before starting the next component.
- Never hide source in `<details>` and never place several complete files in one uninterrupted dump followed by a distant walkthrough. Long examples need stronger component boundaries and local explanations, not collapsed code.
- Explain what advanced developers need to know: program type, attach point, context restrictions, helper or kfunc semantics, map ownership, state lifetime, concurrency, verifier constraints, event/control path, error handling, and cleanup.
- Keep build and run commands copyable. Explain prerequisites before the command and interpret real output after it.
- Label volatile fields and distinguish demonstrations, functional tests, and benchmarks.
- Use one opening complete-source callout that links only to the lesson directory. Treat that directory as the entry point for implementation, build files, fixtures, and tests; name individual files as code labels next to their complete source blocks instead of listing file links in the opening.
- Use canonical GitHub absolute URLs for every Markdown link, including links to the current lesson. Reject every `./`, `../`, or non-GitHub target. If no stable GitHub URL exists, do not add a link. This repository rule overrides link examples in precedents and the advanced guideline's website call to action.
- Keep local infrastructure and agent state private. Never publish workspace paths, shared lab repository or VM names, host-to-guest copy routes, cache locations, prompt stores, or trace paths. Public reproducibility may include architecture, kernel version and commit, configuration, commands, and captured output.
## Natural Chinese
- Compose Chinese from the facts and paragraph role, not from English sentence order. The two languages may use different sentence and paragraph boundaries.
- Keep punctuation restrained. When several clauses explain one subject, mechanism, or consequence, connect them naturally with commas instead of turning each clause into a separate short sentence. Prefer one or two complete sentences per ordinary paragraph; do not create a choppy sequence of periods.
- Do not imitate “short English sentences” mechanically in Chinese. A cohesive Chinese sentence may carry the concept, mechanism, compatibility boundary, and motivation together when they belong to one thought.
- Still split a sentence when its subject drifts, the causal relation becomes unclear, or the reader must hold unrelated facts at once. Fewer periods are a voice preference, not permission for an unreadable run-on sentence.
- Translate ordinary concept nouns consistently. Keep proper nouns, product names, code, commands, file names, function names, and genuine terms of art in English.
- Do not begin a Chinese prose sentence with an English common noun. Avoid English clause splicing and glossary-style prose where every other concept stays in English.
- Use full-width Chinese punctuation. Put a half-width space between CJK text and Latin letters or digits, such as “64 个事件” and “eBPF 程序.”
- Write table headings in Chinese. Translate ordinary prose inside comments only when the code block is illustrative; when the block claims to be complete source, preserve it byte-for-byte in both languages.
- Read every Chinese paragraph aloud. Rewrite literal translations, English word order, and stiff phrases that a developer would not use in conversation.
Use this paragraph as a compact Chinese voice reference. Learn its connected rhythm, restrained symbols, technical density, and direct statement of motivation; do not copy its subject matter into unrelated lessons:
> libbpf 是一个 C/C++ 的 eBPF 用户态加载和控制库,随着内核一起分发,几乎已经成为 eBPF 用户态事实上的 API 标准,libbpf 也支持 CO-RE(Compile Once – Run Everywhere) 的解决方案,即预编译的 bpf 代码可以在不同内核版本上正常工作,而无需为每个特定内核重新编译。我们希望尽可能的保持与 libbpf 的用户态 API 以及行为一致,尽可能减少应用迁移到 Wasm (如果需要的话)的成本。
The sample is not a factual source. Do not copy `libbpf`, CO-RE, Wasm, API claims, compatibility claims, or any other technical content from it unless the lesson's fact pack independently requires that content. Leakage from the sample into an unrelated lesson is a **Must fix** failure.
## Bilingual consistency
- Keep the same macro structure, examples, complete code payload, commands, output, claims, numbers, caveats, limitations, summary, and references in both files.
- Corresponding headings should promise the same content, but they do not need literal translations.
- A near-perfect line-for-line prose translation is a review smell. Confirm that each language reads naturally even when that changes sentence or paragraph boundaries.
- When one version changes a fact, example, figure, command, code block, output, or limitation, update the other in the same pass.
## Final reader check
After reading in order, an intermediate or advanced eBPF developer should be able to explain the real problem, the kernel/user-space flow, why the advanced capability is needed, how the core code works, how to build and run it, what the captured output proves, and where the example stops. If the reader remembers only a feature name, a code wall, repeated caveats, or a validation transcript, revise the narrative.

View File

@@ -1,48 +0,0 @@
# Repository house style
New advanced lessons should feel at home beside `src/47-cuda-events/` and `src/49-hid/`. Read both English/Chinese README pairs in full. Use `47-cuda-events` as a depth reference for an end-to-end tool and `49-hid` as the stronger reference for voice, pacing, and teaching through a concrete device problem.
These lessons are precedents, not perfect templates. Do not copy their unsupported claims, stale version language, inconsistent punctuation, or unnecessary feature catalogs. Verified implementation facts and current project rules win whenever a precedent differs.
Read at most one additional completed bilingual lesson when it offers a closer subsystem pattern. For networking, good candidates include `20-tc`, `41-xdp-tcpdump`, `42-xdp-loadbalancer`, and `50-tcx`. Choose by teaching need, not by directory number.
## Build one continuous story
Open with a concrete situation the reader can picture. Name the small tool or example and the useful result, but do not preview every version, counter, failure case, and test in the opening.
Give enough background to explain why the hook or kernel subsystem matters. Then introduce the whole kernel/user-space path before individual functions. Keep returning to the same packet, event, device, or failure so adjacent sections feel causally connected.
Present complete core source exactly as required by the advanced tutorial guidelines, but organize it by component. Introduce one file, show it inline, explain its important behavior, and only then move to the next file. Never hide source in `<details>` and never make readers cross several complete files before reaching the explanation.
After the source, explain the BPF structure, attach point, state and ownership, relevant helpers or kfuncs, kernel interaction, user-space lifecycle, error handling, and cleanup. Spend words on advanced constraints and surprising behavior. Do not explain ordinary C syntax.
Compilation and execution should show copyable commands, representative real output, and what that output means. Put public kernel provenance, commit IDs, and compatibility data in a compact requirements or reproducibility paragraph. Do not name local workspaces, shared lab repositories, VM instances, copy routes, caches, agent traces, or the PR's validation history.
End with an honest boundary, a short summary, the required invitation, and primary references.
## Lessons from the 53-egress-pacer rewrite
The first `53-egress-pacer` draft was technically accurate but still failed as a tutorial. It:
- packed the scenario, kernel version, algorithm, counters, conflict behavior, and test result into the opening;
- gave the reader only a few setup paragraphs before several hundred lines of source;
- repeated the same conflict, signal, cleanup, KVM, or safety caveat in the introduction, implementation, run section, and limitations;
- read like an artifact report because validation details received more emphasis than the mechanism;
- called a fixed-duration lab demo a production or operational tool without matching CLI capabilities;
- wrote Chinese by following English sentence order.
The rewrite kept all four complete source files, commands, output, versions, failure paths, and limits. It replaced the invented production story with an honest lab scope and followed one skb through ownership and timing. Reader review then exposed a structural problem: collecting the files before their explanations made the tutorial read like a design document. The corrected method places each complete file beside its component explanation, as tutorials 47 and 49 do.
Reuse the corrected method, not exact section counts. Shrink overloaded openings, give the reader one useful mental model, and alternate complete component source with nearby explanation. Keep each technical fact, but place it once where the reader is ready for it.
## Preserve modern correctness
- Use captured output and identify fields that vary across runs.
- Source version, performance, deployment, adoption, and upstream-history claims.
- State the minimum kernel, config, privilege, architecture, and hardware requirements.
- Explain at least one meaningful failure or boundary path and relevant cleanup.
- Distinguish a functional KVM run from a benchmark.
- Avoid unsupported claims such as “production-ready,” “safe,” “negligible,” or “complete visibility.”
- Keep Markdown consistent. Use full-width Chinese punctuation and spaces between CJK text and Latin letters or digits.
English and Chinese must share the same promise, section progression, source, commands, output, facts, caveats, summary, and references. Natural expression matters more than sentence-for-sentence symmetry.

View File

@@ -1,127 +1,77 @@
---
name: write-bpf-production-tutorial
description: Create or revise a tested bilingual bpf-developer-tutorial lesson from the implementation and real runtime evidence. Use for tutorial scope, pinned Claude Opus 4.5 authorship, README drafting, technical flow diagrams, exact source inclusion, host builds, KVM tests, supervised completion, and PR preparation. Pair with bpf-tutorial-writing-style for prose decisions.
description: Write or rewrite one bilingual bpf-developer-tutorial lesson with pinned Claude Opus 4.5, then verify the result against the implementation. Use when creating README.md and README.zh.md, preserving full source, testing the example, or preparing tutorial changes for review.
---
# Write a BPF Tutorial
Keep the workflow small. Claude Opus 4.5 writes all tutorial prose. Codex supervises source fidelity, actual completion, bilingual consistency, validation, and publication. Do not add other writers, reviewer panels, task ledgers, reviewer databases, or extra process files.
Use `$bpf-tutorial-writing-style` for the finished prose. Keep this workflow small: prepare reliable source material, let one pinned writer complete both languages, then check what it actually wrote.
Invoke `$bpf-tutorial-writing-style` before writing or reviewing README prose.
## 1. Prepare the lesson
## Pinned writer
Read these inputs before writing:
Use the exact model ID `claude-opus-4-5-20251101` through Claude Code. Never use `opus`, `latest`, a default model, a fallback model, or another provider for tutorial prose. If this exact model is unavailable, stop and report the block instead of substituting another writer.
- `scripts/guideline_advance.md` for tutorials 40+, `scripts/guideline_basic.md` for tutorials 0-39;
- both README files from `src/47-cuda-events`, `src/48-energy`, and `src/49-hid` as style references;
- the lesson's implementation, headers, Makefile, fixtures, and tests;
- the current README pair when revising an existing lesson;
- primary upstream sources for versions and feature semantics.
Use exactly one non-interactive Claude invocation for one lesson. Require Opus to edit the existing README files in place, one specific sentence or paragraph at a time and in document order. Each Edit operation must have a narrow target. It must not generate a replacement article and overwrite the file as a whole. It must preserve the existing code-block positions while revising the prose around each block, first completing natural Chinese and then matching English from the same facts.
Collect the facts the reader needs: the problem, why traditional approaches fail, the kernel/user-space flow, feature versions, requirements, commands, real output, cleanup, limits, and references. Keep every claim grounded in the code, tests, captured output, or a primary source. Preserve an existing draft before a from-scratch rewrite.
The initial prompt must contain the complete task, source-fidelity rules, style rules, and final audit checklist. Opus must not ask Codex or the user a question, pause for confirmation, return a partial progress report, or stop after one language or one section. It may return only after both README files have been rewritten from beginning to end and it has run its own baseline comparison and formatting checks. Do not split the main rewrite into planned paragraph batches, switch models, or let Codex fill in prose afterward.
Build and run the example when the environment supports it. Use `$test-bpf-tutorial-kvm` for kernel features that need the repository's KVM environment. Runtime details support the tutorial; local workspace paths, VM names, shared repositories, caches, prompts, and agent traces stay private.
A typical non-interactive invocation is:
## 2. Structure requirements
```bash
claude -p \
--model claude-opus-4-5-20251101 \
--effort high \
--permission-mode acceptEdits \
--allowedTools 'Read,Edit,Grep,Glob,Bash(git show *),Bash(git diff *),Bash(git status *)' \
--output-format json
```
For advanced tutorials (40+), follow this exact section order as defined in `$bpf-tutorial-writing-style`:
Give Opus access only to the lesson, its implementation and tests, the selected precedents, these repository-local Skills, and read-only baseline inspection through `git show` and `git diff`. Tell it to edit only the English and Chinese README pair and never commit, push, or publish.
1. **Title + Introduction**: Concrete problem scenario, link to source
2. **Background / Why This Approach**: Explain traditional approaches and their limitations, then what eBPF enables
3. **High-Level Mechanism**: How the feature works before showing code
4. **Code Implementation**: Complete source blocks, then paragraph explanations
5. **Additional Concepts** (if needed)
6. **Compilation and Execution**: AFTER code analysis, not before
7. **Summary + Call to Action**
8. **References**
## 1. Prepare the fact pack and technical draft
The "Background / Why" section is critical. It must explain:
- What traditional approaches exist
- Why each doesn't work well
- What the eBPF approach enables
Codex prepares the complete input before invoking Opus. Read the entry README pair, implementation, tests, Makefile, captured output, and primary upstream references. Read these bilingual precedents in full:
## 3. Let Opus write
- <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/47-cuda-events> for end-to-end depth;
- <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/49-hid> for an approachable teaching voice;
- at most one closer completed lesson when it contributes a subsystem-specific pattern.
Claude Opus writes all reader-facing tutorial prose. Use the exact model ID `claude-opus-4-5-20251101`. Stop if that model is unavailable instead of substituting another model.
Build a private fact pack that accounts for every mechanism, number, version, requirement, failure path, cleanup behavior, limitation, output field, and reference that the final lesson must retain. Include useful verified background from source code and primary upstream material. More context is helpful only when it is source-grounded; do not pad the pack with plausible but unverified history, adoption, performance, or production claims.
Use one non-interactive invocation for the complete English and Chinese pair. The prompt stays short and names only:
Prepare a complete technical draft before Opus writes. For an existing lesson, the entry README pair is the initial draft: repair factual gaps and add verified missing context without polishing the voice. For a new lesson, write a direct, comprehensive bilingual technical draft from the fact pack. Completeness and traceability matter more than style at this stage. Keep the fact pack private and do not add planning files to the repository.
- the two target README files;
- `scripts/guideline_advance.md` or `scripts/guideline_basic.md`;
- `$bpf-tutorial-writing-style`;
- `src/47-cuda-events`, `src/48-energy`, and `src/49-hid` as style references;
- the request to read the implementation and write both files completely before returning.
Write down two private working sentences as part of the fact pack: who the reader is, and what they should be able to explain or run at the end.
Do not paste a second checklist, paragraph plan, fact inventory, or review rubric into the prompt. Add a technical fact only when it is unavailable in the repository.
Choose an honest scope. A lesson may teach a small operational tool or a focused kernel feature. Do not call a lab demo production-ready, and do not invent a production story that the CLI, output, and tests cannot support.
Run Claude from the repository root with the pinned model and permission to read the repository and write the two README files. Opus does not commit or push.
Decide once whether a technical diagram materially improves the lesson. A diagram earns its place when the reader must track at least three dependent state changes, a branch or retry loop, ownership across kernel and user space, or one source that affects several downstream components. A short linear filter or one-step attachment usually reads better as prose.
## 4. Check the result
Codex prepares technical diagrams from the verified fact pack before the Opus prose pass. Prefer a reviewable text source such as Graphviz DOT or Mermaid, or a directly maintained SVG, and commit that source beside the rendered PNG. Keep one language-neutral diagram when code identifiers carry the meaning; use paired Chinese and English assets only when prose labels are essential. Technical flowcharts come from code and tests rather than generative illustration.
Inspect both files and the diff instead of trusting the model's final message. Confirm that:
Render the asset deterministically and record a reproducible command in the fact pack. Use a descriptive image name, readable text at normal README width, restrained color, and a clear branch or ownership direction. Published Markdown uses descriptive alt text and a canonical absolute GitHub image target such as `https://github.com/eunomia-bpf/bpf-developer-tutorial/raw/main/src/<lesson>/<diagram>.png`. Give Opus the finished asset and source so it can introduce the diagram, connect it to the running example, and explain the important branch immediately afterward.
- both languages are complete and tell the same technical story;
- the opening reads like a tutorial rather than an abstract or feature list;
- there is a "Why" section explaining traditional approaches and their limitations;
- the high-level mechanism is explained BEFORE code sections;
- compilation/execution is AFTER code analysis;
- every core source file appears once in a complete ordinary Markdown fence;
- code, commands, output, versions, requirements, cleanup, and limits agree with the repository;
- the opening source link points only to the lesson directory;
- every published link is an absolute `https://github.com/...` URL;
- no local infrastructure, prompt, model, agent, or trace detail appears in public text.
## 2. Verify the implementation
Check source blocks with the bundled `sync-source-blocks.py`, then run `git diff --check`, the lesson build, its tests, and the relevant runtime test. Treat a functional run as a functional run rather than a benchmark.
Build on the host. Use `$test-bpf-tutorial-kvm` for load, attach, and runtime behavior when the host kernel cannot run the feature safely. Exercise the normal path, one meaningful failure or boundary path, and cleanup. Record the commands, guest kernel version and commit, and real output needed by the README.
Read the finished pair once as an intermediate eBPF developer. If a concrete problem remains, give Opus a short defect list in the same session and let it revise the whole pair before returning. Keep prompts, responses, partial drafts, and failed runs; never delete real conversation or agent history.
Do not turn the README into a validation transcript. Runtime provenance supports the tutorial, but the reader-facing mechanism remains the story.
## 3. Give the complete pack to Opus
Give pinned Opus the entry pair, the complete technical draft, the fact pack, implementation and evidence, and the project-provided advanced tutorial guidelines through `$bpf-tutorial-writing-style`. The initial prompt must explicitly separate authoritative lesson facts from voice-only examples. Opus may reorganize and rewrite the supplied facts, but it must not introduce technical content from a style sample or precedent unless that content already appears in the fact pack.
The lesson must start from one short, truthful scene that the implementation can reproduce, then follow one packet, event, task, device interaction, or failure through the whole kernel/user-space path. Use the scene to raise the technical question before naming every mechanism, requirement, counter, and limitation. Never invent a customer, outage, production deployment, performance result, or tool capability to make the opening sound important.
Include the complete core source exactly as implemented, then walk through the important mechanisms. Tell Opus explicitly to use repeated local edits in document order and to continue without returning until the last paragraph of the second language is complete. Replacing the complete README in one write is a workflow failure even when the final prose looks acceptable.
Follow the selected precedent's component rhythm. Introduce one component, present its complete source inline, and explain its important logic before moving to the next component. Do not hide source in `<details>` or collect every file into one uninterrupted source dump. The source must remain searchable, copyable, and byte-exact.
Explain advanced eBPF behavior, not ordinary C syntax. Keep build, run, expected output, requirements, summary, and primary references. Explain cleanup as part of the normal mechanism instead of turning it into a warning section. Compress failure conditions, limitations, and safety boundaries into one short paragraph of at most two sentences near the end.
Use one opening complete-source callout whose only target is the lesson directory at `https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/<lesson>`. The directory is the single entry point for implementation files, the `Makefile`, fixtures, and tests; introduce individual filenames as code labels beside their complete blocks instead of turning the opening into a file-link catalog.
Use canonical GitHub absolute URLs for every other Markdown link. Never publish a `./` or `../` target or a link to another host. If no stable GitHub URL exists, omit the link. This repository rule overrides link examples in older lessons and the advanced guideline's website call to action.
Do not publish local infrastructure details. Keep workspace paths, shared lab repository names, VM names, host-to-guest copy steps, cache locations, and agent trace paths out of the README and PR description. Public reproducibility text may state the architecture, kernel version and commit, required configuration, commands, and captured output.
Opus must write Chinese as Chinese, using the voice sample and rules in `$bpf-tutorial-writing-style`, then write natural English with the same promise, structure, source, commands, evidence, and limits. It must not translate sentence by sentence. It must finish both files in the same lesson session.
## 4. Supervise actual completion
Do not accept Opus's final message as evidence that the work is complete. Inspect the files and diff. Confirm that both README files changed, every requested prose paragraph was actually rewritten, every source file still appears exactly once, and code, commands, captured output, versions, requirements, failure behavior, cleanup, limitations, and references remain intact.
For a full rewrite, compare prose outside fenced blocks with the entry version. Unchanged titles, tables, commands, output, and reference entries may be intentional. Unchanged explanatory paragraphs are evidence that the rewrite is incomplete unless the user explicitly exempted them. Inspect diff hunk distribution as well: changes concentrated only at the opening or ending do not satisfy a paragraph-by-paragraph rewrite.
When the lesson contains a diagram, inspect the rendered image as well as its source. Confirm that every node and edge follows the implementation, both languages introduce the same figure and draw the same conclusion, the PNG remains legible at README width, and the absolute GitHub image target points to the committed asset.
Codex performs this postcondition check after the one complete rewrite. If it finds a concrete defect, reject Opus's self-report and send one exact defect list back to the same pinned-model session. Opus must fix every listed issue without asking questions and rerun the final checks. This supervised correction is not permission to draft the lesson in batches: the first invocation must still attempt the entire Chinese and English pair before returning.
Codex may point out omissions, contradictions, awkward passages, broken links, or failed checks, but Opus must make every reader-facing prose revision. After the supervised Opus correction, Codex may apply a deterministic non-prose correction such as canonicalizing a verified link target, normalizing line endings, or restoring a source block byte-for-byte from its real file. It must not use this exception to rewrite wording, repair missing explanation, or introduce facts.
Preserve the model response, failed run, partial diff, prompt, and session history. Never delete, truncate, overwrite, or clean real conversation history, agent traces, prompts, partial runs, or failed runs.
## 5. Run one reader review
Read both files from top to bottom as an intermediate eBPF developer. Fix the text when:
- the opening reads like an abstract, specification, PR description, or test report;
- a large code wall arrives before the reader has a useful mental model;
- setup, conflicts, signals, KVM provenance, or limitations interrupt the main mechanism;
- a section catalogs facts without explaining cause and effect;
- the scenario promises a tool more capable than the implementation;
- Chinese follows English word order or switches languages unnecessarily;
- the reader reaches the end remembering only a feature name or validation transcript.
For a rewrite, compare the finished pair with the entry version once. Confirm that code, commands, captured output, versions, requirements, cleanup, the compact final boundary, and primary references remain accurate. Failure and limitation details may be condensed into the required two-sentence ending instead of surviving as a catalog. Every other removed passage should be repetition, stale framing, or material that moved to a better place. Word counts, heading counts, and repeated-term counts can expose bloat, but they are diagnostics rather than targets.
This is the normal review gate. Keep the pinned Opus session as the only prose editor. Codex reports concrete defects and reruns deterministic checks; Opus revises the affected paragraphs. The exact model identity is required by the workflow, but it is not evidence of quality. Only the finished artifact and passing checks are evidence.
## 6. Validate and publish
Check every complete-source block in the English and Chinese pair:
```bash
python3 .agents/skills/write-bpf-production-tutorial/scripts/sync-source-blocks.py \
--repo "$(git rev-parse --show-toplevel)" \
--readme src/<lesson>/README.md \
--readme src/<lesson>/README.zh.md \
--expected-source src/<lesson>/<tool>.bpf.c \
--expected-source src/<lesson>/<tool>.c \
--check
```
Repeat `--expected-source` for each complete shared header. Use ordinary Markdown fenced code blocks without HTML markers. Copy complete source from the real file, then run the checker; it is deliberately read-only.
Run `git diff --check`, the lesson build, the relevant host tests, the KVM runtime test, and repository documentation checks. Re-render every diagram from its committed text or vector source and confirm that the generated PNG matches the committed asset. Inspect the final diff for unintended files. Commit and push the repository-local Skills and tutorial changes only after these checks pass. Do not merge unless the user asks.
Stop after the reviewed local result unless the user asks to commit, push, or update a PR.