docs-draft-feature-docs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
<!-- Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Elasticsearch B.V. licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -->
You draft Elastic documentation for any feature or feature area. One skill and one baseline for every area, so that a page about Security and a page about Fleet arrive at review with the same structure, scoping, and voice.
<!-- Maintainers: `context: fork` is omitted on purpose. This skill interviews the requester and takes approval before writing anything, so it stays in the main context. -->
<!-- Copyright Elasticsearch B.V.,并根据一项或多项贡献者许可协议获得许可。有关版权归属的更多信息,请参阅随本作品分发的 NOTICE 文件。Elasticsearch B.V. 根据 Apache License, Version 2.0(“License”)向您许可本文件;除非遵守 License,否则您不得使用本文件。您可以在以下位置获取 License 副本: http://www.apache.org/licenses/LICENSE-2.0 除非适用法律另有规定或您同意遵守 License,否则本软件按“AS IS” BASIS 分发,不附带任何明示或暗示的担保,详见 License 中有关担保和限制的条款。 -->
你为任何功能或功能领域起草 Elastic 文档。每个领域都使用同一个 skill 和同一套 baseline,因此,一篇关于 Security 的页面和一篇关于 Fleet 的页面在送审时会具有相同的结构、范围和语气。
<!-- 维护者:这里有意省略 `context: fork`。此 skill 会先访谈请求者,并在写入任何内容前获得批准,因此它保留在主上下文中。 -->

The baseline

基线

Read the baseline, apply it, and never restate it here.
AGENTS.md
at the root of docs-content is the shared agent baseline, and
contribute-docs/
is the full contribution guide. Between them they cover the core principles, the style guide, cumulative docs, content types, and the PR checklist. A skill that keeps its own copy of those rules becomes a second version that drifts from them.
So this file holds the process, the area reference files hold area facts, and every rule about how Elastic docs should read is loaded from the baseline at run time. When
AGENTS.md
and the contribution guide disagree, the guide wins — that is the baseline's own precedence rule.
阅读基线、应用基线,并且绝不在此复述它。
AGENTS.md
位于 docs-content 根目录,是共享的 agent baseline,而
contribute-docs/
是完整的贡献指南。两者共同涵盖核心原则、style guide、cumulative docs、content types 和 PR checklist。保存这些规则自身副本的 skill 会产生第二个版本,并随时间偏离原始版本。
因此,本文件保存流程,各区域的 reference files 保存区域事实,而所有关于 Elastic 文档应如何撰写的规则都在运行时从 baseline 加载。当
AGENTS.md
与贡献指南不一致时,以贡献指南为准——这正是 baseline 自身的优先级规则。

Where facts come from

事实来源

Three sources, each answering something the other two cannot. Asking the wrong one produces a claim that looks verified and is not.
SourceWhat it knowsWhat it cannot tell you
elastic-docs
MCP
at
https://www.elastic.co/docs/_mcp/
, no auth
Every published page: what exists, what it says, how it is structured, and what it relates toAnything unpublished:
toc.yml
,
docset.yml
,
redirects.yml
,
_snippets/
,
hidden:
pages, or a page in an unmerged pull request
Local checkouts of docs-content and product reposThe files you are about to edit, plus navigation, redirects, and snippetsNothing about the live site, and nothing about a repo you have not cloned
Product source at
HEAD
UI strings, defaults, parameter names, limits, and behaviorWhich release carries the change — see Step 4d
Find pages with the MCP rather than from a path list. Do not encode a page inventory in this skill or in an area reference file when a search can find it and stay current. Area files record only what the MCP cannot answer: boundaries, product source paths, local conventions, navigation files, and known traps.
MCP toolUse it to
search_docs
Find published pages on the topic. This is the first move in Step 5, and the answer to "does this already exist?"
find_related_docs
Find the hub page, the siblings, and the cross-link targets around a topic
get_document_by_url
Read a candidate page. Pass
includeBody: true
, or you get headings and summaries only
analyze_document_structure
See a page's parent pages, which is how you place content in the hierarchy that already exists
check_docs_coherence
Check whether the topic is already covered coherently before adding to it
find_docs_inconsistencies
Find pages that already disagree with each other on this topic
To get from a published page to the file that produces it, read the page with
get_document_by_url
, then find the file by its slug —
rg --files -g '*<slug>*' <repo>
. Do not infer the owning repo from the URL; Step 4e settles that.
If the MCP is not configured, WebFetch the same URLs with
.md
appended, which returns the whole page including its frontmatter. Check reachability with
npx @modelcontextprotocol/inspector --url https://www.elastic.co/docs/_mcp/
.
That fallback replaces reading, not searching. WebFetch needs a URL you already have, and nothing in the fallback answers "what pages exist on this topic." Step 5 loses its first move outright rather than running a narrower version of it, so the local greps in Step 5.2 become the only discovery you have, across only the repos you cloned. Say in the output that no corpus search ran, and do not report "nothing covers this yet" as a finding — you were not in a position to look. A corpus nobody searched is the likeliest way this skill ends up placing a second copy of a page that already exists.
三个来源各自回答其他两个无法回答的问题。问错来源会产出一个看似已核验、实则未经核验的说法。
来源它知道什么它无法告诉你什么
elastic-docs
MCP
,地址为
https://www.elastic.co/docs/_mcp/
,无需认证
每个已发布页面:存在什么、内容说了什么、结构如何,以及关联内容任何未发布内容:
toc.yml
、
docset.yml
、
redirects.yml
、
_snippets/
、
hidden:
页面,或尚未合并的 pull request 中的页面
docs-content 和产品仓库的本地 checkout即将编辑的文件,以及导航、重定向和 snippets关于线上站点的任何信息,以及尚未 clone 的仓库中的任何信息
HEAD 处的产品源码UI 字符串、默认值、参数名、限制和行为哪一版本包含该变更——参见 Step 4d
**通过 MCP 查找页面,而不是依赖路径列表。**不要在这个 skill 或区域 reference file 中编码页面清单,因为搜索可以找到页面并保持最新。区域文件只记录 MCP 无法回答的内容:边界、产品源码路径、本地约定、导航文件和已知陷阱。
MCP 工具用途
search_docs
查找与主题相关的已发布页面。这是 Step 5 的第一步,也是回答“是否已经存在此类内容”的方式。
find_related_docs
查找 hub 页面、同级页面和主题周围的交叉链接目标。
get_document_by_url
读取候选页面。传入
includeBody: true
,否则只能获得标题和摘要。
analyze_document_structure
查看页面的父级页面,并据此将内容放入已有层级结构中的正确位置。
check_docs_coherence
在添加内容前,检查该主题是否已得到一致覆盖。
find_docs_inconsistencies
查找围绕该主题且彼此存在分歧的页面。
要从已发布页面找到生成该页面的文件,先用
get_document_by_url
读取页面,再根据 slug 查找文件:
rg --files -g '*<slug>*' <repo>
。不要从 URL 推断归属仓库;Step 4e 会确定它。
如果未配置 MCP,可使用 WebFetch 获取相同 URL,并在末尾追加
.md
,这样会返回包含 frontmatter 的完整页面。使用
npx @modelcontextprotocol/inspector --url https://www.elastic.co/docs/_mcp/
检查可达性。
**此 fallback 替代的是读取,而不是搜索。**WebFetch 需要已有 URL,而 fallback 无法回答“关于此主题存在哪些页面”。Step 5 会完全失去第一步,而不是以更窄的方式执行该步骤。因此,Step 5.2 中的本地 grep 将成为唯一的发现方式,而且只能覆盖已 clone 的仓库。在输出中说明未执行语料库搜索,不要把“目前没有任何内容涵盖此主题”作为结论——当时你并不具备查找条件。没有搜索过任何语料库,是这个 skill 最终放置第二份重复页面的最可能原因。

Constraints

约束

  • Never write a file or open a pull request without explicit approval. See Approval gates. This matches the baseline's own statement that its conventions are not instructions to push or open pull requests on your own. Creating the working branch in Step 3 is the one exception, because an empty local branch changes nothing and is reversible.
  • Never commit to, or write on, a default branch. Step 3 puts you on a working branch before anything else happens. After gate 2, commit on that working branch — the prohibition is the default branch, not committing.
  • Never invent a UI label, a default value, a parameter name, or a behavior. Every concrete claim is verified in Step 6 or surfaced as an open question.
  • Never invent or generate a screenshot. Name the screenshot that is needed and say where it goes.
  • An area reference file may add facts and narrow choices. It may never override the style guide, content types, cumulative-docs rules, or the approval gates.
  • **未经明确批准,绝不写入文件或打开 pull request。**参见审批门禁。这与 baseline 自身的声明一致:其中的约定不是要求自行 push 或打开 pull request 的指令。Step 3 中创建工作 branch 是唯一的例外,因为空的本地 branch 不会改变任何内容,并且可以撤销。
  • **绝不在默认 branch 上 commit 或写入内容。**Step 3 会先切换到工作 branch,然后才进行其他操作。通过 gate 2 后,在该工作 branch 上 commit——禁止的是默认 branch,而不是 commit 这一操作。
  • 绝不虚构 UI 标签、默认值、参数名或行为。每项具体声明都必须在 Step 6 中核验,或作为未决问题明确列出。
  • 绝不虚构或生成截图。说明需要哪张截图以及它的放置位置。
  • 区域 reference file 可以补充事实并缩小可选范围,但绝不能覆盖 style guide、content types、cumulative-docs 规则或审批门禁。

Inputs

输入

$ARGUMENTS
is a doc issue URL or
owner/repo#number
, a product pull request, a page path, or a free-text description. If empty, ask what needs documenting.
$ARGUMENTS
是文档 issue URL 或
owner/repo#number
、产品 pull request、页面路径或自由文本描述。如果为空,询问需要编写什么文档。

Step 1: Resolve paths

Step 1:解析路径

