ax-narrate

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ax:narrate - write the session's story as a structured narration

ax:narrate - 编写会话的结构化叙事

You were there. This skill turns YOUR OWN memory of the session into a reviewable artifact: 3-7 stops in reading-flow order, each anchored to real evidence - code hunks, turn numbers, user quotes, failures. The point is to capture what a PR diff never shows: the corrections, the dead ends, the recoveries.
The artifact validates against
SessionNarration
in
apps/studio/src/routes/narration-types.ts
and renders in ax studio.
你全程参与了会话。此技能将你对会话的记忆转化为一份可审阅的工件:按照阅读顺序排列的3-7个节点,每个节点都锚定在真实证据上——代码片段、轮次编号、用户引用、失败记录。核心是捕获PR差异永远无法展示的内容:修正过程、死胡同、恢复步骤。
该工件需符合
apps/studio/src/routes/narration-types.ts
SessionNarration
的校验规则,并可在ax studio中渲染。

Step 1 - identify the session

步骤1 - 识别会话

  • Preferred:
    ax sessions here --days=1 --json
    and pick the current session's id (the one matching this conversation). Use the short id.
  • If
    ax
    is unavailable or the session isn't ingested yet, derive a slug:
    <repo>-<YYYYMMDD-HHmm>
    . Note in
    meta
    that turn seqs are best-effort ordinals in that case.
  • If available,
    ax sessions show <id> --json
    gives you the real turn seqs to anchor against. Prefer real seqs over guesses.
  • 首选方式:执行
    ax sessions here --days=1 --json
    并选择当前会话的ID(与本次对话匹配的ID),使用短ID。
  • ax
    不可用或会话尚未被收录,则生成一个slug:
    <repo>-<YYYYMMDD-HHmm>
    。在此情况下,需在
    meta
    中注明轮次序号为最佳预估的序数。
  • 若可用,
    ax sessions show <id> --json
    可提供真实的轮次序号用于锚定。优先使用真实序号而非预估序号。

Step 2 - reconstruct the story from your own context

步骤2 - 从自身语境重构叙事

Re-read the conversation in your head before writing anything:
  1. What did the user originally ask for? (intent)
  2. What existed before, what exists now? (before/after)
  3. Where did the user redirect or correct you? EVERY one of these becomes a
    correction
    anchor. No exceptions.
  4. Which tool failures actually mattered (changed your approach, cost real time, forced a workaround)? Each becomes a
    tool_failure
    anchor. Skip trivial retries that changed nothing.
  5. Which attempts were abandoned? They get a stop or at least a
    turn
    anchor - abandonment is part of the story.
在开始编写前,先在脑中重读对话内容:
  1. 用户最初的需求是什么?(意图)
  2. 变更前后的状态分别是什么?(前后对比)
  3. 用户在哪些地方进行了引导或修正?每一处都要成为
    correction
    锚点,无一例外。
  4. 哪些工具失败产生了实际影响(改变了你的方法、耗费了时间、迫使你寻找替代方案)?每一处都要成为
    tool_failure
    锚点。忽略无影响的重试操作。
  5. 哪些尝试被废弃了?它们需要对应一个节点,或至少一个
    turn
    锚点——废弃过程也是叙事的一部分。

Step 3 - choose 3-7 stops, in reading-flow order

步骤3 - 选择3-7个节点,按阅读顺序排列

A stop is a LOGICAL unit of change, not a file. If three files changed for one reason, that is ONE stop with several anchors. Order rules (stolen from the code-tour playbook because they work):
  • Entry point first: the change that, understood alone, unlocks the rest.
  • Cause before effect: the correction comes before the code it caused.
  • Definitions before consumers: types/schema stops before usage stops.
  • Verification last: tests, typecheck, and the failures hit on the way.
  • Combine trivial housekeeping into one final stop, or omit it.
