discover-event-surfaces

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

discover-event-surfaces

发现事件埋点场景

You are step 2 of the analytics instrumentation workflow. Read a
change_brief
YAML and produce an exhaustive candidate list of analytics events — named well, organized by category, and ready for PM review.
Think like an engineer who ships the feature AND cares about whether it succeeds. Generate events that answer product/business questions, not events that mirror implementation details. Aim for breadth and quality — a downstream skill will narrow the list.
Read the
taxonomy
skill at
../taxonomy/SKILL.md
to understand core analytics philosophy and naming standards.

你是分析埋点工作流的第2步。读取
change_brief
YAML文件,生成详尽的分析事件候选列表——命名规范、按类别组织,可供PM直接评审。
要像一位既要负责功能交付、又关心功能是否成功的工程师一样思考。生成能回答产品/业务问题的事件,而非镜像实现细节的事件。目标是覆盖全面且质量过硬——后续流程会对列表进行精简。
阅读
../taxonomy/SKILL.md
中的
taxonomy
技能文档,了解核心分析理念和命名规范。

1. Parse the change_brief

1. 解析change_brief

  • classification.analytics_scope
    — if
    none
    , stop and tell the user there's nothing to instrument.
  • summary
    — one-line description of the change.
  • user_facing_changes
    — primary signal. Each entry = something a user can now do or see differently.
  • surfaces.components
    — modified UI components; where interactions happen.
  • file_summary_map
    — read summaries for files in
    surfaces
    or touching user-facing logic. Skip tests/config/tooling.
  • classification.analytics_scope
    — 若值为
    none
    ,则停止操作并告知用户无需埋点。
  • summary
    — 变更的单行描述。
  • user_facing_changes
    — 核心信号源。每一项代表用户现在能执行或看到的新变化。
  • surfaces.components
    — 被修改的UI组件;即用户交互发生的位置。
  • file_summary_map
    — 读取
    surfaces
    中或涉及用户可见逻辑的文件摘要。跳过测试/配置/工具类文件。

2. Scan the codebase and map user flows

2. 扫描代码库并映射用户流程

Before generating any events, build a concrete understanding of how users move through the feature. The change_brief gives you file paths and summaries — now read the actual code to trace the full journey.
在生成任何事件之前,先建立对用户使用该功能完整流程的清晰认知。change_brief提供了文件路径和摘要——现在需要读取实际代码来追踪完整的用户旅程。

What to read

需要读取的内容

  • Every file listed in
    surfaces.components
    — read them fully.
  • Files from
    file_summary_map
    that touch user-facing logic (skip tests, config, tooling).
  • Follow imports and references one level out: if a component calls a hook, API function, or navigates to another route, read that target file too. This is how you discover steps the diff didn't touch but that are part of the same flow.
  • surfaces.components
    中列出的所有文件——完整读取。
  • file_summary_map
    中涉及用户可见逻辑的文件(跳过测试、配置、工具类文件)。
  • 追踪导入和引用的一级关联:如果某个组件调用了hook、API函数,或者跳转到其他路由,也要读取目标文件。这能帮助你发现diff未涉及但属于同一流程的步骤。

What to look for

需要关注的要点

Trace the path a user takes from entry to outcome:
  • Entry points — how does the user arrive? Route definitions, navigation calls, menu items, links, feature flag gates.
  • Interaction sequence — what does the user do step by step? Form fills, selections, confirmations, uploads. Look at handler wiring (
    onClick
    ,
    onSubmit
    ,
    onChange
    ) and what state they mutate.
  • Async boundaries — API calls, mutations, server actions. These are where "attempted" becomes "succeeded" or "failed."
  • Terminal states — success confirmations, error handling, redirects, completion screens.
  • Branching paths — conditionals that route users to different outcomes (e.g., free vs paid, first-time vs returning).
追踪用户从进入到完成操作的完整路径:
  • 入口点 — 用户如何进入该功能?路由定义、导航调用、菜单项、链接、功能开关。
  • 交互序列 — 用户一步步会执行哪些操作?填写表单、选择选项、确认操作、上传文件。关注处理函数的绑定(
    onClick
    onSubmit
    onChange
    )以及它们修改的状态。
  • 异步边界 — API调用、数据变更、服务器操作。这些是“尝试执行”转变为“成功”或“失败”的节点。
  • 终端状态 — 成功确认、错误处理、重定向、完成界面。
  • 分支路径 — 将用户导向不同结果的条件逻辑(例如,免费版vs付费版、首次使用vs回头客)。