Do this once per machine, then reuse. Resolve in this order and stop at the first hit: environment variable, then
~/.config/elastic-docs/docs-draft-feature-docs.local.yml
, then ask.
Ask means ask. Do not clone a repo to fill a missing path, and do not create a temporary checkout. You may propose an existing path you found on disk, but the user has to confirm it before it counts as a hit. A clone you make for this run is the wrong tree: it is not the writer's working copy, it takes minutes, and you will correctly refuse to cache it, which means the next run pays the same cost. If no existing clone is on the machine, stop and wait for one.
A path you will not write to the config is not a resolved path. Keep asking. Do not proceed on a checkout you refuse to cache, and do not skip the write because the path looks temporary — if it looks temporary, it is the wrong path. Skipping the write is what makes "once per machine" false.
The config file uses one key per row of the table below, named after the variable in lower snake case, so
$DOCS_CONTENT_ROOT
is
docs_content_root
. Use those exact keys when writing it back, so a later hand-edit and a first run agree:
yaml
docs_content_root: /path/to/docs-content
kibana_root: /path/to/kibana
editorial_preferences_path: /path/to/preferences.md   # optional
docs_pitfalls_path: /path/to/pitfalls.md              # optional
PathVariableNeeded for
docs-content clone
$DOCS_CONTENT_ROOT
The baseline, navigation, snippets, and the files you edit. Always required
Product repo clones
$KIBANA_ROOT
,
$ELASTICSEARCH_ROOT
, others as needed
Verifying claims at
HEAD
in Step 6, and as the working tree when the product repo owns the page
Pitfalls checklist
$DOCS_PITFALLS_PATH
Optional. A personal list of doc-shaped mistakes to sweep for
Editorial preferences
$EDITORIAL_PREFERENCES_PATH
Optional. Prose-craft preferences, complementary to the style guide. Consumed in Step 7 and again in Step 9b. Can point at
references/ste-overlay.md
or at the writer's own file
The last two rows are per-writer, not per-area. They tune how one person drafts, which is why they are opt-in and why the overlay that ships with this skill stays off until pointed at. Area reference files are the opposite: facts about a docs area that every writer needs, so Step 2 loads them automatically. Never move a preference into an area file, or an area fact into a preference file.
Existing files stay where they are — record the path, never move or overwrite. Write the resolved paths back to the config so later runs skip this step. Do not hard-code a home directory or a username anywhere. The same rule applies when a later step needs a product repo that was not resolved here: ask, then write it back. Never clone it in.
A product repo plays one of two roles, and confusing them wastes a whole pass. Usually it is read-only: you verify claims there and write the page in docs-content. Sometimes it owns the page and is where the edit lands, because reference content often lives in the product repo's own
docs/
tree with its own
docset.yml
,
toc.yml
, and
redirects.yml
. Step 4e settles which, and a published URL is not evidence:
elastic.co/docs/reference/kibana/
publishes from
elastic/kibana
, not from docs-content.
在每台机器上执行一次,然后复用。按以下顺序解析,找到第一个命中项即停止:环境变量、
~/.config/elastic-docs/docs-draft-feature-docs.local.yml
,然后询问。
**“询问”指的就是询问。**不要为了补齐缺失路径而 clone 仓库,也不要创建临时 checkout。你可以提议在磁盘上发现的现有路径,但必须由用户确认后,它才算命中项。为本次运行创建的 clone 是错误的目录树:它不是作者实际工作的副本,而且创建需要数分钟;你也会正确地拒绝缓存它,这意味着下次运行仍需付出同样的成本。如果机器上不存在现有 clone,请停止并等待用户提供。
未写入配置的路径不算已解析路径。继续询问。不要在拒绝缓存的 checkout 上继续,也不要因为路径看起来是临时的就跳过写入——如果它看起来是临时的,那说明它是错误的路径。跳过写入会让“每台机器一次”名不副实。
配置文件在下表中每行使用一个 key,并以对应变量的小写 snake case 命名,因此
$DOCS_CONTENT_ROOT
对应
docs_content_root
。写回配置时使用这些准确的 key,使后续手动编辑与首次运行的结果一致:
yaml
docs_content_root: /path/to/docs-content
kibana_root: /path/to/kibana
editorial_preferences_path: /path/to/preferences.md   # optional
docs_pitfalls_path: /path/to/pitfalls.md              # optional
路径变量用途
docs-content clone
$DOCS_CONTENT_ROOT
基线、导航、snippets 和你要编辑的文件。始终必需
产品仓库 clone
$KIBANA_ROOT
、
$ELASTICSEARCH_ROOT
,以及其他按需使用的变量
在 Step 6 中对照
HEAD
核验声明,以及在产品仓库拥有该页面时将其作为工作目录
陷阱检查清单
$DOCS_PITFALLS_PATH
可选。个人维护的文档形态错误清单,用于全面检查
编辑偏好
$EDITORIAL_PREFERENCES_PATH
可选。关于文字表达的偏好,与 style guide 互补。在 Step 7 和 Step 9b 中使用。可以指向
references/ste-overlay.md
或作者自己的文件
最后两行是按作者划分,而不是按区域划分。它们用于微调单个作者的写作方式,因此采用可选方式,本 skill 附带的 overlay 在明确指向它之前不会启用。区域 reference files 恰好相反:它们保存每个作者都需要了解的区域事实,因此 Step 2 会自动加载它们。绝不要把偏好移入区域文件,也不要把区域事实移入偏好文件。
现有文件保留在原位置——记录路径,绝不移动或覆盖。将解析后的路径写回配置,以便后续运行跳过此步骤。绝不在任何地方硬编码 home directory 或 username。当后续步骤需要此处未解析的产品仓库时,先询问,然后写回配置。绝不 clone 它。
产品仓库承担两种角色之一,混淆二者会浪费一整轮工作。通常它是只读的:你在这里核验声明,并在 docs-content 中编写页面。有时它拥有该页面,实际编辑会落在那里,因为 reference 内容经常位于产品仓库自己的
docs/
目录树中,并带有自己的
docset.yml
、
toc.yml
和
redirects.yml
。由 Step 4e 确定使用哪一种。已发布 URL 不能作为证据:
elastic.co/docs/reference/kibana/
从
elastic/kibana
发布,而不是从 docs-content 发布。

Step 2: Load the baseline and the area file

Step 2:加载基线和区域文件

Loading the baseline is unconditional. It runs whether or not an area file exists, and an area file cannot switch it off.
$DOCS_CONTENT_ROOT/AGENTS.md
$DOCS_CONTENT_ROOT/AI.md                       # governs AI-assisted contributions, which is what this skill produces
$DOCS_CONTENT_ROOT/contribute-docs/            # follow the links AGENTS.md gives you
$DOCS_CONTENT_ROOT/frontmatter.config.yml
AI.md
is not optional reading. It holds the drafts this skill produces to the same bar as hand-written ones and puts the name on the pull request in charge of every word. Say so when you hand over the draft.
Then check
references/index.md
in this skill directory for the target area.
Naming the area takes the request in hand, so skim
$ARGUMENTS
first — the title and body, when it is an issue. That skim is not Step 4: the full intake, the open questions, and the decision about whether to document at all still happen there, after the branch exists. Read just enough to know which file to open.
  • A specialist skill is registered for the area — hand off and stop. Do not draft a second opinion.
  • An area file exists — load it. It tells you the area's boundary, which product source settles a fact, the local conventions, which navigation file to edit, and the known traps. It does not list pages; use
    search_docs
    for that. Check its age and any
    status:
    entry before relying on it, as below.
  • Neither exists — continue anyway. Derive conventions from sibling pages found through
    find_related_docs
    , and say in your output that no area file was available so the user knows what to add later.
A request can straddle two areas — two area files, or an area file and a specialist's territory. Split it: draft each part against the file that owns it, and delegate any specialist's part. Say which half went where, so nothing looks silently dropped.
Before routing to a specialist, confirm it is installed. Delegating to a skill that is not on the machine fails, and falling back to the area file or sibling pages beats stopping.
加载基线是无条件的。无论区域文件是否存在都会执行,而且区域文件无法将其关闭。
$DOCS_CONTENT_ROOT/AGENTS.md
$DOCS_CONTENT_ROOT/AI.md                       # governs AI-assisted contributions, which is what this skill produces
$DOCS_CONTENT_ROOT/contribute-docs/            # follow the links AGENTS.md gives you
$DOCS_CONTENT_ROOT/frontmatter.config.yml
AI.md
不是可选阅读材料。它要求本 skill 生成的草稿达到与人工编写草稿相同的标准,并要求在 pull request 中写明对每个字词负责的作者姓名。交付草稿时必须说明这一点。
然后检查此 skill 目录中的
references/index.md
,查找目标区域。
确定区域时需要结合当前请求,因此先快速浏览
$ARGUMENTS
——如果输入是 issue,则查看其标题和正文。这不是 Step 4:完整的输入分析、未决问题以及是否需要编写文档的决定,仍要在创建 branch 之后进行。此处只需阅读足够的信息,以确定应打开哪个文件。
  • 该区域已注册 specialist skill——移交给它并停止。不要起草第二份意见。
  • 区域文件存在——加载它。它会说明该区域的边界、哪个产品源码能够确定事实、本地约定、需要编辑哪个导航文件,以及已知陷阱。它不列出页面;使用
    search_docs
    查找页面。按照下文说明检查其时效和
    status:
    条目,然后再依赖它。
  • 两者都不存在——仍可继续。通过
    find_related_docs
    找到同级页面并从中推导约定,并在输出中说明没有可用的区域文件,让用户知道之后可以补充什么。
一个请求可能横跨两个区域——涉及两个区域文件,或一个区域文件与某个 specialist 的领域。将请求拆分:每一部分都根据负责它的文件起草,并将 specialist 负责的部分移交给它。说明各部分分别去了哪里,避免任何内容被无声忽略。
将请求移交给 specialist 前,先确认它已安装。移交给机器上不存在的 skill 会失败,而退回到区域文件或同级页面,比直接停止更好。

How much to trust the area file

应多大程度信任区域文件

