problem-description
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseProblem Description — Interactive Step-by-Step Walkthroughs
问题描述 — 交互式分步演练
Overview
概述
Generate a self-contained HTML page that explains a technical problem using:
- Concrete data — real names, real numbers, culturally appropriate context (e.g., Thai names for Thai users)
- Manual step-through navigation — ,
Next →,← Previousbuttons. Reader controls pace.↻ Reset - Visual state changes — at each step, the right thing highlights and the reader can point at it
- Color-coded narration — info / warn / error / success / magic boxes explaining what fires + WHY
Core principle: The reader should be able to point to any specific element at each step and say "yes I understand why this is in this state right now."
生成一个独立的HTML页面,通过以下方式解释技术问题:
- 具体数据 — 真实名称、真实数字、符合文化背景的场景(例如针对泰国用户使用泰语姓名)
- 手动分步导航 — 、
Next →、← Previous按钮,由读者控制节奏↻ Reset - 视觉状态变化 — 每一步中,对应元素会高亮,读者可以指向该元素
- 颜色编码说明 — 信息/警告/错误/成功/关键提示框,解释触发的操作及其原因
核心原则: 读者在每一步都应能指向任意特定元素,并说出“我理解为什么它现在处于这个状态”。
Output location — REQUIRED (do this, don't default elsewhere)
输出位置 — 强制要求(必须遵守,不得默认其他位置)
The finished must land inside the project/workspace the user has open in their
editor. Identify that project from the workspace the user is working in — not from your
own current working directory, which on some harnesses (e.g. Antigravity) is an agent
scratch/sandbox dir that is different from the user's project. Save it to:
.html— where<project-root>/docs/problem-description/<name>.htmlis the user's open project. Create<project-root>if missing (docs/problem-description/).mkdir -p=<name>(diagram) orYYYY-MM-DD-<topic>-walkthrough(tables).<topic>-explained
This is the rule most often dropped on a long read, and the one harnesses get wrong:
- Do NOT write it to your agent scratch/sandbox/working directory (e.g. Antigravity's
). That hides the file from the user.
~/.gemini/antigravity/brain/<id>/scratch/ - Do NOT drop it in the project root or under a generic name like .
walkthrough.html - Resolve to the actual open project (e.g.
<project-root>), never a literalC:\Repo2\my-app\docs\problem-description\…placeholder.<project-root>
Verify-and-move — mandatory final action. Harnesses often ignore a "save here" instruction
and write to their own default location anyway. So after writing the file, get its absolute
path and check it is inside the open project's . If it landed
anywhere else — a scratch/sandbox/temp dir, the project root, or a generic filename — move it
to now (create the folder first).
Exception: if the user specified an explicit path, honor that path and skip the move. The
skill is not done until the file is in the right place; then report its final absolute path.
(If no project is open, or your harness genuinely cannot write into the project, save to the
session scratchpad, report the absolute path, and tell the user to move it.)
docs/problem-description/<project-root>/docs/problem-description/<name>.html生成的文件必须保存在用户编辑器中打开的项目/工作区内。从用户当前工作的工作区识别该项目——不要使用你自己的当前工作目录,在某些环境(如Antigravity)中,该目录是Agent的临时沙箱目录,与用户项目不同。保存路径为:
.html— 其中<project-root>/docs/problem-description/<name>.html是用户打开的项目根目录。若<project-root>目录不存在则创建(使用docs/problem-description/命令)。mkdir -p格式为<name>(用于图形式演练)或YYYY-MM-DD-<topic>-walkthrough(用于表格形式演练)。<topic>-explained
这是长文档中最常被忽略的规则,也是环境最容易出错的地方:
- 请勿将文件写入Agent的临时沙箱/工作目录(例如Antigravity的),这会让用户找不到文件。
~/.gemini/antigravity/brain/<id>/scratch/ - 请勿将文件直接放在项目根目录,或使用这类通用名称。
walkthrough.html - 将解析为实际打开的项目路径(例如
<project-root>),绝不要保留C:\Repo2\my-app\docs\problem-description\…占位符。<project-root>
验证并移动 — 强制最终操作:环境经常忽略“保存到此处”的指令,自行写入默认位置。因此,写入文件后,获取其绝对路径并检查是否位于打开项目的目录下。如果文件被保存到了其他位置——临时沙箱/临时目录、项目根目录,或使用了通用文件名——立即将其移动到(先创建目录)。例外情况:如果用户指定了明确路径,则遵循该路径并跳过移动操作。只有当文件处于正确位置时,本技能才算完成;之后需报告文件的最终绝对路径。(如果没有打开的项目,或你的环境确实无法写入项目,则保存到会话临时目录,报告绝对路径并告知用户自行移动。)
docs/problem-description/<project-root>/docs/problem-description/<name>.htmlArchitecture — one engine, plug-in mode packs
架构 — 单引擎+插件式模式包
A generated walkthrough is assembled at generation time from single-source references
into ONE self-contained (no build, no external assets):
.htmlwalkthrough.html = references/walkthrough-engine.html (§ the shared engine)
+ references/mode-<name>.html (§ ONE chosen mode pack)
+ references/term-drilldown.html (§ the drawer, optional)
+ authored scenes[] + GLOSSARY (the bootstrap)- The engine owns the step loop, navigation, palette tokens, the canonical nested narration, the 5 SVG markerheads,
:root, andRENDER_HOOKS. Never edit it to add a mode.modeRenderers - A mode pack registers exactly one renderer — — plus its content DOM and state CSS. Each pack is verified by assembly, not by opening it raw.
modeRenderers['<name>'] = {registry, clear, <setters>, assertRegistryComplete} - Assembly is a script: does the splice deterministically;
scripts/assemble-walkthrough.pyis the mandatory post-assembly self-test (the no-build safety net).scripts/check-walkthrough.py
生成的演练文档在生成时从单一源引用组装为一个独立的文件(无需构建,无外部资源):
.htmlwalkthrough.html = references/walkthrough-engine.html (§ 共享引擎)
+ references/mode-<name>.html (§ 选定的一个模式包)
+ references/term-drilldown.html (§ 术语抽屉,可选)
+ authored scenes[] + GLOSSARY (引导代码)- 引擎负责步骤循环、导航、调色板令牌、标准嵌套说明、5种SVG标记头、
:root和RENDER_HOOKS。绝不要编辑引擎来添加新模式。modeRenderers - 模式包仅注册一个渲染器————以及对应的内容DOM和状态CSS。每个包通过组装进行验证,而非直接打开原始文件。
modeRenderers['<name>'] = {registry, clear, <setters>, assertRegistryComplete} - 组装通过脚本完成:执行确定性拼接;
scripts/assemble-walkthrough.py是组装后的强制自检(无构建流程的安全保障)。scripts/check-walkthrough.py
Pick the mode — flat decision table
选择模式 — 扁平决策表
Ask "what is the problem ABOUT?" (one distinct noun per row) and read across:
| Mode | Problem is ABOUT… | NOT when → use | Pack |
|---|---|---|---|
| diagram | data flow between components (A→B→C) | rows changing state → tables | |
| tables | rows changing state under FK/cascade rules | one entity's lifecycle → state-machine | |
| state-machine | one entity's legal state transitions; an illegal/stuck transition | many rows mutating → tables | |
Sharp disambiguators: state-machine = "ONE entity's status transitions" (not "many
rows mutating" → tables); a future timeline = "WHEN it happened / ordering" (not "what
connects to what" → diagram). Tie-break: when in doubt → diagram. Every new mode row
must name its nearest neighbour in the "NOT when" column.
先问**“问题核心是什么?”**(每行对应一个明确的名词),然后对照选择:
| 模式 | 问题核心是… | 不适用场景→改用 | 模式包 |
|---|---|---|---|
| diagram(图形式) | 组件间的数据流(A→B→C) | 行状态变化→tables | |
| tables(表格形式) | 外键/级联规则下的行状态变化 | 单个实体的生命周期→state-machine | |
| state-machine(状态机形式) | 单个实体的合法状态转换;非法/卡住的转换 | 多行变更→tables | |
明确区分规则:state-machine = “单个实体的状态转换”(而非“多行变更”→tables);未来的timeline(时间线) = “事件发生时间/顺序”(而非“元素间关联”→diagram)。模糊时的决断规则:拿不准就选diagram。每个新模式行必须在“不适用场景”列中指明最接近的替代模式。
When to Use This Skill
何时使用本技能
- User wants an interactive walkthrough of a non-trivial technical problem
- Verbal/text explanation has failed and the user is still confused
- The problem involves multiple components or entities + a chain of cause-and-effect
- The "aha moment" hinges on seeing data move through the system
- Teaching a concept where the reader benefits from controlling pace
Don't use when:
- The answer fits in 1-3 sentences
- It's a "what does X mean?" definition question
- It's a simple bug fix where understanding is trivial
- The user wants to read code (use instead)
drive-to-legacy - The user wants a polished UI/component (use instead)
frontend-design - The user wants to find the bug, not teach it (use instead)
debug-mantra
- 用户需要对非 trivial 的技术问题进行交互式分步演练
- 口头/文字解释无效,用户仍有困惑
- 问题涉及多个组件或实体,以及因果链
- “顿悟时刻”依赖于观察数据在系统中的流动
- 教授概念时,读者能通过控制节奏获益
请勿使用的场景:
- 答案可在1-3句话内说明
- 是“X是什么意思?”这类定义问题
- 是理解难度极低的简单bug修复
- 用户希望查看代码(改用技能)
drive-to-legacy - 用户希望获得 polished UI/组件(改用技能)
frontend-design - 用户希望定位bug,而非讲解bug(改用技能)
debug-mantra
The Process — 6 Phases
流程 — 6个阶段
Phase 0 — Confirm the artifact is wanted
阶段0 — 确认用户需要该产物
Before generating ~500 lines of HTML, ask:
"อยากได้ interactive step-by-step walkthrough (HTML page เปิดในเบราว์เซอร์), หรือคำตอบสั้นๆ พอ?"
Skip Phase 0 if the user explicitly asked for "walkthrough", "animation", "visualization", "step by step", "ทำ animation", "diagram", "interactive", or similar artifact-shape language.
Then ask the second artifact-shape question — the app screen mock:
"อยากให้ walkthrough มี mock หน้าจอจริงของแอป (เช่น grid/form ที่ผู้ใช้เห็น) ด้วยไหม, หรือเอาแค่ diagram ของ flow?"
Ask this whenever the problem is visible on a screen — a wrong number in a column, a
button that is disabled, a row that vanishes. A mock earns its place because the reader
recognizes the screen they actually use, which turns an abstract column name into the cell
they have looked at a hundred times. Skip the question only when nothing about the problem
reaches the UI (a build gate, a migration script, a server-side race).
If they say yes:
- Build the mock from the mode pack's own state model — render the changing cells as
groups registered in the renderer's
.comp, so the pack's existing state CSS (COMPONENTS/active/error/done) drives them. Do NOT invent new CSS states or hexes.locked - Match the real columns, in the real order, read off the component source — not from memory of what the screen probably shows.
- Fill the cells with MEASURED values if the system is live and queryable. One read-only query beats invented rows, and grounded data routinely surfaces a sharper story than the one you set out to tell.
在生成约500行HTML之前,先询问:
“您想要交互式分步演练(可在浏览器中打开的HTML页面),还是简短的文字回答?”
如果用户明确要求“walkthrough”、“animation”、“visualization”、“step by step”、“ทำ animation”、“diagram”、“interactive”或类似描述产物形式的词汇,跳过阶段0。
然后询问第二个产物形式问题——应用界面模拟:
“您希望演练包含应用的真实界面模拟(例如用户日常看到的表格/表单),还是仅展示流程图?”
当问题在界面上可见时(例如列中的错误数值、禁用的按钮、消失的行),必须询问此问题。界面模拟的价值在于读者能识别自己日常使用的界面,将抽象的列名转化为他们看过无数次的单元格。仅当问题完全不涉及UI时(例如构建门限、迁移脚本、服务端竞态),才跳过此问题。
如果用户回答是:
- 基于模式包的状态模型构建模拟——将变化的单元格渲染为渲染器中注册的
COMPONENTS组,使用包中已有的状态CSS(.comp/active/error/done)控制样式。请勿发明新的CSS状态或十六进制颜色值。locked - 匹配真实列——按照组件源码中的真实顺序和列名展示,而非凭记忆推测界面样式。
- 若系统可查询,使用实测值填充单元格。一次只读查询胜过虚构的数据行,真实数据往往能呈现比预设更清晰的问题场景。
Phase 1 — Identify the core misunderstanding AND pick the mode
阶段1 — 识别核心误解并选择模式
Articulate these in one sentence each:
- The ONE concept the reader should grasp by the end (e.g., "the UPDATE-on-ctg_name trick is what acquires the row-level write lock")
- The misunderstanding they have now (e.g., "they think the workflow and the counter entity are two unrelated things")
- The prerequisites they already have (e.g., "they know Dataverse entities and that workflows trigger on Create")
- The unfamiliar terms — list the terms the narration will use that fall beyond
the prerequisites (domain jargon, schema names, project concepts). These become
drillable terms (Phase 4). Read the project's (or the mapped context via
CONTEXT.md) and pull the definition for each term that exists there; for a beyond-prerequisite term not in the glossary, write a one-line definition yourself. A term the reader already knows is not made drillable — over-marking turns the narration into a sea of dotted underlines.CONTEXT-MAP.md
Then pick the mode using the "How to choose" rule above. Tell the user which mode you're using in your first message.
If you can't articulate (1) and (2) in one sentence each, ask the user before continuing. Vague misunderstandings produce vague walkthroughs.
用一句话分别阐述以下内容:
- 读者最终应掌握的一个核心概念(例如:“更新ctg_name的技巧用于获取行级写锁”)
- 读者当前存在的误解(例如:“他们认为工作流和计数器实体是两个无关的事物”)
- 读者已具备的前置知识(例如:“他们了解Dataverse实体,以及工作流在创建时触发”)
- 陌生术语——列出说明中使用的、超出前置知识范围的术语(领域黑话、 schema名称、项目概念)。这些将成为可钻取术语(阶段4)。阅读项目的(或通过
CONTEXT.md映射的上下文),提取其中已有定义的术语;对于前置知识范围外且未在术语表中的术语,自行编写一行定义。读者已了解的术语无需设置为可钻取——过度标记会让说明内容布满虚线下划线,影响阅读。CONTEXT-MAP.md
然后根据上述“模式选择规则”确定模式。在首次回复中告知用户你选择的模式。
如果你无法用一句话分别阐述(1)和(2),在继续前询问用户。模糊的误解会导致模糊的演练文档。
Phase 2 — Choose concrete data
阶段2 — 选择具体数据
Replace abstract entities with realistic, culturally appropriate data.
Data Quality Checklist:
- ≤ 4 entities (boxes or tables) of any one kind — more is noise
- Names read aloud naturally ("BMW Group", "ครอบครัวสมศรี" not "Customer A", "Family A")
- Numbers small enough to mental-math (,
5,42— not80฿)47,392.18฿ - Identifiers must not look like sequence numbers — if a sequence appears in the output (e.g., booking numbers 00001, 00002), avoid IDs like /
cargo-1that the reader will confuse for those. Prefer letter IDs (cargo-2,cargo-A) or source-tagged labels (cargo-B).cargo (Portal) - At least one element participates in EVERY problematic path — so when the conflict step lights up, it's visually obvious on one element
- Schema names match the user's actual codebase (,
ctg_runningnumber— notBudgetTransactions,Counter)Table1 - Cultural fit — default to Thai narration for Thai users; technical terms (workflow, CodeActivity, EntityReference, transaction) stay in English
Bad → Good examples:
| Bad | Good |
|---|---|
| |
| |
| |
| |
用真实、符合文化背景的数据替换抽象实体。
数据质量检查清单:
- 同类实体不超过4个(框或表格)——过多会造成干扰
- 名称读起来自然(例如“BMW Group”、“ครอบครัวสมศรี”,而非“Customer A”、“Family A”)
- 数字小到可心算(、
5、42——而非80฿)47,392.18฿ - 标识符不得类似序列号——如果输出中包含序列号(例如预订号00001、00002),避免使用/
cargo-1这类会让读者混淆的ID。优先使用字母ID(cargo-2、cargo-A)或带来源标签的名称(cargo-B)。cargo (Portal) - 至少有一个元素参与所有问题路径——这样当冲突步骤高亮时,读者能直观看到受影响的元素
- Schema名称与用户实际代码库一致(、
ctg_runningnumber——而非BudgetTransactions、Counter)Table1 - 文化适配——默认对泰国用户使用泰语说明;技术术语(workflow、CodeActivity、EntityReference、transaction)保留英文
反面→正面示例:
| 反面 | 正面 |
|---|---|
| |
| |
| |
| |
Phase 3 — Sequence the steps
阶段3 — 编排步骤顺序
Build a domino chain. Each step adds one new piece of state.
Standard skeleton (diagram mode):
| Step | Purpose |
|---|---|
| 0 | Overview — show all components + arrows in idle state. No action. Reader builds mental model. |
| 1 | Trigger — what initiates the flow? (Light up the triggering component.) |
| 2..N | Single-actor flow — ONE component activates per step, ONE arrow fires per step, ONE value shown flying along it. State accumulates visibly. |
| N+1 | The key question (REQUIRED) — pose a question the reader must answer in their head before the concurrent / failure scenario reveals the answer. |
| N+2..M | Concurrent / failure scenario — show 2-3 actors racing, blocking, or conflicting. |
| M+1 | Counter-example — what would go wrong with the naive approach (e.g., "what if we used MAX()+1?"). |
| M+2 | Summary / resolution — why the architecture works AND its trade-offs / side-effects. |
Standard skeleton (tables mode):
| Step | Purpose |
|---|---|
| 0 | Setup — show all tables + all rules. No action. |
| 1 | Trigger — user action starts the chain. |
| 2..N | Domino effects — ONE rule fires per step, affecting specific named rows. |
| N+1 | Key question. |
| N+2 | Conflict / failure step. |
| N+3 | Resolution with side-effects named. |
Each step has:
- Scene title — imperative, ≤ 12 words ("Step 8 — 🔒 AcquireWriteLock: UPDATE ctg_name forces row X-lock")
- Narration — 2-5 sentences answering WHY (not just WHAT). Why does this fire? Why is the value chosen? Why does this matter to the reader?
- Visual change — light up the active component/row, fire the active arrow, show the flying-value label, highlight the active rule
构建多米诺链式流程。每一步仅添加一个新状态。
标准框架(图形式模式):
| 步骤 | 目的 |
|---|---|
| 0 | 概览——展示所有组件和箭头的空闲状态,无操作。帮助读者建立心智模型。 |
| 1 | 触发——流程的启动源是什么?(高亮触发组件) |
| 2..N | 单参与者流程——每一步激活一个组件、触发一个箭头、展示一个沿箭头流动的值。状态可见地累积。 |
| N+1 | 关键问题(必填)——在并发/失败场景揭示答案前,提出一个需要读者自行思考的问题。 |
| N+2..M | 并发/失败场景——展示2-3个参与者的竞争、阻塞或冲突情况。 |
| M+1 | 反例——如果使用 naive 方法会出现什么问题(例如“如果我们使用MAX()+1会怎样?”)。 |
| M+2 | 总结/解决方案——解释架构为何有效,以及其权衡/副作用。 |
标准框架(表格形式模式):
| 步骤 | 目的 |
|---|---|
| 0 | 设置——展示所有表格和规则,无操作。 |
| 1 | 触发——用户操作启动流程链。 |
| 2..N | 多米诺效应——每一步触发一个规则,影响特定命名的行。 |
| N+1 | 关键问题。 |
| N+2 | 冲突/失败步骤。 |
| N+3 | 解决方案,并说明副作用。 |
每一步包含:
- 场景标题——祈使句,不超过12个词(例如“步骤8 — 🔒 AcquireWriteLock: UPDATE ctg_name强制行X锁”)
- 说明文字——2-5句话,解释原因(而非仅描述操作)。为什么触发此操作?为什么选择这个值?这对读者有什么重要性?
- 视觉变化——高亮激活的组件/行、触发激活的箭头、展示流动值标签、高亮激活的规则
Phase 4 — Author the bootstrap, then assemble
阶段4 — 编写引导代码,然后组装
You write only the bootstrap (the per-walkthrough content); the engine + mode pack +
drawer are inlined by the assembler.
- Read the chosen mode pack () to learn its renderer's setters and its content-DOM ids (e.g. state-machine:
references/mode-<name>.html/setNodeoversetEdge/NODE_LIST; diagram:EDGE_LIST/setComp/setArrow/setLabel; tables:setText/setRowClass/setBadge/setCell). If the pack's built-in content DOM doesn't fit your problem, edit a COPY of the pack'ssetRule(its registry ids must match).§HTML - Write a bootstrap (a snippet) with, in order:
.jsMODE = '<name>';- — alias the pack's setters to flat names so scenes read like
const { setNode, setEdge } = modeRenderers[MODE];.setNode('stDraft','done') - — your drillable terms (only if using the drawer). Each entry
const GLOSSARY = { … };with{term, short, seeAlso, source}(quote the glossary) orsource: 'CONTEXT.md'(a fallback for a term absent from'authored'; consider offering to add it). Mark terms in narration:CONTEXT.md.<span class="term" data-term="key">…</span> - — one function per step, each fully describing DOM state via the flat setters +
const scenes = [ … ];+setNarration(cls, title, bodyHTML)onshow()/hide()s..wt-panel - — the
TOTAL = scenes.length - 1; modeRenderers[MODE].assertRegistryComplete(); buildProgressDots(); render(0);call makes any DOM-id-not-in-registry drift throw at load.assertRegistryComplete()
- Assemble:
Drop
python scripts/assemble-walkthrough.py --engine references/walkthrough-engine.html \ --mode references/mode-<name>.html --drawer references/term-drilldown.html \ --title "<the walkthrough's on-screen heading>" \ --out <project-root>/docs/problem-description/<name>.html --bootstrap your-bootstrap.jsif the walkthrough has no drillable terms.--drawerfills both the browser-tab--titleand the on-screen<title>(it falls back to the output filename stem, so the placeholder never ships — but pass a real title).<h1> - Self-test (mandatory): — it must pass.
python scripts/check-walkthrough.py <out>.html
The drawer is framework, not a scene — never call //
from a scene; it self-registers into so stepping closes it for free.
openTermcloseDrawerGLOSSARYRENDER_HOOKSCritical rule: every scene must fully describe DOM state from scratch. Never
/ from a scene. Declare every panel up front ()
and toggle with . The engine runs → the mode's
→ on every render.
createElementappendChild.wt-panel hiddenshow()/hide()RENDER_HOOKSclear(registry)scenes[step]()你只需编写引导代码(每个演练文档的专属内容);引擎、模式包和术语抽屉由组装器内联到最终文件中。
- 阅读选定的模式包(),了解其渲染器的setter方法和内容DOM的ID(例如状态机模式:
references/mode-<name>.html/setNode对应setEdge/NODE_LIST;图形式模式:EDGE_LIST/setComp/setArrow/setLabel;表格形式模式:setText/setRowClass/setBadge/setCell)。如果包中内置的内容DOM不符合你的问题需求,编辑模式包setRule的副本(确保registry ID匹配)。§HTML - 编写引导代码(一个片段),顺序如下:
.jsMODE = '<name>';- ——将包的setter方法别名简化为扁平名称,使场景代码更简洁,例如
const { setNode, setEdge } = modeRenderers[MODE];。setNode('stDraft','done') - ——可钻取术语(仅当使用术语抽屉时需要)。每个条目包含
const GLOSSARY = { … };,其中{term, short, seeAlso, source}(引用项目术语表)或source: 'CONTEXT.md'(当术语未在'authored'中时的备用定义;可考虑提议将其添加到术语表)。在说明文字中标记术语:CONTEXT.md。<span class="term" data-term="key">…</span> - ——每一步对应一个函数,通过扁平setter方法、
const scenes = [ … ];以及setNarration(cls, title, bodyHTML)的.wt-panel方法完整描述DOM状态。show()/hide() - ——
TOTAL = scenes.length - 1; modeRenderers[MODE].assertRegistryComplete(); buildProgressDots(); render(0);调用会在加载时抛出DOM ID未在registry中定义的错误。assertRegistryComplete()
- 组装:
如果演练文档没有可钻取术语,去掉
python scripts/assemble-walkthrough.py --engine references/walkthrough-engine.html \ --mode references/mode-<name>.html --drawer references/term-drilldown.html \ --title "<演练文档的屏幕标题>" \ --out <project-root>/docs/problem-description/<name>.html --bootstrap your-bootstrap.js参数。--drawer会同时填充浏览器标签的--title和屏幕上的<title>(如果未指定,会回退到输出文件名的主干部分,但建议传入真实标题)。<h1> - 强制自检: ——必须通过。
python scripts/check-walkthrough.py <out>.html
术语抽屉是框架,而非场景的一部分——绝不要在场景中调用//;它会自动注册到中,切换步骤时会自动关闭。
openTermcloseDrawerGLOSSARYRENDER_HOOKS关键规则: 每个场景必须从头开始完整描述DOM状态。绝不要在场景中使用/。提前声明所有面板(),通过切换可见性。引擎在每次渲染时会执行 → 模式的 → 当前场景函数。
createElementappendChild.wt-panel hiddenshow()/hide()RENDER_HOOKSclear(registry)Phase 4.5 — Save and report
阶段4.5 — 保存并报告
Save the artifact INSIDE the open project, in a dedicated folder (see the Output-location contract near the top). Resolve the project root to a real absolute path, never a placeholder. Save path, in priority order:
- The user specified a path → use it exactly.
- A project/workspace is open (the normal case) → (diagram mode) or
<project-root>/docs/problem-description/YYYY-MM-DD-<topic>-walkthrough.html(tables mode), where<project-root>/docs/problem-description/<topic>-explained.htmlis the user's open project/workspace — not your agent working/scratch directory, which may differ. Create<project-root>if it does not exist (docs/problem-description/) so it does not mix with specs, ADRs, and plans in themkdir -proot. Never write it to your agent scratch/sandbox directory (e.g.docs/) when a project is open — that hides the file from the user.~/.gemini/antigravity/brain/<id>/scratch/ - Only when there is genuinely no open project (a throwaway question with nowhere to put it): use the session scratchpad directory and tell the user the absolute path. Do not default to a hard-coded personal path like . This branch is the exception, not the default — if a project is open, the bullet above wins.
c:/Repo2/t/
Then run the verify-and-move check (mandatory) — see the Output-location contract near the top: get the file's absolute path, confirm it is inside , and if the harness wrote it elsewhere (scratch/sandbox/temp, project root, generic name), move it there before reporting — unless the user specified an explicit path (bullet 1), in which case honor that path. The skill is not done until the file is in the right place.
<project-root>/docs/problem-description/Report back:
- The absolute path of the generated file
- Which mode (diagram or tables)
- How many steps
- "Open in your browser — /
ถัดไป →/← ย้อนกลับปุ่มควบคุม pace"↻ เริ่มใหม่
将产物保存到打开的项目内的专用文件夹(见顶部的输出位置约定)。将项目根目录解析为真实的绝对路径,绝不要保留占位符。保存路径优先级如下:
- 用户指定了路径——完全按照该路径保存。
- 打开了项目/工作区(常规场景)——保存到(图形式模式)或
<project-root>/docs/problem-description/YYYY-MM-DD-<topic>-walkthrough.html(表格形式模式),其中<project-root>/docs/problem-description/<topic>-explained.html是用户打开的项目/工作区——不要使用Agent的工作/临时目录,两者可能不同。如果<project-root>不存在则创建(使用docs/problem-description/),避免与mkdir -p根目录下的规格文档、ADR和计划文档混合。绝不要在打开项目时将文件写入Agent的临时沙箱目录(例如docs/)——这会让用户找不到文件。~/.gemini/antigravity/brain/<id>/scratch/ - 确实没有打开的项目(一次性问题,无合适保存位置):保存到会话临时目录,告知用户绝对路径。不要默认使用硬编码的个人路径(如)。此分支为例外情况,非默认——如果打开了项目,优先遵循上一条规则。
c:/Repo2/t/
然后执行强制的验证并移动检查——见顶部的输出位置约定:获取文件的绝对路径,确认其位于目录下;如果环境将文件保存到了其他位置(临时沙箱/临时目录、项目根目录、通用名称),则将其移动到正确位置后再报告——除非用户指定了明确路径(第一条),此时遵循用户指定的路径。只有当文件处于正确位置时,本技能才算完成。
<project-root>/docs/problem-description/回复内容包括:
- 生成文件的绝对路径
- 使用的模式(图形式或表格形式)
- 步骤数量
- “在浏览器中打开——通过/
ถัดไป →/← ย้อนกลับ按钮控制节奏”↻ เริ่มใหม่
Phase 5 — Verify before declaring done
阶段5 — 验证后再宣告完成
Run the self-test checklist:
- Every step's narration answers WHY, not just WHAT
- The "key question" step exists and forces reader thinking
- The resolution / summary step explicitly names side-effects and trade-offs
- in JS (step 0 is included; TOTAL is the index of the last step)
scenes.length - 1 === TOTAL - Every call has a matching
getElementById(id)attribute in the HTMLid - Every id a scene targets resolves to an in the DOM (the checker's scene-id pass), and
id=""passes at load (DOM ids ⊆ registry)modeRenderers[MODE].assertRegistryComplete() - Going from any step returns clean state (idempotent scene rule)
← Previous - returns to step 0 with no residual highlights, badges, or visible panels
↻ Reset - No /
appendChildinside any scene functioncreateElement - No identifier collision: sequence numbers in the output don't conflict with element IDs (e.g., don't use when booking numbers
cargo-1will appear)00001 - Drill-down referential integrity: every has a
data-term="X"entry, and everyGLOSSARY[X]key resolves to aseeAlsoentryGLOSSARY - Grounding: every entry marked
GLOSSARYmatches the glossary wording;source: 'CONTEXT.md'is used only for terms absent from'authored'CONTEXT.md - Drawer is orthogonal: no scene references the drawer
(/
openTerm/closeDrawer/termDrawer); the mode'sGLOSSARYdoes not touch it;clear()runsrender()first (the drawer self-registersRENDER_HOOKS);closeDrawer/Next/Prevclose the drawer and leave no residueReset - See-also hops: clicking a see-also chip swaps the drawer; restores the prior term; with no
← back, drillable terms still work viaCONTEXT.mddefsauthored - Post-assembly self-test passes: reports OK (self-contained,
python scripts/check-walkthrough.py <out>.html+renderer ok,MODE-first, scenes clean, order ok)RENDER_HOOKS
If any item fails — fix before reporting done.
执行自检清单:
- 每一步的说明文字都解释了原因,而非仅描述操作
- 包含“关键问题”步骤,引导读者思考
- 解决方案/总结步骤明确说明了副作用和权衡
- JS中的(包含步骤0;TOTAL是最后一步的索引)
scenes.length - 1 === TOTAL - 每个调用都对应HTML中的
getElementById(id)属性id - 场景中引用的每个ID都能在DOM中找到对应的(检查器的场景ID校验),且
id=""在加载时通过(DOM ID ⊆ registry)modeRenderers[MODE].assertRegistryComplete() - 从任意步骤点击能返回干净的状态(场景规则具有幂等性)
← Previous - 点击能回到步骤0,无残留高亮、徽章或可见面板
↻ Reset - 任何场景函数中都没有/
appendChildcreateElement - 无标识符冲突:输出中的序列号与元素ID不冲突(例如当预订号为时,不要使用
00001)cargo-1 - 钻取引用完整性:每个都有对应的
data-term="X"条目,且每个GLOSSARY[X]键都能解析到seeAlso条目GLOSSARY - 术语来源合规:每个标记为的
source: 'CONTEXT.md'条目都与术语表措辞一致;仅当术语未在GLOSSARY中时才使用CONTEXT.md'authored' - 术语抽屉与场景解耦:场景中未引用术语抽屉(/
openTerm/closeDrawer/termDrawer);模式的GLOSSARY不涉及术语抽屉;clear()先执行render()(术语抽屉自动注册RENDER_HOOKS);closeDrawer/Next/Prev会关闭术语抽屉且无残留Reset - 相关术语跳转正常:点击see-also标签会切换术语抽屉内容;会恢复之前的术语;即使没有
← back,可钻取术语仍能通过CONTEXT.md定义正常工作authored - 组装后自检通过:报告OK(独立文件、
python scripts/check-walkthrough.py <out>.html+渲染器正常、MODE优先执行、场景干净、顺序正确)RENDER_HOOKS
如果任何一项未通过——修复后再宣告完成。
Design Decisions — engine + mode packs
设计决策 — 引擎+模式包
Color tokens live once in the engine's (); never
introduce a new hex. The semantic core: (info/active),
(firing), (locked/key), ,
(done), (error/conflict), ,
. SVG marker fills come from the engine's fixed 5 markerheads
(////), or — never a raw hex.
:rootwalkthrough-engine.html--accent #5fb4ff--amber #ffd479--magic #b070ff--warn #ffaa00--success #4ade80--error #ff5757--bg #0a0e14--panel #1a2330arrowhead-active-magic-done-errorvar(--token)The renderer contract every mode pack implements:
js
modeRenderers['<name>'] = {
registry: { /* one+ flat id-arrays */ },
clear(reg) { /* reset every registry id to idle; hide .wt-panel; restore [data-default] */ },
/* replace-only setters, e.g. setNode(id,state) */
assertRegistryComplete() { /* throw if a DOM id is absent from the registry */ },
};Each pack documents its own states (in the pack file's comments) — don't duplicate them here:
- —
references/mode-diagram.html/setComp/setArrow/setLabel; comp statessetText; arrow statesactive/firing/locked/blocked/done/error/dimmed.active/magic/done/error/dimmed - —
references/mode-tables.html/setRowClass/setBadge/setCell; row statessetRule; badgestarget-delete/target-setnull/target-conflict/fixed/deleted.delete/setnull/conflict - —
references/mode-state-machine.html/setNode; node statessetEdge; the illegal/stuck transition IS the conflict step.current/passed/illegal/stuck/key/dimmed
颜色令牌仅在引擎的中定义一次();绝不要引入新的十六进制颜色值。语义核心:(信息/激活)、(触发中)、(锁定/关键)、、(完成)、(错误/冲突)、、。SVG标记填充来自引擎固定的5种标记头(////)或——绝不要使用原始十六进制颜色值。
:rootwalkthrough-engine.html--accent #5fb4ff--amber #ffd479--magic #b070ff--warn #ffaa00--success #4ade80--error #ff5757--bg #0a0e14--panel #1a2330arrowhead-active-magic-done-errorvar(--token)每个模式包都需实现的渲染器契约:
js
modeRenderers['<name>'] = {
registry: { /* 一个或多个扁平ID数组 */ },
clear(reg) { /* 将所有registry ID重置为空闲状态;隐藏.wt-panel;恢复[data-default] */ },
/* 仅替换的setter方法,例如setNode(id,state) */
assertRegistryComplete() { /* 如果DOM ID未在registry中则抛出错误 */ },
};每个包都在自身文件的注释中记录了支持的状态——此处不再重复:
- —
references/mode-diagram.html/setComp/setArrow/setLabel;组件状态setText;箭头状态active/firing/locked/blocked/done/error/dimmed。active/magic/done/error/dimmed - —
references/mode-tables.html/setRowClass/setBadge/setCell;行状态setRule;徽章target-delete/target-setnull/target-conflict/fixed/deleted。delete/setnull/conflict - —
references/mode-state-machine.html/setNode;节点状态setEdge;非法/卡住的转换即为冲突步骤。current/passed/illegal/stuck/key/dimmed
Idempotent Scenes — The One Rule (both modes)
幂等场景 — 核心规则(所有模式)
Every scene function must fully describe DOM state from scratch. Never build cumulatively.
Why: if scene 4 calls and scene 5 doesn't remove it, then from scene 6 to scene 4 leaves the panel duplicated. Idempotent rendering eliminates this entire class of bugs.
appendChild(panel)← PreviousHow:
- Declare every possible UI element in the initial HTML, hidden with class (or with default content for live-text fields)
.hidden - Scenes call /
show('panelId')to toggle visibilityhide('panelId') - Scenes call the mode's replace-only setters (e.g. /
setNode,setEdge/setComp,setArrow/setRowClass) — these REPLACE state, never appendsetBadge - Scenes call /
setTextto update live-text fieldssetCell - The engine's runs
render()(e.g. the drawer'sRENDER_HOOKS) → the mode'scloseDrawer→ ONLY the current scene functionclear(registry)
No scene function ever does:
document.createElement(...)el.appendChild(...)- (use the wrapper setters, which replace)
el.classList.add(...) el.innerHTML += ...
If you need to "add" a panel mid-walkthrough, declare it once in the initial HTML with and it from the scene.
.hiddenshow()每个场景函数必须从头开始完整描述DOM状态。绝不要累积式构建。
原因:如果场景4调用而场景5未移除该面板,那么从场景6点击回到场景4时,面板会重复显示。幂等渲染可彻底消除这类bug。
appendChild(panel)← Previous实现方式:
- 在初始HTML中声明所有可能的UI元素,使用类隐藏(或为动态文本字段设置默认内容)
.hidden - 场景通过/
show('panelId')切换可见性hide('panelId') - 场景调用模式的仅替换setter方法(例如/
setNode、setEdge/setComp、setArrow/setRowClass)——这些方法会替换状态,而非追加setBadge - 场景调用/
setText更新动态文本字段setCell - 引擎的会执行
render()(例如术语抽屉的RENDER_HOOKS)→ 模式的closeDrawer→ 仅当前场景函数clear(registry)
场景函数绝不能执行以下操作:
document.createElement(...)el.appendChild(...)- (使用封装的setter方法,这些方法会替换状态)
el.classList.add(...) el.innerHTML += ...
如果需要在演练过程中“添加”面板,只需在初始HTML中声明一次并添加类,然后在场景中调用显示即可。
.hiddenshow()Common Mistakes
常见错误
| Mistake | Fix |
|---|---|
| Wrong mode picked — tables for a flow problem | Use the flat selection table. Flow → diagram. Row state → tables. One entity's transitions → state-machine. |
| Auto-playing animation that races past the reader | Manual |
Abstract names ( | Real, domain-flavored, culturally appropriate names. |
IDs collide with output sequence numbers ( | Use letter IDs ( |
| Each step changes too many things at once | One component activates per step. One arrow fires. One value moves. |
| Narration says WHAT, not WHY | Every narration explains the rule's reason. |
| No "key question" step | The conflict/concurrency reveal needs a thinking-pause beforehand. |
| Fix without side-effects called out | Resolution always has trade-offs — name them. |
| Cumulative-replay rendering | Idempotent scenes only — no |
| 300+ lines of HTML for a 2-step problem | This skill is for problems with 4+ chained effects. Smaller problems → just chat or use a single mermaid diagram. |
| Scene functions must fully describe state, not deltas. |
| Same element never highlighted in the conflict step | Pick concrete data so at least one element is hit by every problematic path. |
| Flying-label rect too small / clipped text | Measure your label text length; widen the |
| Invented term definitions instead of CONTEXT.md | Source from the project glossary; author a fallback only when the term is absent (ADR 0017). |
A helper builds | |
| Over-marking — every other word is drillable | Mark only terms beyond the reader's stated prerequisites. |
| Copying the drawer/engine code into a mode pack | The primitive lives once; inline via the assembler ( |
| A scene opens/closes/reads the drawer | The drawer is reader-driven framework, never scene state. Keep scenes pure. |
| Every |
Editing | A mode is a pack registering one renderer — adding a mode is zero engine edits (ADR 0020). |
Hand-splicing the assembled | Use |
| Introducing a new color hex | Reuse |
| Apostrophe inside a single-quoted GLOSSARY string breaks the bootstrap JS | Use double-quotes or reword; |
| 错误 | 修复方案 |
|---|---|
| 模式选择错误——用tables处理流问题 | 使用扁平决策表。流问题→diagram。行状态变化→tables。单个实体的转换→state-machine。 |
| 自动播放动画,节奏过快 | 仅使用手动 |
使用抽象名称( | 使用真实、符合领域特色、文化适配的名称。 |
ID与输出序列号冲突( | 使用字母ID( |
| 每一步同时变更过多内容 | 每一步仅激活一个组件、触发一个箭头、移动一个值。 |
| 说明文字仅描述操作,未解释原因 | 每个说明都要解释规则背后的原因。 |
| 缺少“关键问题”步骤 | 在冲突/并发场景揭示前,需要给读者留出思考时间。 |
| 解决方案未说明副作用 | 解决方案必然存在权衡——明确指出。 |
| 使用累积式回放渲染 | 仅使用幂等场景——场景中禁止使用 |
| 2步问题却生成300+行HTML | 本技能适用于包含4个以上链式效应的问题。小问题→直接聊天或使用单个mermaid图。 |
| 场景函数必须完整描述状态,而非增量变更。 |
| 冲突步骤中没有元素被高亮 | 选择具体数据,确保至少有一个元素受所有问题路径影响。 |
| 流动值标签的矩形过小/文本被截断 | 测量标签文本长度;加宽 |
| 自行定义术语,未使用CONTEXT.md | 优先引用项目术语表;仅当术语未在表中时才自行编写备用定义(ADR 0017)。 |
辅助函数动态构建 | |
| 过度标记——每隔一个词就设置为可钻取 | 仅标记超出读者前置知识范围的术语。 |
| 将术语抽屉/引擎代码复制到模式包中 | 基础代码仅定义一次;通过组装器内联( |
| 场景中打开/关闭/读取术语抽屉 | 术语抽屉是读者驱动的框架,不属于场景状态。保持场景纯粹。 |
| 每个 |
编辑 | 模式是注册单个渲染器的包——添加新模式无需修改引擎(ADR 0020)。 |
手动拼接组装后的 | 使用 |
| 引入新的十六进制颜色值 | 复用 |
| 单引号包裹的GLOSSARY字符串中包含撇号,导致引导JS出错 | 使用双引号或改写; |
Reference files (the always-present scaffolds)
参考文件(始终可用的脚手架)
Build every walkthrough from these bundled files in this skill's folder:
- — the shared engine (also a standalone runnable demo).
references/walkthrough-engine.html - ·
references/mode-diagram.html·references/mode-tables.html— the mode packs (each runs its own demo via assembly).references/mode-state-machine.html - — the term drill-down drawer.
references/term-drilldown.html - — the deterministic generation splice.
scripts/assemble-walkthrough.py - — the mandatory post-assembly self-test.
scripts/check-walkthrough.py
Author's local examples (structural inspiration only — may not exist on your machine; skip if absent):
- — a 22-step diagram-mode concurrency walkthrough.
c:/Repo/glasshull repo/glasshull/docs/2026-05-28-polaris-booking-number-diagram.html - — a 7-step tables-mode SQL 1785 cascade walkthrough.
c:/Repo2/t/cascade-paths-explained.html
所有演练文档都基于本技能文件夹中的以下捆绑文件构建:
- — 共享引擎(同时也是可独立运行的演示)。
references/walkthrough-engine.html - ·
references/mode-diagram.html·references/mode-tables.html— 模式包(每个包都可通过组装运行自身演示)。references/mode-state-machine.html - — 术语钻取抽屉。
references/term-drilldown.html - — 确定性生成拼接脚本。
scripts/assemble-walkthrough.py - — 组装后强制自检脚本。
scripts/check-walkthrough.py
作者本地示例(仅作结构参考——你的机器上可能不存在;如果缺失则跳过):
- — 22步图形式并发演练。
c:/Repo/glasshull repo/glasshull/docs/2026-05-28-polaris-booking-number-diagram.html - — 7步表格形式SQL 1785级联演练。
c:/Repo2/t/cascade-paths-explained.html