Files
isphere-ai-bridge/docs/superpowers/specs/2026-07-09-n13-uia-selector-catalog-design.md
2026-07-09 14:52:13 +08:00

598 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# N13 UIA Selector Catalog Design
日期2026-07-09
## 1. 目标
N13 的目标是基于已 ACCEPT 的 N12R live UIA 证据,设计一套只读 selector catalog 和定位验证流程。
本阶段只做设计,不新增 helper op不新增 MCP tool不点击、不输入、不打开会话、不发送消息、不传输文件。
N13 完成后,下一步才可以写独立实现计划,考虑是否新增只读定位验证能力。
## 2. 输入证据
N12R 返回包已通过外网 validator
```text
runs/internal-sandbox-live-capture-reports/2026-07-09-retry-2/2026-07-08-internal-sandbox-a-validation.md
Decision: ACCEPT
PASS: 36
WARN: 1
FAIL: 0
```
使用的 UIA dump
```text
runs/internal-sandbox-live-capture-intake/2026-07-09-retry-2/2026-07-08-internal-sandbox-a/uia/dump-uia-main.json
```
关键事实:
```text
root control_type: Window
root automation_id: frmMain
root class_name: WindowsForms10.Window.8.app.0.d3a00f_r29_ad1
framework_id: WinForm
UIA node count: 66
max_depth: 7
```
本设计只引用结构性字段,不依赖敏感可见文本。
## 3. 非目标
N13 不做以下事项:
```text
自动登录
搜索联系人
打开会话
点击控件
输入文本
发送消息
发送文件
接收文件
读取或导出聊天内容
注入进程
hook
读取目标进程内存
绕过终端安全/安防
```
N13 也不把 `search_contacts``open_conversation``read_latest_messages` 作为当前实现目标。这些只能在 selector catalog 稳定、只读定位验证通过、并形成新的审批设计后再讨论。
## 4. 推荐方案
采用“selector catalog + 只读定位验证”方案。
核心思想:
1. 用 N12R UIA dump 建立一份 selector catalog。
2. 每个 selector 都只描述如何识别一个 UIA 节点。
3. selector 的初始用途只允许 read-only locate。
4. 后续如果实现 `locate_uia`,也只能返回匹配节点摘要,不执行任何 UI 动作。
5. 任何真实动作类能力必须另写设计、计划和审批边界。
## 5. Selector 数据模型
建议 selector 条目使用以下字段:
```json
{
"id": "main_window",
"description": "主窗口",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "frmMain",
"control_type": "Window",
"framework_id": "WinForm"
},
"preferred": {
"class_name_prefix": "WindowsForms10.Window.8.app.0",
"path_hint": "root"
},
"fallback": [
{
"control_type": "Window",
"class_name_prefix": "WindowsForms10.Window.8.app.0",
"child_automation_id_contains": ["panelLeft", "ucPluginTabControl1"]
}
],
"stability_score": 95,
"evidence": {
"capture_id": "2026-07-08-internal-sandbox-a",
"uia_path": "root"
}
}
```
字段含义:
- `id`:稳定、短小、英文蛇形命名。
- `description`:中文说明。
- `allowed_use`N13 固定为 `read_only_locate`
- `required`:必须同时满足的字段。
- `preferred`:加分项,用于减少误匹配。
- `fallback`:主 selector 失效时的只读匹配策略。
- `stability_score`0 到 100越高越稳定。
- `evidence`:来源证据路径和 UIA 路径。
## 6. 初始 selector catalog
### 6.1 主窗口:`main_window`
```json
{
"id": "main_window",
"description": "iSphere / IMPlatformClient 主窗口",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "frmMain",
"control_type": "Window",
"framework_id": "WinForm"
},
"preferred": {
"class_name_prefix": "WindowsForms10.Window.8.app.0",
"path_hint": "root"
},
"fallback": [
{
"control_type": "Window",
"class_name_prefix": "WindowsForms10.Window.8.app.0",
"child_automation_id_contains": ["panelLeft", "ucPluginTabControl1"]
}
],
"stability_score": 95,
"evidence": {
"uia_path": "root"
}
}
```
理由:`automation_id=frmMain` 出现在根节点root 是 N12R 已确认主窗口,稳定性最高。
### 6.2 主 tab 容器:`main_plugin_tab`
```json
{
"id": "main_plugin_tab",
"description": "主功能 tab 容器",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "ucPluginTabControl1",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/3",
"ancestor_selector": "main_window"
},
"fallback": [
{
"ancestor_selector": "main_window",
"control_type": "Pane",
"child_automation_id_contains": ["FrmHomePage", "ucTabPage"]
}
],
"stability_score": 90,
"evidence": {
"uia_path": "root/3"
}
}
```
理由该节点直接挂在主窗口下automation_id 明确,子结构包含首页和 tab 内容区。
### 6.3 首页窗口:`home_page_window`
```json
{
"id": "home_page_window",
"description": "首页内容窗口",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "FrmHomePage",
"control_type": "Window",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/3/0/0",
"ancestor_selector": "main_plugin_tab"
},
"fallback": [
{
"ancestor_selector": "main_plugin_tab",
"control_type": "Window",
"class_name_prefix": "WindowsForms10.Window.8.app.0"
}
],
"stability_score": 82,
"evidence": {
"uia_path": "root/3/0/0"
}
}
```
理由:该节点可用于确认当前主 UI 内容区存在,但不用于动作。
### 6.4 tab 内容窗口:`tab_page_content`
```json
{
"id": "tab_page_content",
"description": "tab 页内容窗口",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "FrmTabPageContent",
"control_type": "Window",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/3/1/0",
"ancestor_selector": "main_plugin_tab"
},
"fallback": [
{
"ancestor_selector": "main_plugin_tab",
"control_type": "Window",
"child_control_type_contains": ["TitleBar"]
}
],
"stability_score": 82,
"evidence": {
"uia_path": "root/3/1/0"
}
}
```
理由:可作为后续只读结构检查的内容区域锚点。
### 6.5 左侧面板:`left_panel`
```json
{
"id": "left_panel",
"description": "左侧主面板",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "panelLeft",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/4",
"ancestor_selector": "main_window"
},
"fallback": [
{
"ancestor_selector": "main_window",
"control_type": "Pane",
"child_automation_id_contains": ["ucPnlRoster1", "ucFuzzyQuery1"]
}
],
"stability_score": 92,
"evidence": {
"uia_path": "root/4"
}
}
```
理由:该节点是联系人/搜索相关区域的稳定父节点。
### 6.6 组织/联系人容器:`roster_panel`
```json
{
"id": "roster_panel",
"description": "组织/联系人容器外层",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "ucPnlRoster1",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/4/0/0",
"ancestor_selector": "left_panel"
},
"fallback": [
{
"ancestor_selector": "left_panel",
"control_type": "Pane",
"child_automation_id_contains": ["ucRoster1"]
}
],
"stability_score": 88,
"evidence": {
"uia_path": "root/4/0/0"
}
}
```
理由:该节点是 roster 结构外层,可以只读验证联系人区域是否存在。
### 6.7 组织/联系人列表:`roster_view`
```json
{
"id": "roster_view",
"description": "组织/联系人列表区域",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "ucRoster1",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/4/0/0/0",
"ancestor_selector": "roster_panel"
},
"fallback": [
{
"ancestor_selector": "roster_panel",
"control_type": "Pane",
"class_name_prefix": "WindowsForms10.Window.8.app.0"
}
],
"stability_score": 86,
"evidence": {
"uia_path": "root/4/0/0/0"
}
}
```
理由:该节点本次 child_count 为 0不能证明列表项结构只能作为区域存在性 selector。
### 6.8 搜索组件外层:`fuzzy_query_panel`
```json
{
"id": "fuzzy_query_panel",
"description": "模糊搜索组件外层",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "ucFuzzyQuery1",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/4/1/0",
"ancestor_selector": "left_panel"
},
"fallback": [
{
"ancestor_selector": "left_panel",
"control_type": "Pane",
"child_automation_id_contains": ["FrmFuzzyQuery"]
}
],
"stability_score": 90,
"evidence": {
"uia_path": "root/4/1/0"
}
}
```
理由:该组件是搜索输入框的稳定父级。
### 6.9 搜索窗口:`fuzzy_query_window`
```json
{
"id": "fuzzy_query_window",
"description": "模糊搜索内部窗口",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "FrmFuzzyQuery",
"control_type": "Pane",
"framework_id": "WinForm"
},
"preferred": {
"path_hint": "root/4/1/0/0",
"ancestor_selector": "fuzzy_query_panel"
},
"fallback": [
{
"ancestor_selector": "fuzzy_query_panel",
"control_type": "Pane",
"child_automation_id_contains": ["skinAlphaTxt"]
}
],
"stability_score": 88,
"evidence": {
"uia_path": "root/4/1/0/0"
}
}
```
理由:该节点包含搜索输入框,是后续只读定位验证中的关键父节点。
### 6.10 搜索输入框:`fuzzy_search_edit`
```json
{
"id": "fuzzy_search_edit",
"description": "模糊搜索输入框",
"allowed_use": "read_only_locate",
"required": {
"automation_id": "skinAlphaTxt",
"control_type": "Edit",
"framework_id": "WinForm"
},
"preferred": {
"class_name": "WindowsForms10.EDIT.app.0.d3a00f_r29_ad1",
"path_hint": "root/4/1/0/0/2",
"ancestor_selector": "fuzzy_query_window"
},
"fallback": [
{
"ancestor_selector": "fuzzy_query_window",
"control_type": "Edit",
"class_name_prefix": "WindowsForms10.EDIT.app.0"
}
],
"stability_score": 93,
"evidence": {
"uia_path": "root/4/1/0/0/2"
}
}
```
理由:该节点 automation_id、control_type 和 class_name 都明确。N13 只允许定位它,不允许输入搜索词。
## 7. 只读定位验证规则
后续如果实现定位验证,只能做以下事情:
1. 接收 selector id。
2. 读取当前窗口 UIA 树。
3. 按 selector required 字段过滤节点。
4. 用 preferred 字段排序或加分。
5. 如果主 selector 无匹配,再尝试 fallback。
6. 返回节点摘要:`selector_id``matched``match_count``path``control_type``automation_id``class_name``framework_id``is_enabled``is_offscreen``bounds`
禁止返回完整 visible text。可见文本只能返回以下派生信息
```text
has_name: true/false
name_length: number
```
禁止执行:
```text
InvokePattern
ValuePattern.SetValue
SelectionItemPattern.Select
ExpandCollapsePattern.Expand
点击
键盘输入
剪贴板操作
窗口激活
焦点切换
```
## 8. 稳定性评分规则
建议评分:
```text
95-100: root 或唯一主窗口级 anchor
90-94: automation_id 明确、control_type 明确、父子路径稳定
80-89: automation_id 明确,但可能依赖 tab 或运行状态
70-79: 缺 automation_id但 class/control/path 组合可用
0-69: 不进入首批 catalog
```
本次首批 selector 全部要求 automation_id 明确。
## 9. 错误处理设计
只读定位验证应返回结构化结果,不抛出模糊错误。
建议结果:
```json
{
"ok": true,
"selector_id": "fuzzy_search_edit",
"matched": true,
"match_count": 1,
"matches": [
{
"path": "root/4/1/0/0/2",
"control_type": "Edit",
"automation_id": "skinAlphaTxt",
"class_name": "WindowsForms10.EDIT.app.0.d3a00f_r29_ad1",
"framework_id": "WinForm",
"has_name": true,
"name_length": 0
}
],
"warnings": []
}
```
未匹配时:
```json
{
"ok": true,
"selector_id": "fuzzy_search_edit",
"matched": false,
"match_count": 0,
"matches": [],
"warnings": ["selector_not_found"]
}
```
selector 定义非法时:
```json
{
"ok": false,
"selector_id": "fuzzy_search_edit",
"error": {
"code": "INVALID_SELECTOR",
"message": "selector required fields are incomplete"
}
}
```
## 10. 测试策略
N13 设计阶段不写实现代码,但后续实现计划必须包含以下测试:
1. 从 N12R dump fixture 读取 UIA 树。
2. 验证 `main_window` 匹配唯一 root。
3. 验证 `left_panel` 匹配 `root/4`
4. 验证 `fuzzy_search_edit` 匹配 `root/4/1/0/0/2`
5. 验证 selector 不返回完整 `name` 文本,只返回 `has_name``name_length`
6. 验证缺失 selector 返回 `matched=false`,不报崩溃。
7. 验证动作模式字段或动作请求被拒绝。
8. 验证 catalog 中不包含 `send``upload``download``conversation``login` 等动作词作为工具名。
## 11. 文件规划
如果后续进入实现计划,建议新增或修改:
```text
internal/uiaselector/catalog.go
internal/uiaselector/catalog_test.go
internal/uiaselector/matcher.go
internal/uiaselector/matcher_test.go
internal/uiaselector/testdata/n12r-2026-07-09-uia-redacted.json
scripts/verify-n13-uia-selectors.ps1
```
暂不修改:
```text
native/ISphereWinHelper/Program.cs
internal/tools/winhelper.go
cmd/isphere-mcp/main.go
```
除非新的实现计划明确批准新增只读定位工具,否则 Go MCP 仍只暴露现有四个只读工具。
## 12. N13 验收条件
N13 设计可接受条件:
1. selector catalog 只依赖结构性 UIA 字段。
2. 不依赖敏感可见文本。
3. 首批 selector 都能追溯到 N12R ACCEPT dump 的路径。
4. allowed_use 全部是 `read_only_locate`
5. 文档明确禁止点击、输入、打开会话、发送和文件操作。
6. 后续实现计划必须 TDD并先使用 fixture 测试 selector matcher。
## 13. 推荐下一步
下一步不是直接写代码,而是写一份 N13 implementation plan。
该计划应先实现纯离线 selector matcher对 N12R UIA dump fixture 做只读匹配测试。
只有离线 selector matcher 通过后,才讨论是否新增 live `locate_uia` helper/MCP 只读工具。