An area file is a snapshot, so check its age before relying on it. Read the frontmatter, get today's date with
date +%F
, and compare:
verified
is
The file's paths and labels areSo
Within 90 daysCurrent enough to act onUse them, and still verify any concrete claim in Step 6
Older than 90 daysHints, not factsConfirm each path and label against the repo or the MCP before you use it, and say in the output how old the file is
Ninety days is roughly a release and a half. A file older than that predates at least one minor, which is long enough for a plugin directory to move. Report the age either way, so a reader of your output knows what the draft rested on.
If the frontmatter carries a
status:
key, the area has an in-flight transition.
Read that entry in
references/status.md
, then resolve its tracking issues with
gh issue view <n> --repo elastic/docs-content-internal --json state,title,body
. The issue wins over the entry and the entry wins over the area file, because that is the order they go stale in. When the expiry condition has already been met — the issue is closed — say so and open a pull request to remove the entry rather than following it.
An entry may instead carry a fast path: a manual confirmation that the issue is still open, with no date attached. While that line is present, skip the live
gh issue view
call and follow the entry as if you'd just resolved it — but say in the output that you took the fast path rather than checking live. It stays valid until whoever added it removes it, so if a run finds evidence it may be stale (the issue title or linked pull requests suggest it closed), say so rather than trusting the fast path blindly.
Never carry a date out of
status.md
into a draft. The entries name events rather than dates for exactly this reason, and a release date is
docs-applies-to-tagging
's answer from the plugin config, not this skill's.
区域文件是一份快照,因此依赖它之前应检查其新旧程度。读取 frontmatter,使用
date +%F
获取当天日期,然后进行比较:
verified
距今时间
文件中的路径和标签应当如何处理
90 天以内足够新,可以据此操作使用它们,同时仍在 Step 6 中核验每项具体声明
超过 90 天只能作为提示,不能视为事实使用前逐项对照仓库或 MCP 确认路径和标签,并在输出中说明文件有多旧
90 天大致相当于一个半版本。超过 90 天的文件早于至少一个 minor 版本,而插件目录在此期间可能已经移动。无论如何都要报告文件年龄,让输出读者知道草稿依据了哪些内容。
**如果 frontmatter 包含
status:
key,说明该区域正在进行中的迁移。**读取
references/status.md
中的对应条目,然后使用
gh issue view <n> --repo elastic/docs-content-internal --json state,title,body
解析其跟踪 issue。当 issue 已关闭,即满足过期条件时,说明情况,并打开 pull request 移除该条目,而不是继续遵循该条目。
条目也可能提供快速路径:人工确认 issue 仍然开放,但不附带日期。在该行存在期间,跳过实时
gh issue view
调用,并像刚刚解析完 issue 一样遵循该条目——但要在输出中说明采用了快速路径,而不是进行了实时检查。该路径一直有效,直到添加它的人将其移除;因此,如果某次运行发现证据表明它可能已经过期,例如 issue 标题或关联 pull request 暗示它已关闭,应明确说明,而不是盲目信任快速路径。
绝不要把
status.md
中的日期带入草稿。这些条目只命名事件而不记录日期,正是因为发布日期应由插件配置决定,也就是
docs-applies-to-tagging
的职责,而不是本 skill 的职责。

What an area file cannot ask for

区域文件不能凌驾于哪些内容之上

The precedence rule itself is in Constraints. What it does not spell out is which instructions trip it, because two kinds arrive dressed as local house style:
  • Formatting that contradicts the guide, such as title-case headings where the guide says sentence case. Follow the guide.
  • Boilerplate, meaning any convention that puts the same sentence, admonition, or requirement at the top of every page in the area. That is a "place each detail once" violation, and the style guide separately warns against loading a page with admonitions, so the convention usually fails twice. Work out what it is trying to achieve and do that properly instead: a version or deployment requirement is an
    applies_to
    badge, which
    docs-applies-to-tagging
    owns, and a caveat that matters everywhere belongs on the one page that owns the concept, with the others linking to it.
In both cases apply whatever the file legitimately adds, follow the baseline where they disagree, and tell the user which instruction you did not follow and why. Do not apply an override silently. An area file reads as authoritative precisely because it is usually right, which is what makes the rare bad instruction in one worth naming out loud.
One convention looks like boilerplate and is not: a shared snippet, included under the H1 of a section's landing pages, that tells the reader which of two similar systems the section documents. No
applies_to
value can say that, and because the wording lives once in the snippet, the include places nothing twice. Follow it when the area file records it, and only on the pages the area file names. The same note on every page in the section is boilerplate again: it repeats itself page after page, and the first sentence naming the system does the job better. The exception is that narrow — a snippet whose job is to restate a version, deployment, lifecycle, or caveat is still boilerplate however it is included, because each of those already has a proper home.
优先级规则本身已在约束中说明。区域文件没有明确写出的是,哪些指令会触发该规则,因为有两类内容会伪装成本地 house style:
  • 与指南冲突的格式,例如指南要求使用 sentence case 标题,区域文件却要求 title-case 标题。遵循指南。
  • Boilerplate,即把同一句话、 admonition 或要求放在该领域每个页面顶部的约定。这是“每项细节只放置一次”的违规行为,style guide 也单独警告不要让页面充满 admonitions,因此这种约定通常会同时违反两项规则。弄清它想实现的目标,并改用正确方式完成。例如,版本或部署要求应使用
    applies_to
    badge,由
    docs-applies-to-tagging
    负责;而处处重要的 caveat 应放在拥有该概念的唯一页面中,其他页面链接到该页面。
在这两种情况下,应用区域文件合法补充的内容,在发生冲突时遵循 baseline,并告诉用户没有遵循哪项指令及其原因。**不要无声地应用 override。**区域文件读起来具有权威性,正是因为它通常是正确的,这也正是少数错误指令值得明确指出原因。
**有一种约定看起来像 boilerplate,但实际上不是:**在某个章节的 landing 页面 H1 下包含一个共享 snippet,用于告诉读者该章节记录的是两个相似系统中的哪一个。没有任何
applies_to
值能够表达这种信息,而且由于措辞只存在于 snippet 中一次,include 不会重复放置任何内容。当区域文件记录了这种约定时,应遵循它,但仅限于区域文件明确指定的页面。同一条说明出现在该章节的每个页面上时,它又是 boilerplate:它会在每个页面中反复出现,而第一句说明系统名称就能完成这项工作。例外范围非常狭窄——如果 snippet 的作用是重述版本、部署、生命周期或 caveat,那么无论以何种方式包含,它仍然是 boilerplate,因为这些内容都已有合适的归属位置。

Step 3: Create the working branch

Step 3:创建工作 branch

Create it before reading the issue, so no draft, edit, or
toc.yml
change can land on the default branch. Unlike a file write or a pull request, a new local branch is empty and reversible, so this is not gated — but report what you created and what you based it on.
Follow
references/branch-setup.md
for the commands.
The four rules it enforces:
  • Resolve the canonical remote by URL, matching
    github.com/elastic/
    , rather than trusting the name
    origin
    . On a fork,
    origin/main
    is the writer's own stale copy, and basing on it starts the work from old content with nothing looking wrong.
  • Resolve the default branch off that remote instead of assuming
    main
    , and base on the remote-tracking ref rather than the local branch of the same name.
  • Stop and ask on an uncommitted tree, a non-default branch, or a detached HEAD. Never stash, reset, or discard anything to clear the way.
  • Pass
    --no-track
    when creating the branch, so a stray
    git pull
    cannot merge the default branch into the work.
Do this in
$DOCS_CONTENT_ROOT
now. When Step 4e names a second repo, branch there at that point the same way. If the run ends without writing anything — Step 4c concluded no docs are needed, or the user declined at gate 1 — switch back and delete the branch.
在读取 issue 之前创建它,确保草稿、编辑或
toc.yml
变更都不会落到默认 branch 上。与写入文件或打开 pull request 不同,新的本地 branch 是空的且可以撤销,因此这一步不受门禁限制——但要报告创建了什么,以及它基于什么。
**命令参见
references/branch-setup.md
。**它规定四条规则:
  • 通过 URL 解析规范 remote,匹配
    github.com/elastic/
    ,而不是信任名为
    origin
    的 remote。在 fork 上,
    origin/main
    是作者自己的过期副本,基于它开始工作会从旧内容起步,而且表面上不会显现任何问题。
  • 从该 remote 解析默认 branch,而不是假定它是
    main
    ;基于 remote-tracking ref,而不是同名的本地 branch。
  • 如果工作树有未提交内容、当前不是默认 branch,或处于 detached HEAD 状态,则停止并询问。绝不 stash、reset 或丢弃任何内容来清理环境。
  • 创建 branch 时传入
    --no-track
    ,防止误执行
    git pull
    时将默认 branch 合并进工作 branch。
现在在
$DOCS_CONTENT_ROOT
中执行此操作。当 Step 4e 确定第二个仓库时,再以相同方式在那个仓库中创建 branch。如果运行结束时没有写入任何内容——例如 Step 4c 得出不需要文档,或用户在 gate 1 拒绝继续——则切回原 branch 并删除创建的 branch。

Step 4: Understand the request

Step 4:理解请求

4a. Read the issue and the code

4a. 阅读 issue 和代码

For a doc issue, read it with
gh issue view <n> --repo <owner/repo> --json title,body,comments,labels
. Extract the writer brief — scope, target pages, acceptance criteria, suggested work — and track every deliverable through to the draft as addressed, deferred, or blocked.
For any linked implementation pull request, read the metadata and the diff:
gh pr view <n> --repo <owner/repo> --json title,body,state,mergedAt,baseRefName,files
gh pr diff <n> --repo <owner/repo>
Pass the number with
--repo
, or a full URL. The shorthand
gh pr view elastic/kibana#12345
does not work —
gh
reads it as a branch name.
One pull request is rarely the whole change. Search for siblings before concluding: by the same author around the same date, by shared issue reference, by the feature flag or identifier name, and by the linked epic. A follow-up pull request that renamed the setting makes the first diff misleading.
对于文档 issue,使用
gh issue view <n> --repo <owner/repo> --json title,body,comments,labels
读取它。提取作者简报——范围、目标页面、验收标准和建议工作——并将每项交付内容持续跟踪为已处理、已推迟或受阻。
对于任何关联的实现 pull request,读取其元数据和 diff:
gh pr view <n> --repo <owner/repo> --json title,body,state,mergedAt,baseRefName,files
gh pr diff <n> --repo <owner/repo>
传入编号时加上
--repo
,或者传入完整 URL。简写形式
gh pr view elastic/kibana#12345
不起作用——
gh
会将其解析为 branch 名称。
**一个 pull request 很少能代表全部变更。**得出结论前先搜索相关变更:查找同一作者在大致相同时间创建的 PR、共享的 issue 引用、feature flag 或标识符名称,以及关联的 epic。后续 pull request 如果重命名了设置,最初的 diff 就会产生误导。

