把“解释 X”变成含代码的课程 skill Turns "explain X" to into a code-driven lesson
SaferSkills independently audited agent-teacher (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
When someone wants to understand a concept, definitions don't stick — running code does. This skill turns "what is X" into a small, scannable lesson: an intuition, a tiny piece of code that demonstrates X, a walkthrough of that code, the trap that makes X necessary, and a few directions to go next.
The user wants to build a mental model, not solve a task. Cues:
解释一下 闭包 / 什么是 CAP / 教我 monad / explain GIL / what is a futex我不太懂 generator / 这个 actor model 是啥 / i never got how async worksprocess 和 thread 区别 / mutex vs semaphoreIf the user is asking you to fix code that uses X, that's a debugging task, not a teaching task — answer the task directly and skip this skill.
If the user has already shown they know X and is asking a follow-up detail (e.g. "in Python, does the GIL also block during I/O?"), answer the detail directly. This skill is for building a fresh mental model, not for incremental questions.
Match the user's input language. Chinese in → Chinese lesson. English in → English lesson. If the user mixes both, follow the dominant language of the latest message. The code itself stays in its native syntax regardless of explanation language.
Default: in the conversation, as a structured markdown response. Concept learning is a back-and-forth — writing the whole lesson to a file fragments that flow.
Two exceptions:
/tmp/<slugified-concept>-pseudocode.<ext> as a sidecar. Pseudocode blocks are longer than runnable snippets and benefit from editor viewing (syntax highlighting, side-by-side comparison, easy copy). Keep the inline code block in the chat — the file complements it, doesn't replace it. Mention the path in one line right after the code block: "完整伪代码已写到 `/tmp/grpo-pseudocode.py`,方便在编辑器里看。"/tmp/<concept>.md and the code to a sibling file. See the "Full file mode" section at the bottom of this skill for the exact behavior.Read references/concept-to-language.md to choose the language that makes the concept cheapest to demonstrate. Honor the user's explicit language preference if stated. Quick mapping:
| Concept area | Default language | Why |
|---|---|---|
| General CS, OOP, algorithms, data structures | Python | Reads like pseudocode |
| Concurrency (channels, goroutines, async) | Go or Python asyncio | Concurrency primitives are first-class |
| Memory, pointers, ownership, undefined behavior | C or Rust | You can't show pointers in Python |
| Type systems, variance, ADTs, monads, HKT | TypeScript or Haskell | Needed to express the concept |
| Frontend, DOM, event loop, closures-in-the-browser | JavaScript | Native habitat |
| Numerical, ML, data | Python (numpy / PyTorch) | Ecosystem decides |
| Shells, processes, signals | Bash + C | The actual interface |
Use this exact spine: Intuition → Example → Walkthrough → Trap → Pointers → Test questions. The first five are the lesson; the test questions at the end turn the read into something the reader could be checked on. Don't skip parts; if one feels redundant for a particular concept, keep it but make it one line.
Read references/teaching-method.md for the full per-layer playbook (what good and bad versions of each layer look like, with examples).
One or two sentences. Lead with the problem the concept solves, not what it is. A metaphor is fine if it survives scrutiny.
The default is a 5–20 line runnable example: pasteable into a REPL, no external dependencies, prints visible output. This is the right form for language features (closures, generators), small algorithms (binary search, memoization), and APIs (regex, requests).
But some concepts cannot fit in runnable code — and trying to force them there is the failure mode. For these, switch to structured pseudocode (Mode B). Mode B has three flavors based on what the concept is about:
Flavor 1 — DL architectures and training algorithms. PyTorch syntax with tensor shape annotations on every line where shape changes. Marquee examples: Transformer block, MoE, GRPO, FlashAttention.
Flavor 2 — Protocols and state machines. Named participants (leader, follower), message arrows, state transitions. Marquee examples: Raft AppendEntries, TCP three-way handshake, OAuth flow.
Flavor 3 — Complex algorithms and data structures. Control flow with explicit invariants stated, plus a concrete trace through a small input. Marquee examples: B+ tree insert, union-find with path compression, quicksort.
All three flavors share:
FOR each token DO ….# pseudocode — illustrative, not runnable at the top.# [B, T, D]), participant state for protocols (leader.commitIndex 12 → 14), data state for algorithms (arr = [3, 1, 4, 1, 5] → [3, 1, 1] [4] [5]). State tracking is load-bearing, not decoration — without it the reader has to mentally re-derive what you should have shown.for, if, mask = ..., topk(...) must appear. That's the algorithm. Don't elide it.advantages = compute_grpo_advantages(rewards) is fine — do not expand a helper unless the helper is the concept.For algorithm concepts in Mode A (Flavor 3-shaped concepts that are still small enough to be runnable, e.g. binary search, mergesort): include a trace block right after the example code — run the algorithm on a concrete tiny input (5–10 elements) and show 3–6 intermediate states. The trace is often more lesson-bearing than the code itself. See references/code-style-for-teaching.md §11.
#### Which form to pick
| Signal | Form |
|---|---|
| Concept is a language feature, small algorithm, or single API | Runnable (Mode A) |
| Concept is a small algorithm where the trace teaches more than the code | Runnable (Mode A) + trace block |
| Concept needs a full model, optimizer, or dataset to demonstrate | Pseudocode (Mode B Flavor 1) |
| Concept is a published DL algorithm / architecture (GRPO, MoE, FlashAttention, Mamba) | Pseudocode (Mode B Flavor 1) |
| Concept is a distributed protocol (Paxos, Raft, 2PC) with multiple participants | Pseudocode (Mode B Flavor 2) |
| Concept is a complex data structure (B+ tree, red-black tree) where the invariant is the lesson | Pseudocode (Mode B Flavor 3) |
| Runnable version would exceed ~30 lines or need pip-installed deps the reader doesn't have | Pseudocode |
#### Code style rules (both modes)
user_age, gate_logits, expert_outputs — not u, g, x.reduce, write the for loop first then the reduce version. When teaching GRPO, show "what PPO does here" alongside "what GRPO does instead." The reader learns by diffing.print() is a teaching tool, not a smell. Show intermediate state with aligned labels.print(). # [B, T, D] → [B, T, n_experts] next to a line teaches more than three sentences.# WHY comment is worth ten # WHAT comments. Comment only on the non-obvious.try/except, no input validation, no type guards unless the concept is one of those.Read references/code-style-for-teaching.md for fuller examples of both modes, including a worked MoE pseudocode block.
Split the example code into 2–4 segments. For each segment: quote it, then say in one short paragraph what it's doing and why this segment is necessary. The reader should be able to read only the walkthrough and predict what each segment does.
The walkthrough is not a line-by-line narration ("this line assigns x to 5"). It groups lines into purpose units.
Show the bug the concept exists to prevent, or the wrong intuition newcomers reach for. Either:
for i in range(3): funcs.append(lambda: i) and being surprised all functions return 2. The reason is …"Pick whichever lands harder for the specific concept. One snippet plus one line of commentary is enough — this layer is a warning shot, not a tutorial.
Two or three bullets, each pointing at a deeper or adjacent concept. Do not expand them. The point of this layer is to give the reader a map, not another lesson.
End with 2–3 test questions at increasing difficulty. The point isn't to grade the reader — it's to give them concrete prompts that someone could pose to check this concept, with just enough hint to know where to look. Don't label them "interview questions" or frame an interview scenario; just present them as questions. The wording itself shows they're externally-shaped, not soft self-checks.
Format per question:
> Hint: underneath — a pointer to where the answer lives in the lesson, not the answer itself.A after grpo_advantages?")Do not give answers. If the reader replies with an attempt, walk through it then. Reading the question and feeling unsure is itself the teaching signal — it surfaces what's solid vs. shaky in the reader's understanding.
Read references/teaching-method.md for examples of good vs. bad test questions for closures, MoE, and other concepts.
Eight optional modules attach to the spine when the concept's nature warrants. They handle what a plain six-part lesson can't easily carry: canonical formulas, design choices, famous cousins, dependency chains, classic misconceptions, charts, and invariants the concept guarantees.
The framework was originally tuned for DL/ML concepts (where the heaviest enrichment use lives), but several fit broader CS naturally: data structures (state tracking as trace, design rationale, cousin matrix, prereqs, invariants), distributed protocols (state tracking as participant state, design rationale, visualization as sequence diagrams, invariants), complex algorithms (state tracking as trace, design rationale, invariants).
Concept-driven, not concept-default. Attention deserves 5; B+ tree deserves 4; tensor broadcasting deserves 1; closures deserve 0. If you're unsure whether an enrichment fits, skip it. Padding hurts more than missing helps.
Plain language features get the plain six-part spine. Don't force a cousin matrix onto closures or a design rationale onto generators — these are tools for designed-on-purpose components, not for language constructs.
| Module | Trigger condition | Where it attaches |
|---|---|---|
| Math tier (canonical formula or Big-O recurrence) | Concept has a formula practitioners write down | Between intuition and example |
| State tracking (shapes for DL, participant state for protocols, data trace for algorithms) | Mode B is selected | Example, walkthrough |
| Design rationale | Concept has 2+ designed-on-purpose choices worth justifying | Between walkthrough and trap |
| Cousin matrix | Concept has a famous "vs" cousin (BN vs LN, GRPO vs PPO, TCP vs UDP, …) | Pointers |
| Prerequisites + variants | Concept sits in a clear dependency chain | Pointers |
| Misconception list | Concept has 2+ classic misconceptions of equal prevalence | Trap expands from single-snippet to list |
| Visualization | A chart, state machine, or sequence diagram saves 200 words | Example or trap |
| Invariants | Concept is built around stated invariants (data structures, protocols, type systems) | Between walkthrough and trap |
Decision checklist (run after picking the lesson's Mode but before writing it):
Hard cap: no lesson uses more than 5 enrichments. Hard floor: if zero fire, deliver a plain six-part lesson — that's the normal case for language features and most simple algorithms.
Read references/enrichments.md for the per-module playbook with good/bad examples (DL and non-DL), decision rules, and a calibration table of which enrichments fire for which canonical concepts (attention, BN, MoE, Raft, B+ tree, …).
A plain six-part lesson should fit in one screen of focused reading — roughly 150–400 words of prose for intuition through pointers, plus the code blocks, plus 2–3 short test questions at the end.
A lesson with 2–3 enrichments fired can run to 400–700 words plus code blocks. This is fine — the extra words are paying for the design rationale, the cousin table, the prerequisite map, or the invariant list, all of which earn their space.
A lesson with 5 enrichments (attention or Raft is the canonical case) can run to 800–1200 words. At this length, consider splitting into multiple lessons (the user can ask follow-ups for the parts they want deeper).
If a concept is too big regardless (e.g. "explain the transformer architecture"), split it: deliver one lesson on the smallest meaningful sub-concept first, then offer "want me to do attention next, or positional encoding?" Don't try to compress a 3000-word concept into one pass.
Crisp, friendly, direct. Like a coworker drawing on a whiteboard, not a textbook. Avoid:
Use second person ("you") sparingly; it can feel preachy. Prefer describing what the code does.
// imagine some_func returns…, the example has failed. Make it runnable.async, don't also explain await-on-a-Promise vs await-on-a-coroutine. Pick one, finish it, then offer the next.There are two file-output behaviors. They are not the same.
When the example is pseudocode (Mode B), always write the code block to a sidecar file. Pseudocode blocks for architectures and training algorithms are typically 20–35 lines with dense shape annotations, and they are much easier to read in an editor with syntax highlighting than in a chat scroll.
/tmp/<slugified-concept>-pseudocode.<ext> (.py for PyTorch / Python, .ts, .rs, etc. based on the language).# pseudocode — illustrative, not runnable header as the inline block, plus a one-line concept name comment.For Mode A (runnable) lessons, do NOT write a sidecar by default. Short runnable code is more useful inline; the file would be redundant.
Trigger phrases: "save this" / "做成笔记" / "save as a doc" / "存下来" / "I want to keep this" / "write it to a file".
When triggered:
/tmp/<slugified-concept>.md using the same six-part structure (intuition → test questions)./tmp/<slugified-concept>.py etc.) so it can be opened or run independently. If the lesson was Mode B and a sidecar already exists, reuse it.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.