
pstack Benny 自动化中的 Feature Map为缺陷复现绘制用户视角的功能地图【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins在 Cursor 的 pstack 插件中benny是一套面向 Slack 问题报告的自动化包一个 automation 负责分诊triage另一个负责复现已确认的 bug 并在必要时准备有界的草稿修复。复现 automation 不直接“认识”你的应用而是通过一个可配置的控制适配器control adapter去驱动真实 UI。feature-map.example.md 正是这个体系的核心文档它定义了“功能地图”feature map的编写模板、填写规则和一个完整虚构示例。读完后你将掌握如何为任意应用编写一份 Benny 可直接消费的 feature map理解它与控制适配器契约的逐字段对应关系以及它在复现、证据采集与 setup 校验流程中如何被实际调用。Feature Map 在 Benny 体系中的位置Benny 的复现技能 reproduce-and-fix-issues/SKILL.md 开头就声明了 fail-closed 原则Load the external Benny configuration supplied by the automation. If the config, required actions, control adapter, orcompleted feature mapis missing, fail closed.也就是说feature map 与外部配置、控制适配器并列为复现工作的前置条件缺失时整个流程直接停止而不是让 Agent 现场猜测路径与选择器。它的定位可以概括为三句话均出自文档开头Map every user-facing feature Benny may reproduce为每一个 Benny 可能复现的用户可见功能建一个条目Read the relevant section before driving the app驱动应用之前先读对应章节而不是边做边找Keep this map at the user point of view. Discover internals and current code paths at runtime instead of freezing them here地图只记录用户视角实现细节和当前代码路径属于运行时发现不能固化进地图否则应用一重构地图就过期。这与 setup-benny/SKILL.md 的要求一致Fill one feature-map section for every user-facing feature the automation may reproduce. Keep it at the user point of view. Do not freeze implementation details or current code paths in the map.存放位置与打包规则文档第 5 行给出了明确的存放约定Copy this file outside.cursor/automations/benny/, for example to.cursor/benny/feature-map.md, and setcontrol.feature_map_pathto the copy. Pack refreshes must not overwrite it.即把模板复制到打包目录之外如.cursor/benny/feature-map.md再填写并让配置的control.feature_map_path指向这份副本。原因是 Benny 的整个目录会被安装/刷新到目标仓库的.cursor/automations/benny/下见 README.md 与 FOR_AGENTS.md而用户自有的配置、feature map、routing map 必须放在包外这样“pack refresh包刷新”更新源文件时才不会覆盖你填写的内容。FOR_AGENTS.md 的 shared rules 中也重申了这一点i keep user-owned configuration, feature maps, routing maps, and secrets outside.cursor/automations/benny/so pack refreshes cannot overwrite them.配套的 configuration.example.yaml 中对应的控制块为control: skill_name: control-target-app feature_map_path: .cursor/benny/feature-map.md environment: safe-test-environment-placeholder artifact_directory: /tmp/benny-artifacts artifact_retention_hours: 24其中skill_name指向实现适配器契约的控制技能feature_map_path即指向上面这份用户自有的功能地图副本。单功能模板七个必填小节文档的 “Per-feature template” 一节给出了每个功能条目必须遵循的固定结构。以下按原文顺序完整展开并说明每个字段的含义与消费方。条目骨架每个功能用一个 H3 标题承载功能名紧跟一行“用户可见目的”### feature name one-line user-visible purpose1. How a user gets there用户如何到达Click pathscreen - menu, tab, or panel - control描述从哪个界面、经过哪个菜单/标签/面板、点哪个控件进入该功能Keyboard shortcutshortcut or none快捷键或明确写 none。这一节是“用户路径”复现时 SKILL.md 要求找到 “the feature-map section that matches the reported user path”——即拿用户报告中的操作路径来匹配地图条目所以这里的书写方式直接决定能否被正确路由到对应功能。2. How the control adapter drives it适配器如何驱动它逐条列出adapter actionwithinputsshouldvisible result即“执行某适配器动作、带上某输入、应观察到某可见结果”Reset说明适配器如何把该功能恢复到全新状态。Reset 不是可选装饰SKILL.md 的复现步骤要求“Reset enough state to make the second attempt independent”把状态重置到足以让第二次尝试独立而控制适配器契约 control-adapter.md 同样要求适配器“Reset the feature for a second independent repro attempt”。3. Stable selectors稳定选择器role and accessible name角色加可访问名称ARIA relationshipARIA 关系data-component or purpose-named data attribute组件标记或按用途命名的 data 属性。随后是一条硬性禁令Never use generated CSS or StyleX classes, dynamic hashes, child indexes, or brittle DOM position.禁止使用生成的 CSS/StyleX 类名、动态哈希、子节点序号和脆弱的 DOM 位置。这与适配器契约中 “Drive mapped features and states” 一节的选择器规则逐字呼应“Never use generated CSS or StyleX classes, dynamic hashes, child indexes, or brittle DOM position”说明模板里的选择器不是给人看的装饰而是适配器实现要直接遵守的契约。4. States to exercise需要演练的状态模板要求覆盖四组状态Default, hover, focus-visible, active, disabledLoading, empty, errorSelected, open, expandedrelevant feature-specific variants功能特有的状态变体并注明 “Mark states that do not apply”——不适用的状态要显式标记而不是静默省略。适配器契约对应要求“Interact with default, hover, focus-visible, active, disabled, loading, empty, error, selected, open, expanded, and feature-specific stateswhen they apply”即地图标了不适用适配器就不必演练该状态。5. Preconditions and setup前置条件与准备五个维度必须写全Authaccount state账户状态Datafixture数据 fixturePermissionsrole角色/权限Flagsflag or none特性开关Servicesrequired availability依赖服务的可用性。适配器契约中“Arrange a state through safe fixture data, permissions, flags, service responses, or supported test controls”正是消费这份前置清单用安全的 fixture、权限、开关、服务响应或受支持的测试控件去布置状态。文档同时强调与契约同文布置前置条件不等于可以注入缺陷本身“The repro itself must still come from real user interaction”。6. Evidence and cross-check证据与交叉验证Screenshotapp identity, feature, and discriminating state——截图必须能同时看出“是哪个应用”“是哪个功能”“处于哪个有区分度的状态”Videoentry path, interaction, and final state——录屏必须覆盖入口路径、交互过程和最终状态Cross-checkread-only state or value that confirms the UI——一个只读的状态或取值用来独立确认 UI 所示。这对应 SKILL.md 第 8 步“Capture and review evidence”复现成功要录制完整路径、截图 broken final state、并由只读的媒体评审员回答唯一问题——“does the evidence visibly show the discriminating broken state?”。模板中的 cross-check 字段“Check selected-item ID”“Check the stored item value read-only”就是 SKILL.md 第 7 步第 7 条 “Cross-check a real state value when possible” 的落地位置。7. Gotchas已知陷阱known dead end or wrong surface已知的死路或错误界面例如营销页不是目标界面、只读详情页不是编辑器safe environment translation安全的环境转译。第二条对接的是适配器契约的 “Environment translation” 一节在宣布环境被阻塞之前先用去掉平台专有名词的措辞重述缺陷询问同一行为能否在可用环境里安全地测转译得来的证据必须标注为 translated evidence不能当作精确复现。虚构示例任务应用的四个功能文档用四个“虚构任务应用”的功能完整演示了模板的填法原文明确声明 “They are examples, not required Benny features”即仅为示例、不是 Benny 必须实现的功能。下面完整保留这四个示例的每个字段。Sign in登录目的让用户进入任务应用。到达路径打开应用并选择Sign in无快捷键。适配器驱动open_app、click Sign in、fill credentials、click Continue应打开 item 列表Reset 通过登出并清掉一次性会话完成。稳定选择器按钮Sign in、文本框Email和Password、data-componentsign-in-form。演练状态Default、focus-visible、submitting、disabled、loading、error。前置条件一次性disposable账户 可用的认证服务。证据与交叉验证录制从落地页到 item 列表的完整过程以只读方式检查会话状态。陷阱营销页是错误的界面wrong surface认证服务缺失属于 block阻塞而非复现失败。Item list and detail列表与详情目的让用户浏览 items 并打开其中一条。到达路径打开Items标签页然后选中一行。适配器驱动select_tab Items加click fixture item应打开其详情页Reset 通过关闭详情并清除选中完成。稳定选择器名为Items的标签页和列表、以 fixture 命名的行、data-componentitem-detail。演练状态Loading、empty、error、selected、open、expanded。前置条件有名字的 fixture items、读权限、可用的 item 服务。证据与交叉验证展示选中态与相匹配的详情标题以只读方式核对 selected-item ID。陷阱搜索结果可能外观相似但走的是不同路径不要拿搜索结果页冒充列表页路径。Item editor条目编辑器目的让用户创建或编辑条目。到达路径从详情页选Edit或从列表选New item。适配器驱动click Edit、fill field、click Save应更新详情页Reset 通过恢复 fixture 完成。稳定选择器按钮Edit、New item、Save表单Item editorlabel-linked fields由 label 关联的字段。演练状态Default、focus-visible、dirty、validating、disabled、saving、error、success。前置条件可编辑的 fixture、写权限、可用的保存服务。证据与交叉验证展示从字段变化到详情页更新的全过程以只读方式核对存储的条目值。陷阱不要注入表单状态do not inject form state只读的详情字段不是编辑器别认错界面。Settings设置目的让用户修改个人偏好。到达路径打开个人资料菜单再选Settings。适配器驱动open_menu Profile、click Settings、toggle preference应更新对应控件Reset 通过恢复初始偏好完成。稳定选择器按钮Profile、菜单项Settings、regionSettings、按用途命名的偏好属性。演练状态Closed、open、selected、focus-visible、disabled、loading、error。前置条件已登录的测试账户、已知偏好值、可用的偏好服务。证据与交叉验证展示菜单路径与最终控件状态以只读方式核对偏好取值。陷阱操作系统设置是另一个界面different surface不要与应用的设置页混淆。这四个示例恰好覆盖了模板的七个小节并示范了两个易错点一是每个条目都写明 Reset两次独立复现的基础二是每个条目都给出只读交叉验证对应 SKILL.md “State inspection may confirm an observation. It must not inject or force the symptom” 的边界。完整性检查清单文档末尾的 “Completeness checklist” 是验收一份 feature map 是否合格的九条标准建议逐条对照自查Every reproducible user-facing feature has a section——每个可复现的用户可见功能都有条目Every section names a user path, adapter actions, and reset——每个条目都给出用户路径、适配器动作和 ResetSelectors use roles, names, ARIA, stable component markers, or purpose-named attributes——选择器只用角色、名称、ARIA、稳定组件标记或按用途命名的属性No selector uses generated classes or DOM position——没有任何选择器依赖生成类名或 DOM 位置Relevant interaction, loading, empty, error, selected, and expanded states are covered——相关的交互、loading、empty、error、selected、expanded 状态都被覆盖Auth, fixtures, permissions, flags, and services are explicit——认证、fixture、权限、开关、服务全部显式列出Screenshot, video, and underlying cross-check requirements are explicit——截图、录屏与底层交叉验证的要求明确Wrong surfaces, dead ends, and safe environment translations are listed——错误界面、死路和安全环境转译都列了出来Implementation details remain runtime discoveries——实现细节保持为运行时发现未固化进地图。Feature Map 在复现流程中的真实消费方式模板并非孤立存在它在 SKILL.md 的工作流和适配器契约里有明确的消费点。梳理如下复现前的“第 5 步”加载并检查适配器SKILL.md 第 5 步Load and check the control adapter规定Readreferences/control-adapter.mdand the completed map atcontrol.feature_map_path, then invoke the skill named bycontrol.skill_name. Find the feature-map section that matches the reported user path. Read it before driving the app. If no section covers the feature, mark the run blocked instead of inventing a path or selector.注意最后一句地图里找不到对应章节时标记本次运行为 blocked而不是现场发明路径或选择器。feature map 因此同时充当了“导航手册”和“能力边界声明”——适配器契约也要求它“Report which feature-map sections it can drive and which are blocked”。同一节还列出了适配器必须具备的七项能力Bring up、Navigate mapped features、Drive real UI、Inspect state、Screenshot、Recording、Cleanup其中第 2 项 “Navigate the mapped feature and exercise its documented states” 直接依赖地图条目中登记的适配器动作名与状态清单任一项缺失即标记 blocked 并停止“Do not pretend a screenshot, unit test, state mutation, or source reading is a UI repro”。适配器契约的“Drive mapped features and states”control-adapter.md 用一个独立小节把地图字段与适配器义务一一对应起来Feature Map 字段适配器义务契约原文要求How a user gets there“Read the relevant feature-map section before driving the app”按用户可见路径导航How the control adapter drives it调用该功能登记的 adapter action 名Reset 用于第二次独立复现States to exercise演练 default、hover、focus-visible、active、disabled、loading、empty、error、selected、open、expanded 及功能特有状态when they applyPreconditions and setup用 fixture、权限、flags、服务响应或测试控件布置状态但不得借此注入缺陷本身Stable selectors角色、可访问名称、ARIA、稳定组件标记、按用途命名的 data 属性禁用生成类名、动态哈希、子节点序号、DOM 位置Evidence and cross-check捕获地图点名的截图、视频与只读交叉验证启用前的九步 setup check适配器契约的 “Setup check” 一节要求在启用复现 automation 之前跑一次无害的适配器自检九步全部成功且全程不向 Slack 源频道发消息才允许启用Bring up the app拉起应用Confirm the stable app marker确认可稳定识别的应用标记Load one completed feature-map section加载一份已完成的地图章节Navigate to that feature through its user path按用户路径导航到该功能Exercise one disposable state through mapped adapter actions用登记的动作演练一个可丢弃状态Inspect the resulting state检查 resulting 状态Capture a screenshot截图Record a short clip录制短片Clean up清理。第 35 步正是对 feature map 单条目字段的端到端验证条目里的用户路径、适配器动作名、状态清单是否真实可执行在这一轮自检中就会暴露出来。与复现主循环的衔接确认“已复现”前SKILL.md 第 7 步要求完成七个动作命名正确终态、命名错误终态、到达二者分歧点、观察到错误状态、重置到足以独立的状态、重复同一路径并再次观察到同一错误状态、尽可能交叉核对真实状态值。其中“重置”和“交叉核对”两步分别消费地图条目中的 Reset 字段与 Cross-check 字段第 8 步的证据评审则消费 Evidence 字段。第 13 步 “Prove the fix” 在打补丁的构建上重复同样的真实 UI 路径两次并要求 “Cross-check the same real state value used for the baseline”——即 before/after 两侧使用地图中登记的同一个只读值保证证据口径一致。编写建议从模板规则到实操综合模板正文、虚构示例与检查清单编写一份合格 feature map 时值得遵守的实践要点按功能建条目不按代码模块建条目。条目名与“到达路径”都从用户视角出发Sign in、Items标签页实现细节留给运行时发现。应用重构后地图仍然有效反之把代码路径写进地图会让地图率先腐化。动作写成“输入—动作—可见结果”三元组例如 “click Saveshould update detail”。SKILL.md 与适配器契约反复强调“visible result”“real user actions”可见结果是适配器校验动作是否生效的依据。Reset 必须真实可执行。“sign out and clear the disposable session”“restore the fixture”这类描述是可执行方案两次独立复现、baseline/patched 对比都建立在它之上。选择器四选三角色可访问名、ARIA 关系、稳定组件标记、按用途命名的属性。写完可对照清单第 3、4 条自查是否混入了生成类名或序号定位。不适用的状态要写“不适用”而不是漏写。清单第 5 条要求覆盖相关状态模板要求 “Mark states that do not apply”——显式标记让适配器契约里的 “when they apply” 判断有据可依。Gotchas 是复现效率的来源。“营销页是错误界面”“搜索结果走的是不同路径”“只读详情字段不是编辑器”这类一句话提示能省掉 Agent 在错误界面上反复试探的时间“safe environment translation” 条目则对接契约的转译规则预先声明哪些转译是安全的。完成标准以九条清单验收并以 setup check 九步做运行时验收。前者审文档后者验适配器两者都通过后才适合把control.feature_map_path指向该文件并启用benny-reproduce。小结feature-map.example.md 的价值不在模板本身而在于它把“Agent 如何在真实 UI 上可靠地复现缺陷”这件事拆成了可检查的字段用户路径决定条目能否被路由到适配器动作与 Reset 决定复现能否两次独立执行稳定选择器决定驱动是否可复现状态清单决定覆盖是否完整前置条件决定环境能否布置证据字段决定结果能否被评审Gotchas 决定少踩多少坑。配合 configuration.example.yaml 中的control配置块、SKILL.md 的十五步工作流与 control-adapter.md 的适配器契约它构成了 pstack Benny 复现链路中“文档—配置—契约”三层互相咬合的一环地图缺失则 fail closed条目缺章节则标记 blocked字段不完整则无法通过九步 setup check。这套“先写清地图、再驱动界面、证据先行”的设计对任何让 Agent 操作真实 GUI 的自动化方案都有直接参考价值。【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考