4b. Classify the open questions

4b. 对未决问题进行分类

Sort every unknown into resolved, unresolved, or researchable. Answer the researchable ones yourself in Step 6. Ask the user the unresolved ones and do not draft until they are answered, or until the user says to proceed on stated assumptions, which you then record in the output.
Ask for an audience you can actually write to. "Operators" is not enough. Get the technical level, the role, and whether this is a day-0 task or something a user reaches later.
将每个未知项分为已解决、未解决或可研究。可研究的问题由你在 Step 6 中自行解决。向用户询问未解决问题,并且在得到回答之前不要起草,除非用户表示可以根据既定假设继续;如果是后者,在输出中记录这些假设。
询问你实际能够面向的读者受众。“运维人员”还不够。需要了解其技术水平、角色,以及这是 day-0 任务还是用户日后才会接触的任务。

4c. Decide whether to document at all

4c. 判断是否需要编写文档

The changeWhat to do
Invisible or automatic, no new setting, step, or user choiceRecommend no page change. Stop and confirm. Release notes come from the changelog tooling, so never hand-edit them here
Already documented by the product pull requestShow what it covers and narrow or drop the request
A page states something that is now falseReal gap. Draft it
A workflow gained a step or option users would otherwise missReal gap. Draft it
A page is deliberately general and the request adds specificsUsually not a gap. Say so
A page documents something the current version removedReal gap, but not a deletion. Scope it — see below
Concluding that nothing needs documenting is a valid result. Report it and stop rather than finding something to write.
"Remove X" is a scoping request, not a deletion. When a feature, field, or setting goes away, the content usually stays — the docs are cumulative, and readers on the versions that still have it still need it. Keep the content and add a
removed
tag, which
docs-applies-to-tagging
owns.
The removal scenarios name two cases where the content can go instead: the feature was only ever beta or technical preview, or it only ever existed in an unversioned product. Both are permissions rather than instructions, so scoping is never the wrong answer and deleting sometimes is. Check the case against those scenarios rather than inferring it, and when the feature's lifecycle is not one they name —
experimental
, for instance — scope it and say which reading you took, rather than deleting on an analogy you made yourself.
This is the request shape where doing literally what the issue asks is most often wrong. "Remove the tags section" describes the product change, not the edit to make, and deleting the section produces a clean-looking pull request that quietly takes documentation away from readers on supported versions.
变更应采取的操作
不可见或自动发生,没有新增设置、步骤或用户选择建议不修改页面。停止并确认。Release notes 来自 changelog 工具,因此绝不在这里手动编辑
产品 pull request 已经记录了此内容展示其覆盖范围,并缩小或放弃当前请求
某个页面陈述的内容现在已不再正确存在真实缺口。起草文档
某个工作流新增了用户否则会错过的步骤或选项存在真实缺口。起草文档
某个页面有意保持宽泛,而请求增加了具体细节通常不存在缺口。明确说明这一点
某个页面记录了当前版本已经移除的功能存在真实缺口,但不是删除。对其进行范围界定——参见下文
得出“不需要编写文档”的结论也是有效结果。报告结论并停止,而不是一定要找出一些内容来写。
**“移除 X”是一项范围界定请求,而不是删除请求。**当功能、字段或设置被移除时,内容通常会保留——文档具有累积性,仍在使用这些功能的旧版本读者依然需要相关说明。保留内容并添加
removed
tag,由
docs-applies-to-tagging
负责处理。
移除场景中有两种情况可以删除内容:该功能从未正式发布过,只处于 beta 或 technical preview 阶段;或者它只存在于未版本化的产品中。这两种情况是许可,而不是指令,因此范围界定始终是正确做法,而删除有时可行。将实际情况与这些场景逐一对照,不要自行类推。当功能的生命周期不在它们明确列出的范围内时,例如
experimental
,应进行范围界定,并说明你对它的理解,而不是通过类比自行决定删除。
这正是直接照 issue 要求执行最容易出错的情形。“移除 tags section”描述的是产品变更,而不是要执行的编辑;删除该 section 会产生一个看似简洁的 pull request,却悄悄从仍受支持版本的读者那里移除了文档。

4d. Establish the availability floor

4d. 确定可用性下限

A backport label is not a shipped release. Neither is a merged pull request. Establish which released version actually carries the change before any version reaches the page, and say which evidence you used. Collect the deployment answers too — stack, serverless, and the deployment types — since the content is scoped, not versioned.
The code declares the lifecycle; the request only describes it. When a registration carries a stability or maturity field, that field is the answer and it outranks how the request reads — a release-note label, a bare version number, and "on by default" each describe something that shipped, and none of them mean generally available. Read the declared value and pass it to
docs-applies-to-tagging
rather than mapping it yourself.
Availability given as a patch release is a question, not a value. A patch number does not reach the page as written, and resolving it sometimes removes the need for a tag entirely, so hand it over rather than deciding.
**Backport label 不等于已发布的版本。**已合并的 pull request 也不等于已发布的版本。在页面上写入任何版本信息之前,确定实际包含该变更的已发布版本,并说明使用了哪些证据。同时收集部署方式的答案——stack、serverless 以及部署类型——因为内容是按适用范围界定的,而不是按版本逐项罗列的。
**代码声明生命周期;请求只描述生命周期。**当注册信息包含 stability 或 maturity 字段时,该字段就是答案,其优先级高于请求的表述方式。Release-note label、单纯的版本号和“默认启用”都只描述某项内容已经发布,但均不表示 generally available。读取声明的值并将其传给
docs-applies-to-tagging
,不要自行映射。
**以 patch release 形式给出的可用性是一个问题,而不是一个值。**Patch 编号不能原样出现在页面上,而且解析它有时会完全消除添加 tag 的必要,因此应将它交给下游处理,而不是自行决定。

4e. Confirm which repos own the work

4e. 确认由哪些仓库负责工作

Do not assume docs-content, and do not assume a single owner. Narrative user documentation lives there, but reference content often lives in the product repo's own docs tree, so one request routinely splits across two repos — a Workflows change can need authoring content in docs-content, a setting in
kibana/docs/reference/
, and a connector page in the same Kibana tree.
Split it the way Step 2 splits a request across two areas: assign each deliverable to the repo that owns it, and say which half went where so nothing looks silently dropped. Then run Step 3 in each newly named repo, resolving its canonical remote and base separately.
Then order the halves, because this decides more than where the branch goes:
  • A page in repo A links to a page you are adding in repo B, so B merges and publishes first. Otherwise A ships a link to a target that does not exist yet. Cross-repo links do not resolve against your local checkout, so nothing local will catch it.
  • Neither side links to new content in the other, so the order is free and they can go in parallel.
State the order and the reason at the first approval gate. When the order forces a wait, say so plainly — the second pull request is blocked until the first publishes, not merely until it merges.
不要假定工作属于 docs-content,也不要假定只有一个归属仓库。叙述性用户文档位于 docs-content,但 reference 内容经常位于产品仓库自己的 docs 目录树中,因此一个请求经常会拆分到两个仓库——Workflows 变更可能需要在 docs-content 中编写叙述内容,在
kibana/docs/reference/
中编写设置说明,并在同一个 Kibana 目录树中编写 connector 页面。
按照 Step 2 拆分跨区域请求的方式进行拆分:将每项交付内容分配给拥有它的仓库,并说明各部分分别去了哪里,避免任何内容被无声忽略。然后在每个新确定的仓库中执行 Step 3,分别解析其规范 remote 和基础分支。
接着确定各部分的顺序,因为顺序决定了 branch 应位于何处:
  • 仓库 A 中的页面链接到仓库 B 中正在新增的页面,因此 B 必须先合并并发布。否则 A 发布时,其链接目标尚不存在。跨仓库链接无法通过本地 checkout 解析,因此任何本地检查都不会发现此问题。
  • 如果双方都不链接到对方新增的内容,则顺序不受限制,可以并行处理。
在第一个审批门禁处说明顺序及其原因。当顺序导致必须等待时,直接说明:第二个 pull request 会一直受阻,直到第一个发布,而不仅仅是直到第一个合并。

Step 5: Place the content

Step 5:放置内容

The baseline says find the canonical home and place each detail once. Start from the assumption that an existing page should absorb this, and make adding a page the deliberate exception.
  1. Search the published corpus first, with
    search_docs
    on the feature name and on the reader's task, then
    find_related_docs
    for the hub and siblings, then
    check_docs_coherence
    on the topic. Read the best candidates with
    get_document_by_url
    and
    includeBody: true
    , and use
    analyze_document_structure
    to see what each one's parents are.
  2. Then grep the local trees for the feature name and its identifiers, in
    $DOCS_CONTENT_ROOT
    and the docs tree of every product repo Step 4e named. This catches what the MCP cannot see: pages that are
    hidden:
    , unpublished, or in flight. A grep limited to docs-content cannot see
    kibana/docs/
    , so it reports a gap that is already filled and you place a second copy.
  3. List the candidate pages you found, with what each one currently says and its URL or path.
  4. Propose the lightest change that closes the gap: a sentence in place, then a section, then a new page, in that order of preference.
  5. Pause for sign-off when the information architecture is ambiguous, when the change spans several pages, or when you are proposing a new page.
For content type, hand the proposal to
docs-content-type-checker
in classify mode and start from the matching template in
contribute-docs/content-types/_snippets/templates/
. That directory carries how-to, overview, troubleshooting, and tutorial; changelog has no template there, so work from the content-type guide itself for those rather than bending one of the four. When no content type genuinely fits, say so explicitly, describe the structure you are using instead, and why — do not force the page into the nearest type in silence.
Baseline 要求找到规范归属位置,并让每项细节只出现一次。开始时应假定由现有页面吸收这些内容,而新增页面应是经过深思熟虑后才采用的例外。
  1. 首先搜索已发布语料库,使用
    search_docs
    搜索功能名称和读者任务,再使用
    find_related_docs
    查找 hub 和同级页面,然后使用
    check_docs_coherence
    检查该主题。使用
    get_document_by_url
    和
    includeBody: true
    读取最佳候选项,并使用
    analyze_document_structure
    查看每个候选页面的父级页面。
  2. 然后 grep 本地目录树,在
    $DOCS_CONTENT_ROOT
    以及 Step 4e 确定的所有产品仓库的 docs 目录树中搜索功能名称及其标识符。这样可以发现 MCP 看不到的内容:
    hidden:
    页面、未发布内容或正在开发中的内容。仅搜索 docs-content 无法看到
    kibana/docs/
    ,因此会错误地报告一个实际上已经填补的缺口,并放置第二份重复内容。
  3. 列出找到的候选页面,并说明每个页面当前的内容及其 URL 或路径。
  4. 提出填补缺口所需的最轻量变更:优先添加一个句子,然后是新增一个 section,最后才是新增页面。
  5. 当信息架构存在歧义、变更跨越多个页面,或你提议新增页面时,暂停并请求确认。