Produce a funnel hypothesis

生成漏斗假设

Synthesize what you found into one or more funnels — ordered sequences of user steps from entry to outcome. Each funnel should have:
  • A descriptive name (e.g., "Property extraction flow", "Onboarding wizard")
  • The ordered steps, each with the file and function/handler where it happens
  • Which step is the start and which is the end
Not every change has a funnel. Single-action features (a toggle, a one-click export) don't need one — just note that there's no multi-step flow. But when a flow exists, mapping it here is what allows you to confidently assign funnel start/end as critical later.
Keep the hypothesis grounded in code you actually read. Don't invent steps you didn't see evidence for.
将发现的信息整合为一个或多个漏斗——即用户从入口到结果的有序步骤序列。每个漏斗应包含:
  • 描述性名称(例如,“属性提取流程”、“引导注册向导”)
  • 有序步骤,每个步骤需标注对应的文件和函数/处理函数
  • 标记哪个步骤是起点,哪个是终点
并非所有变更都有漏斗。单一操作类功能(如开关、一键导出)无需漏斗——只需标注无多步流程即可。但当存在流程时,在此处映射漏斗是后续确定关键漏斗起止点的基础。
漏斗假设必须基于你实际读取的代码。不要凭空捏造没有证据的步骤。

3. Determine naming conventions and fetch existing events

3. 确定命名规范并获取现有事件

Invoke
discover-analytics-patterns
and use its
event_naming_convention
and
property_naming_convention
outputs. That skill owns the naming-resolution procedure and precedence order. Do not redefine it here.
Before generating candidates, pull the project's existing event taxonomy so you can avoid duplicates and match the naming convention already in use.
调用
discover-analytics-patterns
技能,使用其返回的
event_naming_convention
property_naming_convention
输出。该技能负责命名规则的确定和优先级排序,请勿在此处重新定义。
在生成候选事件之前,先获取项目现有的事件分类体系,以避免重复并匹配已在使用的命名规范。

Resolve the project

确定项目

If the change_brief includes an Amplitude
projectId
, use it directly. Otherwise, call
get_context
to resolve the project name or ask the user which project to target. You need a
projectId
for the next call.
如果change_brief包含Amplitude的
projectId
,直接使用该ID。否则,调用
get_context
来确定项目名称,或询问用户目标项目。你需要一个
projectId
来进行下一步调用。

Pull existing events

获取现有事件

Call
get_events
with the resolved
projectId
(no cursor needed — just the first page is enough for pattern detection). This returns event objects with fields like
eventType
,
category
,
description
, etc.
使用解析后的
projectId
调用
get_events
(无需游标——仅第一页数据即可用于模式检测)。该调用会返回包含
eventType
category
description
等字段的事件对象。

Build naming references and an existing event index

构建命名参考和现有事件索引

  1. Existing event index — Collect all
    eventType
    values into a set. You'll check candidates against this set in step 4 to avoid proposing events that are already tracked. An event is a duplicate if its semantic meaning matches an existing
    eventType
    , not just its exact string — e.g., if
    Subscription Upgraded
    exists, don't propose
    Plan Upgraded
    for the same action.
  1. 现有事件索引 — 将所有
    eventType
    值收集到一个集合中。在第4步中,你会对照此集合检查候选事件,避免提出已被跟踪的事件。判断重复的依据是语义匹配,而非字符串完全一致——例如,如果已存在
    Subscription Upgraded
    ,则无需为相同操作提出
    Plan Upgraded

4. Generate candidate events

4. 生成候选事件

