feat: add bounded session and history navigation
Add session scrolling, latest-message navigation and fingerprint location under the shared UI gate; reuse navigation in history reads and provide read-only smoke. Navigation index snapshot passed 124 tests and a full build. Windows 4.1.13.63 read-only validation passed 10/10, including two-scroll history location; no sends. Record scope limits, including next-unread navigation not yet implemented.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# 导航增量验收 — 2026-09-06
|
||||
|
||||
## 本次实现
|
||||
|
||||
- `session scroll --direction up|down --pages N`:会话列表滚动;默认不输出联系人名称,`--include-content` 显式开启。
|
||||
- `chat latest [--session <name>]`:回到指定会话的最新可见消息。
|
||||
- `chat locate --fingerprint <可见消息指纹> [--session <name>] [--scrolls N]`:有界向上搜索并将匹配行带入视口。
|
||||
- `chat history` 支持 `--session`;两个历史读取入口复用共享滚动与回到最新逻辑,不再按累计滚轮距离猜测返回位置。
|
||||
- `chat merged-open` 是可选的卡片窗口导航,仅返回新窗口句柄,**不负责内容提取**。合并内容的正式读取由独立的 `db merged` 实现。
|
||||
- 增加 `smoke --read-only`,明确返回 `sendSkipped=true`、`confirmed=false`;只读验证不发送标记。
|
||||
|
||||
所有 UI 操作使用现有跨进程命令锁、输入桌面检查和会话核验。先使用 UIA Scroll/ScrollItem,缺失时使用集中维护的滚轮兜底;不点击输入框、不发送或转发消息。
|
||||
|
||||
## 验证
|
||||
|
||||
- 微信 `4.1.13.63`,Windows 真机 `10.1.1.101` 的现有已登录会话。
|
||||
- 发布目录:`C:\Users\Rogee\wx-agent\releases\navigation-20260906T113948`。
|
||||
- Linux Core 测试 **124/124**,完整 Release build **0 warnings / 0 errors**。
|
||||
- `Test-Navigation.ps1` 最终 **10/10** 通过,发送次数 **0**:doctor、inspect-ui、只读 smoke、会话下滚/上滚、回到最新、历史读取、定位、再次回到最新、打开合并卡片。
|
||||
- 定位测试确实向上滚动 **2 次**后找到指定指纹,不是仅匹配当前页。
|
||||
- 第一次脚本将 JSON 枚举误作数字,7 步后主动停止;修正为 `Text` / `Merge` 后完成第二次只读验证。未把第一次失败记为通过。
|
||||
|
||||
脱敏证据:[`evidence/Navigation-20260906/`](evidence/Navigation-20260906/)。不提交联系人名称、消息正文或完整 UI 树。
|
||||
|
||||
## 边界
|
||||
|
||||
- 指纹是现有 UIA 可见快照指纹,不是数据库 server ID;相同文本重复消息在不同视口的身份仍有局限,不能据此进行不可逆操作。
|
||||
- 无原生滚动百分比时,“回到最新”依赖连续稳定视口,不宣称数据库历史完整性。定位达到滚动上限返回 `ResultUnconfirmed`;视口停止变化而未找到返回 `ControlNotFound`。
|
||||
- 本增量未实现“下一个未读会话”。会话列表缺少已验证的未读标记时,不从预览文本猜测未读状态。
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"Scrolls": 2,
|
||||
"message": {
|
||||
"Fingerprint": "1e59c51f8086b6ec6d80e34a16daabc0359f0fd4f4633289113e653b9b0ab166",
|
||||
"Type": "Text",
|
||||
"length": 61,
|
||||
"content": null,
|
||||
"quote": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"Scrolls": 2,
|
||||
"ViewportChanged": true,
|
||||
"sessions": [
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:1DC65E74B01A64FA",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:B0E5330510C53A70",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:4DF34FAE92A9BB26",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:2EF8DCA410614184",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:2092711F288D71DA",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:AD8DF8A5CA6DCC46",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:BA4121C435EF5D04",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:563C6AC6EFB52329",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:5F1E8BDE6155432A",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:D93D7F06AE52537F",
|
||||
"IsCurrent": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"Scrolls": 2,
|
||||
"ViewportChanged": true,
|
||||
"sessions": [
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:28032CB51B5D5918",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:EC654065E79D4554",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:C7CE04276AC5A9C4",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:9F775FAD499E92FF",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:2B55CD2E01D1E400",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:A5B67004830C26E7",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:8ABDA031D8E42C4E",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:68C6E1577C7F5576",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:BFE36215E3C4FDAA",
|
||||
"IsCurrent": false
|
||||
},
|
||||
{
|
||||
"name": null,
|
||||
"nameId": "sha256:1DC65E74B01A64FA",
|
||||
"IsCurrent": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"scope": "M1",
|
||||
"doctorErrors": [],
|
||||
"output": "C:\\Users\\Rogee\\wx-agent\\releases\\navigation-20260906T113948\\artifacts\\ui-tree.json",
|
||||
"nodes": 154,
|
||||
"sanitized": true,
|
||||
"sentTo": null,
|
||||
"Fingerprint": null,
|
||||
"sendSkipped": true,
|
||||
"confirmed": false
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Checks": [
|
||||
{
|
||||
"Stage": "doctor",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "inspect-ui",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "smoke",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "sessions-down",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "sessions-up",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "latest-before",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "history",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "locate",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "latest-after",
|
||||
"ExitCode": 0
|
||||
},
|
||||
{
|
||||
"Stage": "merged-open",
|
||||
"ExitCode": 0
|
||||
}
|
||||
],
|
||||
"SendsAttempted": 0,
|
||||
"BinarySha256": "F443EC6EF044F66349E55EBEB4ED0109EA13C96D8216079AEAEE3A19DF9A32DA",
|
||||
"Success": true
|
||||
}
|
||||
Reference in New Issue
Block a user