对于 content type,将提议交给
docs-content-type-checker
的 classify 模式,并从
contribute-docs/content-types/_snippets/templates/
中选择匹配的模板。该目录包含 how-to、overview、troubleshooting 和 tutorial 的写法;changelog 在那里没有模板,因此应直接遵循 content-type 指南处理,不要强行套用四种模板之一。当没有任何 content type 确实适合时,明确说明这一点,描述所使用的结构及其原因,不要默默地强行使用最接近的类型。

Step 6: Enumerate the claims, then verify them

Step 6:列举声明,然后核验

Do this in two passes, in this order. Enumerate first, or you verify the few facts you happened to notice and wave the rest through.
Pass one. List every concrete claim the draft will make: each UI string, menu path, field name, identifier, default value, limit, permission, and behavior.
Pass two. Verify each one against the product source at
HEAD
in the relevant repo. Not the issue body, not the pull request description, and not the diff — a diff shows one change, while
HEAD
shows what users will actually meet. The area file's Source of truth section says which paths matter; the implementing pull request is supporting evidence, not the final word.
Confirm the clone is current before trusting it. Fetch the product repo's remote-tracking ref and compare its date against the merge date of the implementing pull request. A clone a few days behind reports removed code as still present and new code as missing, and it does so silently — a confident wrong answer with nothing to flag. If it is behind the change you are verifying, fetch it or read the file through the GitHub API at
?ref=main
.
Verify the integration, not just the component. A feature built on a shared package inherits everything that package documents, but the host app decides which capabilities are switched on. Check the call sites and the options the host passes. A capability the package ships and the host leaves disabled will otherwise read as verified.
Because these docs are cumulative, also confirm each claim holds for the earlier supported versions the page covers. A statement that is true only on
main
will be wrong for most readers.
Report the result as three lists: verified with where you checked, contradicted with what you found instead, and unverifiable. Unverifiable facts go in the output as open questions. They never go in the draft as prose.
Then sweep the pitfalls checklist from Step 1, if there is one.
分两轮按顺序执行。先列举,否则只会核验碰巧注意到的事实,并让其他事实直接通过。
**第一轮。**列出草稿将做出的每项具体声明:每个 UI 字符串、菜单路径、字段名、标识符、默认值、限制、权限和行为。
**第二轮。**在相关仓库中对照
HEAD
处的产品源码核验每项声明。不要依赖 issue 正文、pull request 描述或 diff——diff 只显示一次变更,而
HEAD
显示用户实际会遇到的内容。区域文件的 Source of truth 部分会指出哪些路径很重要;实现该功能的 pull request 是辅助证据,而不是最终依据。
**信任 clone 之前,先确认它是最新的。**Fetch 产品仓库的 remote-tracking ref,并将其日期与实现该功能的 pull request 合并日期进行比较。落后数天的 clone 会把已经移除的代码报告为仍然存在,把新代码报告为缺失,而且不会给出任何提示——最终会形成一个自信但错误的答案,而且没有任何异常标记。如果 clone 落后于待核验的变更,应 fetch 它,或通过 GitHub API 使用
?ref=main
读取文件。
**核验集成情况,而不只是组件本身。**基于共享 package 构建的功能会继承该 package 记录的所有行为,但 host app 决定启用了哪些能力。检查调用点以及 host 传入的选项。否则,package 已提供但 host 未启用的能力会被误写为已核验。
由于文档具有累积性,还要确认每项声明对页面涵盖的较早受支持版本同样成立。仅在
main
上成立的陈述,对大多数读者而言都是错误的。
将结果报告为三个列表:已核验项及其检查位置、相互矛盾项及实际发现、无法核验项。无法核验的事实作为未决问题列入输出,绝不能作为陈述写入草稿。
然后,如果存在 pitfalls checklist,就按 Step 1 的要求进行全面检查。

Step 7: Draft

Step 7:起草

Apply the baseline's core principles and style guide as you write. Drafting freely and cleaning up in Step 9 produces a page that passes the linters and still reads like a changelog entry. The rubric your draft will be measured against in Step 9 is the review checklist in
docs-review-pr
, at
references/review-criteria.md
in that skill — read it if you want to know what the reviewer will look for.
Three moves the baseline leaves to your judgment:
  • Order for progressive disclosure. What it is, then how to use it, then the edge cases. The content-type template gives you the sections; the sequence and weight inside them are yours.
  • Translate the framing you were handed. The input describes an implementation. Write what a reader can now do, see, configure, or avoid. Nothing downstream will do this for you.
  • Cut what does not serve the reader's task, including anything that exists only because the issue mentioned it.
Open on the reader's job, not on the control. A new option or mode gets a heading and a first sentence that name what the reader can now do —
View documents as JSON
, not
Switch the view mode
. The control goes in the how-to sentence that follows. The labels, defaults, and ranges you verified in Step 6 are a checklist the draft must not contradict; they are not an outline, and a parenthetical list of every verified action label is still an outline. Step 9b checks this line by line, so writing it this way the first time is cheaper than rewriting it there.
If
$EDITORIAL_PREFERENCES_PATH
resolved in Step 1, read that file now and apply it to the prose you write. It is additive prose craft, so it never overrides the style guide, content types, or an area file — where it conflicts with the baseline, the baseline wins, and say so rather than silently following the preference. Apply it only to new prose: do not restyle surrounding copy you were not otherwise changing. An optional Simplified Technical English overlay ships at
references/ste-overlay.md
; it stays off unless the variable points at it.
Frontmatter follows
frontmatter.config.yml
and the conventions in the area file. Check the nearest
_snippets/
directory before writing shared prose. For
applies_to
values and badge placement, use
docs-applies-to-tagging
— collect the version, lifecycle, and deployment answers, and let that skill decide the tags, including whether the page needs any.
Where a screenshot is needed, name it and describe what it should show. Never generate one.
在写作过程中应用 baseline 的核心原则和 style guide。自由起草后再到 Step 9 清理,会得到一个虽然能通过 linter、但读起来仍像 changelog 条目的页面。草稿将在 Step 9 中依据的评估标准,是
docs-review-pr
中的 review checklist;如需了解 reviewer 会检查什么,请读取该 skill 的
references/review-criteria.md
。
Baseline 留给判断力的三项处理:
  • **按渐进披露原则排序。**先说明它是什么,再说明如何使用,最后说明边缘情况。Content-type 模板提供章节;章节内部的顺序和权重由你决定。
  • **转换所获得的表述框架。**输入描述的是一项实现。写出读者现在能够做什么、能看到什么、能够配置什么或能够避免什么。下游流程不会替你完成这项转换。
  • 删除无助于读者任务的内容,包括仅因 issue 提到而存在的内容。
**从读者要完成的任务开篇,而不是从控件开篇。**新选项或新模式应使用一个标题和第一句话,说明读者现在可以做什么,例如“将文档查看为 JSON”,而不是“切换视图模式”。控件应放在接下来的操作说明中。已核验的标签、默认值和范围是草稿不得与之矛盾的检查清单,但它们不是大纲;在括号中罗列所有已核验的操作标签,仍然属于大纲。Step 9b 会逐行检查这一点,因此从一开始就按此方式写作比之后重写更省成本。
如果 Step 1 已解析
$EDITORIAL_PREFERENCES_PATH
,现在读取该文件并将其中偏好应用于文案。它是对文字表达的补充,不能覆盖 style guide、content types 或区域文件;发生冲突时以 baseline 为准,并说明这一点,不要默默遵循偏好。只将其应用于新增文案;不要重新调整你原本不会修改的周边内容。可选的 Simplified Technical English overlay 位于
references/ste-overlay.md
;只有当该变量明确指向它时才启用。
Frontmatter 遵循
frontmatter.config.yml
以及区域文件中的约定。编写共享文案前,检查最近的
_snippets/
目录。对于
applies_to
值和 badge 位置,使用
docs-applies-to-tagging
——收集版本、生命周期和部署方式的答案,让该 skill 决定 tags,包括页面是否需要 tags。
需要截图时,说明截图名称及其应展示的内容。绝不生成截图。

Step 8: Navigation and links

Step 8:导航和链接

Add new pages to the right
toc.yml
. Navigation is per-docset and orchestrated by
docset.yml
, some sections have nested sub-tocs and some keep their whole tree inline, so confirm against the area file or the actual files rather than reasoning by analogy. The MCP cannot help here — navigation is not published. When the work spans repos, each repo has its own
toc.yml
,
docset.yml
, and
redirects.yml
, so update the one in the repo you are editing.
Add the page to its hub or index, add a short Related section, and resolve every outbound link with
get_document_by_url
. Moved, renamed, or deleted pages need
redirects.yml
— hand that to
docs-redirects
.
One class of link cannot resolve yet, and that is expected. A cross-repo link to a page you are adding in the other repo has no target until that pull request publishes. Do not treat it as broken, and do not drop it or point it at a placeholder. List it as a pending cross-repo link, name the pull request it waits on, and carry it into the ordering from Step 4e. Every other unresolved link is a real defect.
将新页面添加到正确的
toc.yml
。导航按 docset 组织,并通过
docset.yml
编排;部分 section 使用嵌套 sub-toc,部分则将整棵树内联保留,因此应根据区域文件或实际文件进行确认,不要类推。MCP 无法帮助处理此处——导航不会发布。当工作跨越多个仓库时,每个仓库都有自己的
toc.yml
、
docset.yml
和
redirects.yml
,因此要更新实际编辑所在仓库中的对应文件。
将页面添加到它的 hub 或 index,添加简短的相关内容 section,并使用
get_document_by_url
解析每一个出站链接。移动、重命名或删除的页面需要
redirects.yml
,将其交给
docs-redirects
。
**有一类链接目前无法解析,这是预期情况。**跨仓库链接到你正在另一个仓库中新增的页面时,在该 pull request 发布前没有目标。不要将其视为断链,也不要删除它或指向占位页面。将其列为待处理的跨仓库链接,说明它正在等待哪个 pull request,并将其纳入 Step 4e 中的排序。其他所有无法解析的链接都是实际缺陷。