Start from the funnel hypothesis. If you identified funnels in step 2, generate events for the funnel start and end first — these are your anchors. Then fill in candidates for intermediate steps and non-funnel surfaces.
For each
user_facing_change
, ask: "If a user does this — what outcomes would a PM want to know about?"
Generate from four categories (ordered by priority):
CategoryWhat it capturesWhen to include
business_outcomeRevenue, retention, growth actions (purchases, subscription changes, conversion gates)Change touches monetization or retention surface
user_journeyMeaningful state transitions (workflow completed, feature activated, onboarding finished)Change introduces or alters a user journey step
feature_successThe "it worked" moment — confirmed outcome, not button click (document created, report generated)Any new or materially changed feature
friction_failureWhere users fail, get stuck, or give up (errors, empty states, abandonment)Complex multi-step interactions or error-prone flows
从漏斗假设开始。如果在第2步中识别出漏斗,优先生成漏斗起点和终点的事件——这是核心锚点。然后补充中间步骤和非漏斗场景的候选事件。
针对每个
user_facing_change
,思考:“如果用户执行此操作,PM希望了解哪些结果?”
按优先级从高到低,从以下四类中生成事件:
类别捕获内容适用场景
业务结果收入、留存、增长相关行为(购买、订阅变更、转化节点)变更涉及变现或留存相关场景
用户旅程有意义的状态转换(流程完成、功能激活、引导注册完成)变更引入或修改了用户旅程步骤
功能成功“操作成功”时刻——已确认的结果,而非按钮点击(文档创建、报告生成)任何新增或重大修改的功能
摩擦与失败用户遇到失败、卡顿或放弃的节点(错误、空状态、中途退出)复杂多步交互或易出错的流程

Deduplicate against existing events

与现有事件去重

After generating candidates, check each one against the existing event index you built in step 3. For each candidate:
  • Exact match — the
    eventType
    already exists verbatim. Drop the candidate.
  • Semantic match — a different name tracks the same user action or outcome (e.g., you proposed
    Plan Upgraded
    but
    Subscription Upgraded
    already exists for the same action). Drop the candidate.
  • Partial overlap — an existing event covers a broader action that subsumes your candidate (e.g.,
    Checkout Completed
    already exists and your candidate
    Payment Submitted
    fires at the same moment). Drop unless the candidate captures meaningfully different information.
If you drop a candidate because it already exists, note it in a
already_tracked
list in the output so the user can see what's covered.
生成候选事件后,对照第3步构建的现有事件索引检查每个候选事件:
  • 完全匹配
    eventType
    完全一致。移除该候选事件。
  • 语义匹配 — 不同名称但跟踪的是同一用户操作或结果(例如,你提出了
    Plan Upgraded
    ,但已存在
    Subscription Upgraded
    用于跟踪相同操作)。移除该候选事件。
  • 部分重叠 — 现有事件覆盖了更宽泛的操作,包含你的候选事件(例如,已存在
    Checkout Completed
    ,而你的候选事件
    Payment Submitted
    在同一时刻触发)。除非候选事件能捕捉到明显不同的信息,否则移除。
如果因事件已存在而移除候选,请在输出的
already_tracked
列表中注明,以便用户了解已有的覆盖范围。

5. Quality filter

5. 质量筛选

Every candidate must pass all three:
  1. Decision-useful — A PM could make a product decision from this alone, without five other events for context.
  2. Outcome-focused — Captures that something happened, not that the user attempted it.
    Property Extracted
    >
    Extract Button Clicked
    . Prefer confirmed outcomes; form submissions are acceptable when no server confirmation exists.
  3. Stable across redesigns — Named around the business/product concept, not the UI element. If renaming a modal would make the event name stale, it's too coupled.
Cut: raw clicks/hovers without outcomes, internal technical actions (API callbacks, state updates), UI-versioned names (
modal_v2_submit
), sub-step-level granularity.
每个候选事件必须通过以下三项检查:
  1. 决策有用性 — PM仅通过该事件就能做出产品决策,无需其他事件提供上下文。
  2. 结果导向 — 捕捉“已发生”的结果,而非用户“尝试执行”的动作。
    Property Extracted
    优于
    Extract Button Clicked
    。优先选择已确认的结果;若无服务器确认,表单提交也可接受。
  3. 跨版本稳定 — 围绕业务/产品概念命名,而非UI元素。如果重命名模态框会导致事件名称失效,则说明命名与UI耦合过紧。
需剔除的事件: 无结果的原始点击/悬停、内部技术操作(API回调、状态更新)、带UI版本号的名称(
modal_v2_submit
)、过细的子步骤粒度事件。