节点是一个逻辑变更单元,而非单个文件。如果三个文件因同一原因发生变更,那这是一个包含多个锚点的节点。排序规则(借鉴自代码漫游手册,因其行之有效):
  • 入口点优先:单独理解该变更即可掌握后续所有内容。
  • 先因后果:修正操作放在其引发的代码变更之前。
  • 先定义后使用:类型/架构节点放在使用节点之前。
  • 验证环节最后:测试、类型检查,以及过程中遇到的失败。
  • 将琐碎的整理操作合并为最后一个节点,或直接省略。

Step 4 - write each stop

步骤4 - 编写每个节点

  • title: short and friendly. "Call counts become a char diffstat", not "Changes to files-touched.ts".
  • gist: ONE sentence. Not two. A reader who reads nothing else must get the stop from the gist. Conversational, the way you'd say it to a colleague.
  • detail: 2-4 sentences of markdown (paragraphs,
    inline code
    , bold). Say WHY the change looks the way it does; "we did X instead of Y because Z" is exactly what the reader wants.
  • transition: a short connective phrase to the next stop; empty string
    ""
    for the last stop.
  • anchors: MUST be non-empty. An unanchored stop is an unsupported claim. Anchor kinds:
kindrequired fieldsuse for
file_hunk
file
,
old_text
,
new_text
,
label
, opt
turn_seq
a real code change
code_state
artifact
,
label
,
lang
,
code
, opt
turn_seq
the evolving architecture snapshot
turn
turn_seq
,
label
a plain moment in the transcript
user_direction
turn_seq
,
quote
user steering (not correcting)
correction
turn_seq
,
quote
,
outcome
user correcting course
tool_failure
turn_seq
,
tool
,
error_excerpt
,
recovery
consequential failure
term
name
,
definition
a domain term the story leans on
  • title:简短友好。例如“调用次数转为字符差异统计”,而非“修改files-touched.ts文件”。
  • gist:一句话描述。不能是两句。只读这一句话的读者也能理解该节点的核心内容。用和同事交流的口语化风格表述。
  • detail:2-4句Markdown格式的内容(段落、
    行内代码
    加粗)。说明变更为何是当前的样子;“我们选择X而非Y是因为Z”正是读者需要的信息。
  • transition:连接到下一个节点的简短短语;最后一个节点留空字符串
    ""
  • anchors:必须非空。无锚点的节点属于无依据的表述。锚点类型如下:
类型必填字段适用场景
file_hunk
file
,
old_text
,
new_text
,
label
, 可选
turn_seq
真实的代码变更
code_state
artifact
,
label
,
lang
,
code
, 可选
turn_seq
演进中的架构快照
turn
turn_seq
,
label
对话中的某个普通时刻
user_direction
turn_seq
,
quote
用户的引导(非修正)
correction
turn_seq
,
quote
,
outcome
用户的路线修正
tool_failure
turn_seq
,
tool
,
error_excerpt
,
recovery
产生影响的失败
term
name
,
definition
叙事中涉及的领域术语

Hard anchor rules