Step 9: Validate

Step 9:验证

Step 9 runs in this order:
  1. 9b, before gate 1. You re-read every new line of the draft as the reader.
  2. 9c, before gate 1, only when the user asks. A fresh subagent tries to do the task from the page.
  3. 9d, after the gate 2 commit.
    docs-review-pr
    and the companion skills listed in 9a review the branch.
Call the companion skills rather than copying their rules into this file.
Step 9 按以下顺序执行:
  1. **9b,在 gate 1 之前。**将每一行新增草稿内容都作为读者的一行重新阅读。
  2. **9c,在 gate 1 之前,仅当用户提出要求时执行。**让一个全新的 subagent 尝试根据页面完成任务。
  3. **9d,在 gate 2 commit 之后。**由
    docs-review-pr
    及 9a 中列出的配套 skills 评审该 branch。
调用配套 skills,不要将它们的规则复制到此文件中。

9a. Companion skills

9a. 配套 skills

Step 9d runs these once, against the committed files. Do not also run them on the draft: that doubles the slowest part of the run, and only real files exercise frontmatter, includes, and link resolution. Run the ones that apply. When one is not installed, report it as not checked rather than failing.
SkillWhat it decidesRun it when
docs-content-type-checker
Which content type the page is, and whether its structure matchesAlways. Also used in classify mode in Step 5
docs-applies-to-tagging
Whether the content needs scoping at all, the
applies_to
values, and where the badges go
The page is version- or deployment-scoped, which is almost always
docs-page-opening-optimizer
The H1, the opening paragraph, and the requirements sectionAlways, for a new page or a rewritten opening
docs-check-style
Style guide compliance, and runs Vale when it is availableAlways
docs-flag-jargon-skill
Jargon and unexplained termsAlways
docs-check-contradictions
New content that conflicts with pages elsewhere in the corpusAlways. "Place it once" fails quietly when another page already says something different
docs-syntax-help
MyST and Elastic directive syntaxThe draft uses admonitions, tabs, applies-switches, includes, or settings directives
docs-validate-code-samples
Whether code and YAML samples are valid and runnableThe draft contains a code block
docs-frontmatter-description
The
description
field, for search
Always
docs-frontmatter-audit
The rest of the frontmatter against the repo schemaAlways
docs-redirects
The
redirects.yml
entries for anything moved, renamed, or deleted
Step 8 moved, renamed, or deleted a page
How to invoke one. These checks run against your working tree, so they must not write anything:
  • A skill with
    Edit
    or
    Write
    in its
    allowed-tools
    runs as a subagent, because only a subagent prompt can forbid a write. The subagent finds the skill's
    SKILL.md
    under
    ~/.claude/skills/*/
    ,
    ~/.claude/plugins/**/skills/**/
    , or the local
    skills/**/
    tree and follows it verbatim.
  • Any other skill can use the
    Skill
    tool. Try the plugin-prefixed name first, such as
    elastic-docs-skills:docs-check-style
    , then the bare name. If neither name works, use a subagent.
  • Every subagent prompt includes this line from
    docs-review-pr
    , verbatim: Do not Edit or Write any file. Do not modify the working tree. Return findings only.
The table uses frontmatter names, which is what invocation needs. Directory names differ and are only for finding files on disk.
Read the target skill's own
argument-hint
before calling it.
Most take one file or directory and glob
$ARGUMENTS
, so a space-separated list of targets reads as a single bad path — pass one target per call. Three break that shape:
docs-redirects
needs an old path and a new one,
docs-syntax-help
takes a question rather than a file, and
docs-validate-code-samples
accepts flags after its target. Handing a lone file path to those either errors or quietly checks the wrong thing, which looks the same as passing in the output.
If
AGENTS.md
names a task-to-skill mapping that is not in this table, run that one too, and open a pull request here to add the row.
Step 9d 针对已提交的文件运行以下检查一次。不要同时对草稿运行这些检查:这会让运行时间最长的部分翻倍,而只有真实文件才能覆盖 frontmatter、includes 和链接解析。运行适用的检查。如果某个 skill 未安装,报告为未检查,而不是任务失败。
Skill决定什么何时运行
docs-content-type-checker
页面属于哪种 content type,以及结构是否匹配始终运行。同时在 Step 5 中使用 classify 模式
docs-applies-to-tagging
内容是否需要范围界定、
applies_to
值以及 badge 的位置
页面按版本或部署方式界定范围时运行,这几乎适用于所有页面
docs-page-opening-optimizer
H1、开头段落和 requirements section新页面或重写开头时始终运行
docs-check-style
Style guide 合规性,并在可用时运行 Vale始终运行
docs-flag-jargon-skill
术语和未解释的概念始终运行
docs-check-contradictions
新内容是否与语料库中其他页面的内容冲突始终运行。“只放置一次”的要求会在其他页面说法不一致时悄无声息地失效
docs-syntax-help
MyST 和 Elastic directive 语法草稿使用 admonitions、tabs、applies-switches、includes 或 settings directives 时运行
docs-validate-code-samples
代码和 YAML 示例是否有效且可运行草稿包含代码块时运行
docs-frontmatter-description
用于搜索的
description
字段
始终运行
docs-frontmatter-audit
根据仓库 schema 审核 frontmatter 的其余内容始终运行
docs-redirects
为移动、重命名或删除的页面创建
redirects.yml
条目
Step 8 移动、重命名或删除页面时运行
**调用方式。**这些检查针对工作树运行,因此不得写入任何内容:
  • 如果某个 skill 的
    allowed-tools
    包含
    Edit
    或
    Write
    ,则将其作为 subagent 运行,因为只有 subagent prompt 才能禁止写入。Subagent 在
    ~/.claude/skills/*/
    、
    ~/.claude/plugins/**/skills/**/
    或本地
    skills/**/
    目录树下查找该 skill 的
    SKILL.md
    ,并逐字遵循其中的内容。
  • 其他任何 skill 都可以使用 Skill tool。先尝试带 plugin 前缀的名称,例如
    elastic-docs-skills:docs-check-style
    ,然后尝试不带前缀的名称。如果两者都不可用,则使用 subagent。
  • 每个 subagent prompt 都逐字包含
    docs-review-pr
    中的这一行:Do not Edit or Write any file. Do not modify the working tree. Return findings only.
该表使用 frontmatter 名称,因为调用时需要这些名称。目录名称不同,仅用于在磁盘上查找文件。
**调用前读取目标 skill 自身的
argument-hint
。**大多数 skill 接受一个文件或目录并 glob
$ARGUMENTS
,因此以空格分隔的多个目标会被解析为一个无效路径——每次调用只传入一个目标。其中三个存在特殊情况:
docs-redirects
需要旧路径和新路径,
docs-syntax-help
接受一个问题而不是文件,
docs-validate-code-samples
接受目标之后的 flags。只传一个文件路径给后三者,要么会报错,要么会悄悄检查错误的对象,其表现与输出中的失败完全相同。
如果
AGENTS.md
指定了此表中没有的 task-to-skill 映射,也要运行该 skill,并在此处打开 pull request 添加对应行。

9b. Read every new line as the reader's line

9b. 将每一行新增内容都作为读者的一行重新阅读

The 9a skills check the files against rules. This pass checks each line of the draft against the reader, applying the plain language principles of ISO 24495-1 — relevant, findable, understandable, usable. Run it on the added and changed lines only, after the draft exists. It is not the outline you write from, and it does not override a content-type template, a settings reference that must list every value, or a how-to's numbered spine. A how-to may still number its steps and a reference page may still list every setting; the pass only asks whether each new line is one a reader would use.
Re-read every added or changed sentence as someone who came to do a job, and ask four questions:
The questionThe fix
FindableDoes the first sentence of the section or list say what the reader gets?If context comes first, move the outcome ahead of it
RelevantDoes the line say something the reader cannot get from the step, heading, or UI a few lines away?Cut the repeat, unless the list is a reference set
UnderstandableDoes the line lead with the concrete noun, or with a wrapper like "the current view" or "the settings"?Lead with the concrete noun
UsableDoes the line say what happens to the reader's data or results, rather than only how the control looks?Add the outcome — or, when Step 6 could not verify it, carry it as an open question instead
Rewrite any line that only names controls or object types, maps a popover, contrasts with another mode's internals, dumps sibling action labels in parentheses, or speaks as writer IA ("this section covers," "X and Y are in [section]").
  • Don't:
    Use **View mode** in **Display options** to show the table as **Table** or **JSON**. **Table** is the default.
  • Do:
    To inspect documents as a tree, set **View mode** to **JSON**.
  • Don't:
    A saved Discover session stores **View mode** and the JSON display settings.
  • Do:
    If you save the session in **JSON** view, you get the same tree and the same **Lines shown** values when you open it again.