6. Name events

6. 事件命名

Use the naming conventions returned by
discover-analytics-patterns
. New events should look like they belong with the rest of the instrumentation: same casing, same word order, same delimiters, same prefix patterns, and the same level of specificity.
If you later need to suggest property names in rationale or instrumentation hints, use the
property_naming_convention
returned by
discover-analytics-patterns
.
In all cases, use product-domain subjects (Property, User, Document), not code names (PropertyItem, ActionStore).
Good (Title Case convention)Bad
Property Extracted
extract_property_clicked
Extract Type Configured
type_dropdown_changed
Property Creation Failed
500_error_new_property
使用
discover-analytics-patterns
返回的命名规范。新事件应与现有埋点风格一致:相同的大小写、语序、分隔符、前缀模式,以及相同的粒度。
如果后续需要在理由或埋点提示中建议属性名称,请使用
discover-analytics-patterns
返回的
property_naming_convention
所有情况下,使用产品领域的术语(Property、User、Document),而非代码中的命名(PropertyItem、ActionStore)。
规范示例(标题大小写)不规范示例
Property Extracted
extract_property_clicked
Extract Type Configured
type_dropdown_changed
Property Creation Failed
500_error_new_property

7. Determine file and instrumentation point

7. 确定文件和埋点位置

For each candidate, use
file_summary_map
and
surfaces.components
to identify:
  • file
    — the source file where the tracking call belongs. Prefer the file closest to where the outcome is confirmed (not where the user initiates the action). Usually a component file from
    surfaces.components
    or a hook where an async operation resolves.
  • instrumentation
    — 1-2 sentences: when it fires (after what condition/callback/state transition) and how it's wired (which function/handler to place it in). Reference actual function names from file summaries so an engineer can find the right line.
针对每个候选事件,使用
file_summary_map
surfaces.components
确定:
  • file
    — 埋点调用应放置的源文件。优先选择结果确认位置附近的文件(而非用户触发操作的位置)。通常是
    surfaces.components
    中的组件文件,或是异步操作完成的hook文件。
  • instrumentation
    — 1-2句话说明:事件触发时机(满足什么条件/回调/状态转换后),以及如何绑定(应放置在哪个函数/处理函数中)。引用文件摘要中的实际函数名称,以便工程师找到正确的代码行。

8. Deepen understanding, then prioritize

8. 深化理解并排序优先级

For each candidate, first work through these two fields — they force you to think concretely about the event's value before scoring it:
  • analysis_recipe
    — Describe the specific chart, funnel, or query an analyst would build with this event. Be concrete: mention the visualization type, segmentation dimensions, and any other events to combine with. e.g., "Weekly funnel: Panel Opened → Extract Type Selected → Property Extracted, segmented by extractType. Alert if completion rate drops below 50%."
  • stakeholder_narrative
    — Write a sentence that a PM could drop into a quarterly review or board deck, using this event's data. Imagine the metric already exists and write the story it tells. e.g., "68% of users who try extraction complete it on the first attempt, up from 45% last quarter." If you can't imagine a compelling slide sentence, the event probably isn't worth instrumenting.
Now, with that context fresh, assign a priority:
PriorityMeaningGuidance
3 (critical)You would block a release if this event were missing. It answers a question the team will ask in the first week.Reserve for events that directly measure whether the feature succeeded or failed. Most changes produce only 1-2 critical events.
2 (useful)Adds real analytical value but the feature can ship without it. Worth adding if instrumentation cost is low.Segmentation dimensions, secondary workflows, configuration choices.
1 (optional)Nice-to-have. Only instrument if the team has bandwidth and a specific hypothesis to test.Edge-case failures, exploratory engagement signals, discoverability metrics.
Funnel events deserve special attention. When a change introduces or modifies a multi-step process (checkout flow, onboarding wizard, data import pipeline), the PM's first question will be "where are users dropping off?" A gap between funnel start and funnel end with no visibility in between is a blind spot that can hide serious product problems — if engagement craters at step 2 of 5, the team needs to know, not guess.
Funnel start and funnel end events are always critical (priority 3). Without the bookends, you can't measure conversion rate — the single most important metric for any funnel. These two events are non-negotiable regardless of funnel length or complexity.
To decide how many intermediate funnel events to mark critical, gauge the length and complexity of the funnel:
  • Short process (2-3 steps, single page): The start and end events are enough. Don't instrument every micro-step in a simple flow.
  • Medium process (3-5 steps, possibly spanning pages): Add one intermediate event at the most likely drop-off point — typically where the user commits effort (fills a form, makes a key selection, uploads a file).
  • Long process (5+ steps, multi-page or wizard-style): 2-3 intermediate events at natural phase boundaries. Think "started → configured → submitted → confirmed" rather than tracking every field interaction.