锚点严格规则

  • file_hunk
    carries VERBATIM old/new fragments from the actual edits you made - copy the real text, never paraphrase code. Keep hunks short (5-15 lines per side); pick the most telling fragment, not the whole edit.
    old_text: null
    for pure insertions,
    new_text: null
    for pure deletions. Never both null.
  • Every user correction/redirect in the session gets a
    correction
    anchor with a verbatim (trimmed)
    quote
    and a concrete
    outcome
    - what actually changed because of it.
  • Every consequential tool failure gets a
    tool_failure
    anchor with a real
    error_excerpt
    and how you recovered (or
    "abandoned"
    ).
  • Never fabricate turn seqs. Use
    ax sessions show
    seqs when you have them; otherwise count user turns from the start of the conversation and say so in the detail.
  • code_state
    is the architecture spine of the narration: pick ONE stable
    artifact
    id (e.g.
    "review-architecture"
    ) and restate the FULL snapshot at each stop where the design moved - pseudo-code of types/interfaces, how they compose, and the call stack (plan-style:
    Caller -> Callee // note
    ). Consecutive snapshots of the same artifact animate token-by-token in studio, so KEEP shared lines byte-identical between stops and let only the real delta differ - a new method, a renamed shape, an added edge case. Use
    code_state
    for the evolving design; use
    file_hunk
    for one-off code jumps (those render as static before/after diffs, not motion).
  • file_hunk
    必须包含你所做编辑的原文片段——复制真实文本,绝不要改写代码。保持片段简短(每侧5-15行);选择最具代表性的片段,而非完整编辑内容。纯插入时
    old_text: null
    ,纯删除时
    new_text: null
    。不可两者都为null。
  • 会话中每一处用户修正/引导都要对应一个
    correction
    锚点,包含原文(精简后)
    quote
    和具体的
    outcome
    ——即该修正实际带来的变化。
  • 每一处产生影响的工具失败都要对应一个
    tool_failure
    锚点,包含真实的
    error_excerpt
    以及你的恢复方式(或
    "abandoned"
    )。
  • 绝不要编造轮次序号。有
    ax sessions show
    提供的序号时优先使用;否则从对话开始计数用户轮次,并在detail中说明。
  • code_state
    是叙事的架构核心:选择一个稳定的
    artifact
    ID(例如
    "review-architecture"
    ),并在每个设计发生变化的节点处重述完整快照——类型/接口的伪代码、它们的组合方式、调用栈(计划风格:
    Caller -> Callee // 备注
    )。同一工件的连续快照在studio中会逐 token 动画展示,因此要保持节点间的共享内容完全一致,仅修改真实差异部分——新增方法、重命名结构、添加边缘案例。
    code_state
    用于展示演进中的设计;
    file_hunk
    用于展示一次性代码跳转(后者会渲染为静态的前后差异,而非动态效果)。

Step 5 - emit the artifact

步骤5 - 生成工件

Write
.ax/narrations/<session-id>.json
(create the directory if needed) with exactly this top-level shape:
json
{
  "schema_version": 1,
  "kind": "narration",
  "meta": {
    "session_id": "<id>",
    "generated_at": "<ISO-8601 now>",
    "generator": "skill",
    "model": "<your model id>"
  },
  "title": "...",
  "intent": "...",
  "before": "...",
  "after": "...",
  "stops": [ { "title": "...", "gist": "...", "detail": "...", "transition": "...", "anchors": [ ... ] } ]
}
Before finishing, self-check against the validator's rules:
  • stops
    non-empty (3-7), every stop's
    anchors
    non-empty.
  • Every gist is one sentence; every
    correction
    has an
    outcome
    ; every
    tool_failure
    has a
    recovery
    ; no
    file_hunk
    with both sides null or empty.
  • Strings are plain JSON strings (escape newlines in hunks as
    \n
    ).
Then tell the user where the file landed and give a 2-line summary of the story you wrote. Do not paste the whole JSON into chat.
编写
.ax/narrations/<session-id>.json
文件(若目录不存在则创建),必须遵循以下顶层结构:
json
{
  "schema_version": 1,
  "kind": "narration",
  "meta": {
    "session_id": "<id>",
    "generated_at": "<ISO-8601 now>",
    "generator": "skill",
    "model": "<your model id>"
  },
  "title": "...",
  "intent": "...",
  "before": "...",
  "after": "...",
  "stops": [ { "title": "...", "gist": "...", "detail": "...", "transition": "...", "anchors": [ ... ] } ]
}
完成前,对照校验规则进行自检:
  • stops
    非空(3-7个),每个节点的
    anchors
    非空。
  • 每个gist都是一句话;每个
    correction
    都有
    outcome
    ;每个
    tool_failure
    都有
    recovery
    ;没有两侧都为null或空的
    file_hunk
  • 字符串为标准JSON字符串(片段中的换行需转义为
    \ 
    )。
然后告知用户文件的保存位置,并给出你所编写叙事的2行摘要。不要将完整JSON粘贴到聊天中。",