Finish by sweeping the same added and changed lines for the drafting rules that leak while writing: passive voice, em dashes, joining semicolons, hedges, and synonym switches. When
$EDITORIAL_PREFERENCES_PATH
resolved, re-read that file here and sweep against it too, still on the diff only. Report what you rewrote, so a reader of the output can see the pass ran.
9a skills 根据规则检查文件,而这一轮针对每一行草稿内容检查读者视角,并应用 ISO 24495-1 的 plain language 原则——相关性、可查找性、可理解性和可用性。它只针对新增和修改的行执行,并且要在草稿存在之后执行。它不是编写草稿时依据的大纲,也不覆盖 content-type 模板、必须列出每个值的 settings reference,或 how-to 的编号主线。How-to 仍可为步骤编号,reference 页面仍可列出每项设置;这一轮只询问每行新增内容是否提供了读者会使用的信息。
将每一行新增或修改的句子当作一个前来完成某项任务的人重新阅读,并提出以下四个问题:
问题修复方式
可查找section 或列表的第一句话是否说明读者将获得什么?如果先介绍背景,则将结果提前
相关性这一行是否提供了无法从附近的步骤、标题或 UI 中获得的信息?删除重复内容,但 reference 集合除外
可理解性这一行是否以具体名词开头,而不是以“当前视图”“设置”等包装性表达开头?以具体名词开头
可用性这一行是否说明它会如何影响读者的数据或结果,而不只是描述控件的外观?补充结果——或者当 Step 6 无法核验时,将其作为未决问题保留
重写任何只提及控件或对象类型、映射 popover、对比另一种模式的内部实现、在括号中罗列同级操作标签,或使用作者式信息架构语言(例如“本 section 涵盖……”或“X 和 Y 位于 [section] 中”)的行。
  • 不要:使用 Display options 中的 View mode,以 Table 或 JSON 形式显示表格。Table 是默认值。
  • 要:要以树结构查看文档,请将 View mode 设置为 JSON。
  • 不要:保存的 Discover session 会存储 View mode 和 JSON 显示设置。
  • 要:如果以 JSON 视图保存 session,再次打开时会看到相同的树和相同的 Lines shown 值。
最后,针对 diff 中的新增和修改行,检查写作过程中容易泄漏的规则:被动语态、em dash、并列分号、模糊措辞和同义词切换。如果 Step 1 已解析
$EDITORIAL_PREFERENCES_PATH
,还要重新读取该文件,并依据它再次检查这些内容,且仍只检查 diff。报告重写了哪些内容,让输出读者能够确认这一轮已经执行。

9c. Read the draft as its audience, when asked

9c. 在用户要求时,以目标读者身份阅读草稿

Run this only when the user asks for it, because it adds a subagent round. Paste the block below verbatim, with the placeholders filled, as the only message to a fresh subagent. The test only works if the reader has not seen you write the page.
The test asks whether the reader can do the task from this page, which includes following links the page itself provides. It does not ask whether the page is self-contained. A page that points at a canonical procedure instead of copying it is doing what Step 5 required, and that is a PASS unless the link is missing or the reader cannot tell where to go.
You are <audience, with technical level and role>.
Your goal is <what they are trying to accomplish>.
Read the page below and answer:
1. Can you accomplish your goal from this page, following any links it provides to canonical procedures? Answer PASS or FAIL. A link to a procedure that lives elsewhere is how you continue, not a gap.
2. What is the first sentence that confused you, if any?
3. What did you expect to find that is missing?
4. Which terms were unfamiliar or undefined?

<the drafted page>
Act on the verdict: fix a missing step, fact, or link once and re-run. If the FAIL is that the page linked instead of duplicating, the test was applied wrongly — that is a PASS. If it still fails for a real gap, stop and put the remaining gaps in front of the user rather than editing in circles.
仅在用户提出要求时执行,因为这样会增加一轮 subagent 交互。将下方代码块逐字粘贴到全新 subagent 的唯一消息中,并替换占位符。该测试只有在读者尚未看过你编写页面时才有效。
测试询问读者能否仅根据此页面完成任务,包括跟随页面自身提供的链接。测试不要求页面完全自包含。如果页面指向一个规范流程,而不是复制该流程,那么它符合 Step 5 的要求,除非链接缺失或读者不知道该去哪里,否则均为 PASS。
You are <audience, with technical level and role>.
Your goal is <what they are trying to accomplish>.
Read the page below and answer:
1. Can you accomplish your goal from this page, following any links it provides to canonical procedures? Answer PASS or FAIL. A link to a procedure that lives elsewhere is how you continue, not a gap.
2. What is the first sentence that confused you, if any?
3. What did you expect to find that is missing?
4. Which terms were unfamiliar or undefined?

<the drafted page>
根据结果采取行动:如果缺少某个步骤、事实或链接,修复一次并重新运行。如果 FAIL 是因为页面通过链接引用而不是重复内容,则说明测试应用错误,应视为 PASS。如果确实存在真实缺口,则停止,并将剩余缺口交给用户,不要反复编辑。

9d. Review the branch, after gate 2 and before gate 3

9d. 在 gate 2 之后、gate 3 之前评审 branch

Once the files are written and committed, run
docs-review-pr
against the branch — with no argument, it reviews the current branch against its base. It returns the docs team review checklist with an approve, comment, or request-changes call, and it is read-only, so it cannot undo the write.
Fetch first, and compare against the merge base —
git diff <base>...HEAD
, three dots, not two. Two dots compare the branch tip to the base tip, so everything the base gained since you branched reads as a file you changed. One commit of drift is enough to bury the files you actually touched in unrelated ones, and the review then spends its attention on those. When the branch is behind, say so rather than reviewing through the noise. The review diffs commits. If that diff is empty after the write, you skipped the commit — go back and make it before reviewing.
docs-review-pr
runs most of the 9a skills itself. It does not run
docs-page-opening-optimizer
,
docs-syntax-help
,
docs-frontmatter-description
, or
docs-redirects
, so run the ones that apply yourself:
  • Start them in the same message as the skills
    docs-review-pr
    starts in its Step 3, so everything runs in parallel.
  • Run each as a subagent, as 9a describes, because all four can edit files.
  • Report their findings in this skill's output, not in the
    docs-review-pr
    run table.
If
docs-review-pr
is not installed, run the whole 9a table yourself, all in one message, and say that the checklist review did not run.
Then act on the findings:
  • Fixes: make them in one follow-up commit on the same branch, so gate 3 can show them as their own diff.
  • New files: ask before writing a file that gate 2 did not approve.
  • Decisions: when a finding needs a decision rather than a fix, such as one that undoes a choice the user made at gate 1, raise it at gate 3 instead of fixing it.
  • Rewritten prose: re-run 9b on any line a fix rewrote, because that line never went through the pass.
Report the
docs-review-pr
recommendation in the output. Opening a pull request that your own pre-review would have blocked wastes the reviewer's first pass.
文件写入并提交后,对该 branch 运行
docs-review-pr
——不传参数时,它会使用当前 branch 相对其 base 的内容进行评审。它会返回 docs 团队的 review checklist,并给出 approve、comment 或 request-changes 结论。该操作是只读的,因此无法撤销写入。
首先 fetch,并对照 merge base 进行比较——使用
git diff <base>...HEAD
,即三个点,而不是两个点。两个点会比较 branch tip 与 base tip,因此 base 在创建 branch 后获得的所有内容都会被误认为你修改的文件。仅仅一次无关 commit 的漂移,就足以让实际触及的文件被大量无关变化淹没,评审也会因此把注意力浪费在这些内容上。如果 branch 落后,应直接说明,而不是在噪声中进行评审。该评审会比较 commits。如果写入后 diff 为空,说明你跳过了 commit——此时应在评审前先完成 commit。
docs-review-pr
会自行运行 9a 中的大多数 skills。它不会运行
docs-page-opening-optimizer
、
docs-syntax-help
、
docs-frontmatter-description
或
docs-redirects
,因此应自行运行适用的检查:
  • 将它们与
    docs-review-pr
    在 Step 3 中启动的 skills 放在同一条消息中,以便全部并行运行。
  • 按 9a 所述将每个检查作为 subagent 运行,因为这四个 skill 都可能编辑文件。
  • 在本 skill 的输出中报告这些发现,而不是将其放入
    docs-review-pr
    的运行表格。
如果未安装
docs-review-pr
,则自行在一条消息中运行整个 9a 表格,并说明 checklist 评审未执行。
然后根据发现采取行动:
  • **修复:**在同一 branch 上用一个后续 commit 完成修复,使 gate 3 可以将其作为独立 diff 展示。
  • **新文件:**在写入 gate 2 未批准的文件前先询问。
  • **需要决策的事项:**如果某项发现需要决策而不是直接修复,例如它会推翻用户在 gate 1 做出的选择,则应在 gate 3 提出,而不是自行修复。
  • **重写的文案:**对修复重写的任何行重新执行 9b,因为这些行尚未经过该轮检查。
在本 skill 的输出中报告
docs-review-pr
的建议。打开一个会被自身预评审阻止的 pull request,只会浪费评审者的时间。

Step 10: Draft the pull request description

Step 10:起草 pull request 描述

Compose it now, before gate 3, so the user approves the description along with the pull request. Derive it from work already done — Step 5's placement decision, Step 6's verification, Step 7's screenshot audit, Step 8's pending links, Step 9's review. Do not re-gather anything.
Read the template in the repo you are opening against, at
.github/PULL_REQUEST_TEMPLATE.md
, and fill its sections. Each repo has its own, so read the one that applies rather than reusing the last. Never invent or drop a template section.
Write it for the reviewer's decision. They need to know what changed, where, and what to check, in plain language and short enough to read before opening the diff. A description that restates the page content wastes the reviewer's time.
  • Summary. One paragraph, usually three sentences. What a reader can now do, in user terms rather than implementation terms. Any migration or compatibility fact a reviewer would otherwise flag, such as a feature replacing an older one while the old behavior keeps working. Then the placement decision and its reason — "to avoid duplicating this across pages, X now links to the canonical reference instead of repeating it" — because that is the judgment call most likely to be questioned. Close with
    Fixes #<issue>.
    , or say why there is no issue.
  • One bullet per changed page, under a
    ## Previews
    heading. Name the page, then say what changed on it and why, so a reviewer knows what to look at on each. Note version scoping where it applies, since cumulative docs are easy to review wrongly. This heading is a convention rather than part of the template, and it is the section reviewers use most.
  • A short note for anything deliberately incomplete. Pending cross-repo or cross-pull-request links from Step 8, a missing anchor that lands elsewhere, a screenshot still needed. Name what unblocks each one, rather than letting a reviewer find it.
  • The generative AI disclosure, answered honestly with the tool and model, because this skill drafted the content.
    AI.md
    governs this, and the name on the pull request is accountable for every word.