Be selective with intermediate events. Every funnel event you mark critical is one more thing an engineer must implement and a PM must monitor. If you're unsure whether an intermediate step is worth tracking, it probably isn't — the start and end events will reveal whether there's a problem, and the team can always add granularity later once they see where drop-off is high.
Less is more. A focused set of critical events that actually get dashboarded beats a sprawling list nobody looks at. When in doubt, downgrade — it's easier to add an event later than to remove one that's already in dashboards.
针对每个候选事件,先完成以下两个字段——这能让你在打分前更深入地思考事件的价值:
  • analysis_recipe
    — 描述分析师使用该事件可构建的具体图表、漏斗或查询。需具体:提及可视化类型、细分维度,以及需要结合的其他事件。例如:“每周漏斗分析:面板打开 → 提取类型选择 → 属性提取,按extractType细分。若完成率低于50%则触发告警。”
  • stakeholder_narrative
    — 写一句话,让PM可以直接放入季度评审或董事会演示文稿中,使用该事件的数据。假设该指标已存在,写出它能讲述的故事。例如:“68%尝试提取功能的用户首次操作即完成,较上季度的45%有所提升。” 如果无法构思出有说服力的演示语句,该事件可能不值得埋点。
在明确上述背景后,为事件分配优先级
优先级含义指导原则
3(关键)如果缺少该事件,你会阻止发布。它能回答团队在发布第一周必然会提出的问题。仅用于直接衡量功能成功或失败的事件。大多数变更仅会产生1-2个关键事件。
2(有用)能提供实际分析价值,但功能可以在无该事件的情况下发布。若埋点成本低则值得添加。细分维度、次要流程、配置选项相关事件。
1(可选)锦上添花的事件。仅当团队有带宽且有特定假设需要验证时才进行埋点。边缘故障、探索性参与信号、可发现性指标。
漏斗事件需特别关注。当变更引入或修改多步流程(结账流程、引导注册向导、数据导入管道)时,PM的第一个问题会是“用户在哪个环节流失?”。漏斗起点和终点之间的覆盖缺口会隐藏严重的产品问题——如果用户在5步流程的第2步就流失,团队需要明确知道原因,而非猜测。
漏斗起点和终点事件始终为关键优先级(优先级3)。没有这两个端点,就无法衡量转化率——这是任何漏斗最重要的指标。无论漏斗长度或复杂度如何,这两个事件都是必不可少的。
决定多少中间漏斗事件标记为关键优先级时,需评估漏斗的长度和复杂度:
  • 短流程(2-3步,单页面):起点和终点事件已足够。无需为简单流程的每个微步骤埋点。
  • 中等流程(3-5步,可能跨页面):在最可能的流失点添加一个中间事件——通常是用户投入精力的环节(填写表单、做出关键选择、上传文件)。
  • 长流程(5步以上,多页面或向导式):在自然阶段边界添加2-3个中间事件。例如“开始 → 配置 → 提交 → 确认”,而非跟踪每个字段的交互。
中间事件的选择要谨慎。每个标记为关键的漏斗事件都需要工程师实现,且PM需要监控。如果不确定某个中间步骤是否值得跟踪,那大概率不值得——起点和终点事件会揭示是否存在问题,团队可以在发现流失点后再添加更细粒度的埋点。
少即是多。一组集中的关键事件能真正用于仪表盘展示,胜过无人关注的冗长列表。如有疑问,降低优先级——后续添加事件比移除已在仪表盘中的事件更容易。

9. Emit YAML output

9. 输出YAML格式结果

Output only the YAML block — no surrounding prose.
yaml
event_candidates:
  source_summary: "<from change_brief.summary>"
  analytics_scope: "<from change_brief.classification.analytics_scope>"
  event_naming_convention: "<from MCP if clear, otherwise codebase instrumentation, otherwise taxonomy skill>"
  property_naming_convention: "<from MCP if clear, otherwise codebase instrumentation, otherwise taxonomy skill>"

  already_tracked:                         # omit if no duplicates found
    - existing_event: "Subscription Upgraded"
      candidate_dropped: "Plan Upgraded"
      reason: "Same action — existing event already tracks plan/subscription upgrades."

  funnels:                                 # omit if no multi-step flows found
    - name: "Descriptive funnel name"
      steps:
        - step: "Step description"
          file: "src/components/Foo.tsx"
          function: "handleOpen"
          role: start                      # start | intermediate | end
        - step: "Next step"
          file: "src/components/Bar.tsx"
          function: "onSubmit"
          role: intermediate
        - step: "Final step"
          file: "src/hooks/useSave.ts"
          function: "onSuccess"
          role: end

  candidates:
    - name: "Event Name Here"
      category: feature_success          # business_outcome | user_journey | feature_success | friction_failure
      rationale: "What PM question this answers."
      analysis_recipe: "Weekly trend of completions; funnel from Panel Opened → Extract Type Selected → Event Name, segmented by extract type."
      stakeholder_narrative: "Feature X adoption reached 40% of active users within two weeks of launch, exceeding our 25% target."
      priority: 3                        # 3 = critical, 2 = useful, 1 = optional
      funnel: "Funnel name"             # which funnel this belongs to, if any
      funnel_role: start                 # start | intermediate | end — omit if not part of a funnel
      surface: "ComponentName"           # from surfaces.components
      file: "src/components/Foo/Bar.tsx"
      instrumentation: "Fire after the async save resolves, inside onSuccess of useExtract(). Pass result status."

    - name: "Another Event"
      category: user_journey
      rationale: "..."
      analysis_recipe: "..."
      stakeholder_narrative: "..."
      priority: 2
      surface: "..."
      file: "..."
      instrumentation: "..."
Order: higher categories first, most impactful within each category first.

仅输出YAML块——无需额外说明文字。
yaml
event_candidates:
  source_summary: "<来自change_brief.summary>"
  analytics_scope: "<来自change_brief.classification.analytics_scope>"
  event_naming_convention: "<若MCP明确则使用,否则使用代码库埋点规范,最后使用taxonomy技能规范>"
  property_naming_convention: "<若MCP明确则使用,否则使用代码库埋点规范,最后使用taxonomy技能规范>"

  already_tracked:                         # 若无重复则省略
    - existing_event: "Subscription Upgraded"
      candidate_dropped: "Plan Upgraded"
      reason: "Same action — existing event already tracks plan/subscription upgrades."

  funnels:                                 # 若无多步流程则省略
    - name: "Descriptive funnel name"
      steps:
        - step: "Step description"
          file: "src/components/Foo.tsx"
          function: "handleOpen"
          role: start                      # start | intermediate | end
        - step: "Next step"
          file: "src/components/Bar.tsx"
          function: "onSubmit"
          role: intermediate
        - step: "Final step"
          file: "src/hooks/useSave.ts"
          function: "onSuccess"
          role: end

  candidates:
    - name: "Event Name Here"
      category: feature_success          # business_outcome | user_journey | feature_success | friction_failure
      rationale: "What PM question this answers."
      analysis_recipe: "Weekly trend of completions; funnel from Panel Opened → Extract Type Selected → Event Name, segmented by extract type."
      stakeholder_narrative: "Feature X adoption reached 40% of active users within two weeks of launch, exceeding our 25% target."
      priority: 3                        # 3 = critical, 2 = useful, 1 = optional
      funnel: "Funnel name"             # 所属漏斗名称(如有)
      funnel_role: start                 # start | intermediate | end — 非漏斗事件则省略
      surface: "ComponentName"           # 来自surfaces.components
      file: "src/components/Foo/Bar.tsx"
      instrumentation: "Fire after the async save resolves, inside onSuccess of useExtract(). Pass result status."

    - name: "Another Event"
      category: user_journey
      rationale: "..."
      analysis_recipe: "..."
      stakeholder_narrative: "..."
      priority: 2
      surface: "..."
      file: "..."
      instrumentation: "..."