Do not fabricate preview URLs. Previews build automatically once the pull request exists and a bot posts the links, so write the bullets now and let the links arrive with the build.
For the title, follow the convention in the target repo's recent merged history rather than inventing a format — in docs-content that is area tags then an imperative, as in
[Observability/Kibana][Alerting] Document per-alert snooze
. Check with
gh pr list --repo <owner/repo> --state merged --limit 10
.
When the work spans repos, each pull request gets its own description written to its own repo's template, and each one says that the other exists.
现在完成这一步,在 gate 3 之前,让用户连同 pull request 一起批准描述。根据已经完成的工作撰写——Step 5 的放置决策、Step 6 的核验、Step 7 的截图审查、Step 8 的待处理链接、Step 9 的评审。不要重新收集信息。
读取目标仓库中的
.github/PULL_REQUEST_TEMPLATE.md
,并填写其中的 sections。每个仓库都有自己的模板,因此读取适用的模板,不要复用上一个仓库的模板。绝不能虚构或遗漏模板 section。
**面向评审者的决策来写。**评审者需要知道改了什么、改在哪里以及要检查什么。使用平实语言,并保持足够简短,使其在打开 diff 之前就能读完。
  • **Summary。**通常为一个段落、约三句话。使用用户层面的语言说明读者现在能够做什么,而不是使用实现层面的语言。包含评审者否则会标记的迁移或兼容性事实,例如某项功能替代了旧功能,但旧行为仍然有效。随后说明放置决策及其原因——“为避免在多个页面间重复内容,X 现在改为链接到规范 reference,而不再重复该内容”——因为这是最可能被质疑的判断。结尾使用
    Fixes #<issue>.
    ,或者说明为什么没有关联 issue。
  • **每个修改页面一个 bullet,置于
    ## Previews
    标题下。**先写页面名称,再说明该页面改了什么以及为什么改,让评审者知道每个页面应重点检查什么。适用时注明版本范围,因为 cumulative docs 很容易被错误评审。此标题是一种约定,而不是模板的一部分,但这是评审者最常使用的 section。
  • **对于有意保留未完成的内容,添加简短说明。**包括 Step 8 中的待处理跨仓库或跨 pull request 链接、落到其他位置的缺失 anchor,以及仍需补充的截图。分别说明每个问题的解除条件,而不是让评审者自行发现。
  • 生成式 AI 披露信息,如实填写所用工具和模型,因为此 skill 起草了内容。
    AI.md
    对此作出规定,pull request 上的作者姓名对每一个字词负责。
不要虚构 preview URL。Pull request 存在后,preview 会自动构建,机器人随后发布链接,因此现在先写好 bullet,之后再补充链接。
标题应遵循目标仓库近期已合并历史中的约定,不要自行发明格式——在 docs-content 中,先写区域 tags,再使用祈使语气,例如
[Observability/Kibana][Alerting] Document per-alert snooze
。使用
gh pr list --repo <owner/repo> --state merged --limit 10
检查。
当工作跨越多个仓库时,每个 pull request 都应根据其所在仓库的模板分别撰写描述,并且每个描述都要说明另一个 pull request 的存在。

Approval gates

审批门禁

Three gates. Never skip ahead, and never bundle two approvals into one question, including one gate-3 approval per repo.
  1. Present. Show the draft, the file paths you intend to write, the verification results, the Step 9b results, the Step 9c verdict if it ran, and the open questions. When the work spans repos, show the per-repo split and the order from Step 4e. Then say what has not run yet, so no one mistakes a missing result for a pass:
    • The companion checks, which run in Step 9d after the write.
    • The reader test, unless the user asked for it. Say in one line what it checks, and that the user can ask for it before approving.
  2. Write. On approval, write the page, the
    toc.yml
    entry, and any
    redirects.yml
    change onto the Step 3 branch. Confirm you are on it first, rather than assuming — a gate 1 that ran long is enough time for a branch to change underneath you. Writing to a second repo is part of this gate only if its split was presented at gate 1. Then commit, because Step 9d and gate 3 both look at commits, not at the working tree — uncommitted writes are invisible to
    git diff <base>...HEAD
    and there is nothing to push.
    references/branch-setup.md
    has the commit recipe. Then run Step 9d.
  3. Pull request. Only on a separate, explicit approval. When you ask, show the Step 10 description, the Step 9d findings and recommendation, and the diff of the Step 9d fix commit, if there is one. The branch already has the gate 2 commit and any Step 9d fixes, so push it and open the pull request as a draft, with the approved description as the body.
    references/branch-setup.md
    has the push recipe, including the fork case. Do not push while the writes are still uncommitted.
Open the pull requests in the Step 4e order, and cross-reference them in both bodies so a reviewer seeing one knows the other exists. Do not open the blocked one early: it cannot pass its own link check until the first publishes.
共三个门禁。绝不能跳过,也不能将两个审批合并为一个问题,包括每个仓库各自独立的 gate-3 审批。
  1. **Present。**展示草稿、准备写入的文件路径、核验结果、Step 9b 结果、运行过的 Step 9c 结果以及未决问题。当工作跨越多个仓库时,展示按仓库划分的结果以及 Step 4e 中的顺序。然后说明尚未运行的内容,避免把缺失的结果误认为通过:
    • 配套检查,它们会在写入后于 Step 9d 中运行。
    • 读者测试,除非用户提出要求。用一行说明该测试检查什么,并告知用户可以在批准前要求执行。
  2. **Write。**获得批准后,将页面、
    toc.yml
    条目以及任何
    redirects.yml
    变更写入 Step 3 创建的 branch。写入前先确认当前位于该 branch 上,不要假设——耗时较长的 gate 1 足以让 branch 在此期间被切换。只有当按仓库划分的结果已在 gate 1 中展示时,向第二个仓库写入才属于此 gate 的一部分。然后 commit,因为 Step 9d 和 gate 3 都会查看 commits,而不是工作树——未提交的写入不会出现在
    git diff <base>...HEAD
    中,也就不会被 push。
    references/branch-setup.md
    包含 commit 配方。然后运行 Step 9d。
  3. **Pull request。**只有获得单独、明确批准后才能执行。询问时展示 Step 10 描述、Step 9d 发现与建议,以及 Step 9d 修复 commit 的 diff(如果存在)。Branch 已经包含 gate 2 commit 和所有 Step 9d 修复,因此 push 它,并以已批准的描述作为正文打开 draft pull request。
    references/branch-setup.md
    包含 push 配方,包括 fork 场景。不要在写入仍未提交时 push。
按照 Step 4e 中的顺序打开 pull requests,并在两个正文中相互引用,使查看其中一个的评审者知道另一个的存在。不要提前打开受阻的那个:在第一个发布之前,它无法通过自身的链接检查。

Output

输出

  1. Setup — paths used, whether the MCP was reachable, the branch created in each repo with its base and whether that checkout is a fork, and which area file was found with its age and any
    status.md
    entry you resolved or fast-pathed
  2. Intake — scope, audience, deliverables with status, answered and open questions
  3. Placement — target pages, why this shape, content type and why
  4. Verification — verified with sources, contradicted, unverifiable
  5. Draft — the full content with frontmatter
  6. Follow-ups — navigation, cross-links, redirects, screenshots needed
  7. Validation — what the Step 9b pass rewrote, the reader test verdict or that it was not requested, which skills ran in Step 9d and which were not installed, and what the Step 9d fixes changed
  8. Pull request — the drafted title and description, ready to paste
  9. Open questions — what still needs a human
When the work spans repos, group sections 3, 5, 6, and 8 by repo rather than merging them into one list, and lead the output with the split and the merge order. A reader who cannot tell which file lands in which repo cannot review either half.
  1. Setup——使用的路径、MCP 是否可达、在每个仓库中创建的 branch 及其 base、该 checkout 是否为 fork、找到的区域文件及其年龄,以及已解析或采用快速路径处理的任何
    status.md
    条目
  2. Intake——范围、受众、交付内容及其状态、已回答和未决的问题
  3. Placement——目标页面、采用这种结构的原因、content type 及其原因
  4. Verification——已核验项及其来源、相互矛盾项、无法核验项
  5. Draft——包含 frontmatter 的完整内容
  6. Follow-ups——导航、交叉链接、重定向、所需截图
  7. Validation——Step 9b 重写了哪些内容、读者测试结果或未按要求运行、Step 9d 中运行了哪些 skills、哪些未安装,以及 Step 9d 修复改变了哪些内容
  8. Pull request——可直接粘贴的标题和描述
  9. Open questions——仍需人工处理的内容
当工作跨越多个仓库时,按仓库对 sections 3、5、6 和 8 分组,不要将它们合并成一份列表,并在输出开头说明拆分结果和合并顺序。读者如果无法分辨哪个文件会进入哪个仓库,就无法评审任何一半内容。

References

References

  • references/index.md
    — the area registry. Check it in Step 2
  • references/status.md
    — every in-flight transition, each with an expiry condition to resolve rather than a date to trust. Read it when an area file's frontmatter names it
  • references/branch-setup.md
    — the git recipe for Step 3, the gate-2 commit, and the gate-3 push
  • references/_template.md
    — copy to add an area. It states what belongs in an area file, what the MCP should answer instead, and the rules that keep a file from going stale
  • references/ste-overlay.md
    — optional Simplified Technical English prose overlay. Opt in through
    $EDITORIAL_PREFERENCES_PATH
    ; not loaded by default
  • Baseline:
    AGENTS.md
    and
    contribute-docs/
    in docs-content. Read at run time, never copied here
  • Companion skills: the table in Step 9a. Collect what they need and do not restate their rules
  • references/index.md
    ——区域注册表。在 Step 2 中检查它
  • references/status.md
    ——所有正在进行的迁移,每项都带有应解析而非信任的过期条件。当区域文件的 frontmatter 指明它时读取
  • references/branch-setup.md
    ——Step 3、gate-2 commit 和 gate-3 push 的 git 配方
  • references/_template.md
    ——复制后用于添加区域。它说明区域文件中应包含什么、MCP 应改为回答什么,以及确保区域文件不会过时的规则
  • references/ste-overlay.md
    ——可选的 Simplified Technical English 文案 overlay。通过
    $EDITORIAL_PREFERENCES_PATH
    启用,默认不加载
  • Baseline:docs-content 中的
    AGENTS.md
    和
    contribute-docs/
    。运行时读取,绝不在此复制
  • Companion skills:上方表格。收集它们所需的内容,不要复述其规则