排序规则:类别优先级高的在前,同一类别内影响大的在前。

Example

示例

Input excerpt:
yaml
user_facing_changes:
  - "Users can now select Extract Type (Text or Attribute) in the PropertyItem panel"
surfaces:
  components:
    - name: PropertyItem
      change: modified
Good candidates:
yaml
- name: "Property Extracted"
  category: feature_success
  rationale: "Core adoption signal — tells PMs whether the extract workflow completes."
  analysis_recipe: "Weekly funnel: Panel Opened → Extract Type Selected → Property Extracted, segmented by extractType. Alert if completion rate drops below 50%."
  stakeholder_narrative: "72% of users who open a property panel complete an extraction, up from 0% before this release — validating the new extract workflow."
  priority: 3
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire after extract resolves successfully in onSuccess handler. Include extractType (TEXT or ATTRIBUTE)."

- name: "Extract Type Selected"
  category: feature_success
  rationale: "Shows which mode users prefer — informs investment in Attribute mode."
  analysis_recipe: "Pie chart of Text vs Attribute selections over 30 days. Combine with Property Extracted to get per-mode completion rate."
  stakeholder_narrative: "85% of extractions use Text mode vs 15% Attribute — we should double down on Text UX before expanding Attribute capabilities."
  priority: 2
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire in onChange of Extract Type select, passing new value."

- name: "Property Extraction Failed"
  category: friction_failure
  rationale: "Surfaces where the extract workflow breaks for reliability prioritization."
  analysis_recipe: "Error rate chart: Property Extraction Failed / (Property Extracted + Property Extraction Failed), grouped by error reason. Alert on spikes."
  stakeholder_narrative: "Extraction failure rate dropped from 12% to 3% after the v2 error-handling patch — users are hitting fewer dead ends."
  priority: 2
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire in catch/onError of extract call. Include error reason if available."
Do NOT include:
Extract Type Dropdown Opened
(click, no outcome),
PropertyItem State Updated
(internal),
Attribute Input Focused
(too granular).
输入片段:
yaml
user_facing_changes:
  - "Users can now select Extract Type (Text or Attribute) in the PropertyItem panel"
surfaces:
  components:
    - name: PropertyItem
      change: modified
优质候选事件:
yaml
- name: "Property Extracted"
  category: feature_success
  rationale: "Core adoption signal — tells PMs whether the extract workflow completes."
  analysis_recipe: "Weekly funnel: Panel Opened → Extract Type Selected → Property Extracted, segmented by extractType. Alert if completion rate drops below 50%."
  stakeholder_narrative: "72% of users who open a property panel complete an extraction, up from 0% before this release — validating the new extract workflow."
  priority: 3
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire after extract resolves successfully in onSuccess handler. Include extractType (TEXT or ATTRIBUTE)."

- name: "Extract Type Selected"
  category: feature_success
  rationale: "Shows which mode users prefer — informs investment in Attribute mode."
  analysis_recipe: "Pie chart of Text vs Attribute selections over 30 days. Combine with Property Extracted to get per-mode completion rate."
  stakeholder_narrative: "85% of extractions use Text mode vs 15% Attribute — we should double down on Text UX before expanding Attribute capabilities."
  priority: 2
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire in onChange of Extract Type select, passing new value."

- name: "Property Extraction Failed"
  category: friction_failure
  rationale: "Surfaces where the extract workflow breaks for reliability prioritization."
  analysis_recipe: "Error rate chart: Property Extraction Failed / (Property Extracted + Property Extraction Failed), grouped by error reason. Alert on spikes."
  stakeholder_narrative: "Extraction failure rate dropped from 12% to 3% after the v2 error-handling patch — users are hitting fewer dead ends."
  priority: 2
  surface: "PropertyItem"
  file: "src/components/PropertiesPanel/PropertyItem.tsx"
  instrumentation: "Fire in catch/onError of extract call. Include error reason if available."
请勿包含:
Extract Type Dropdown Opened
(仅点击,无结果)、
PropertyItem State Updated
(内部操作)、
Attribute Input Focused
(粒度太细)。