Repository navigation
fix(telemetry): isolate temporary machine routes across usage channels - #8168
Conversation
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.
未发现本次引入的阻断问题,结论 APPROVE。必要本地 premerge 和 CQR 仍为失败;相同 Todo 兼容性故障在不可变基线与本 head 上独立复现,评审通过不解除合并门。
动机 / Motivation
运行本地验证、临时安装或重建子进程环境的使用者,会遇到测试活动被当作真实安装统计的问题。 同一份临时机器状态在丢失关闭标记后,旧发送器会创建安装标识并发送统计;新路径识别实际临时位置,阻止发送并保留原状态。 本轮独立回环 HTTP 对照中,临时安装从五个请求变为零请求,正常持久安装的五个请求保持一致。 本次不清理历史统计,不推断个人或组织身份,不改变工作执行授权,也不宣称已经更新安装中的应用。 不修复会让每个可丢弃 HOME 累积新的合成安装记录,也不能凭历史标签安全地反向清理。
改动思路 / Approach
临时位置属于共用遥测 owner 的发送资格,放在现有 TypeScript owner 中可覆盖 CLI、后台发送和 Chat,避免三处维护不同政策。 当前 PR 交付物理路径防护、原发送入口接入、设置页状态和双语说明;不新增持久开关或另一套授权 owner。 环境标记仍是首道隔离,物理路径只是补充:仅修一个 smoke 会漏掉直接 CLI 和复制来的已开启状态;凭 test/scratch 名称猜测又会误伤正常用户。新 helper 只观察本机文件系统,原 owner 继续处理告知、同意、锁、generation 与网络请求。它不持久化新的“临时身份”。未知路径沿用设置不可用边界;可选遥测失败也不能替换工作命令的结果。
具体改动 / Changes
规范依据为 docs/reference/usage-ping.md,spec_revision 98d7a9f361414a461897aca711a85dedd42e5611;按修改前已接受的说明判断,而非用本 PR 改写后的文字自证。原文没有编号,下面以描述性标签映射四项义务:synthetic-runs-excluded(合成运行不计作安装)、shared-first-disclosure(CLI/脚本/App 共用首次告知政策)、explicit-disable-precedence(关闭阻止全部通道)、local-collector-only(专项测试仅向可丢弃本地收集器发送)均为 implemented,证据分别是独立 HTTP 对照、持久安装对照、关闭/排队并发回归、真实回环正例与远端拒绝。没有把可选设备用途标签当成同意。
关键代码讲解
temporaryUsageEnvironment把机器 HOME、状态、Host 配置和加载的运行时代码与系统/声明的临时根比较;physicalPath解析尚不存在文件的最近现存祖先和符号链接。按路径分量匹配,避免前缀相似的持久目录被误判;后台发送器本身使用临时工作目录,因此 CWD 不参与分类。blockedBy保留原显式关闭、CI、Do Not Track、策略与接收方优先级,再检查临时路径。仅LOOPX_USAGE_PING=1加数字回环收集地址可用于传输资格验证,不能越过前面的关闭或同意政策。observe在写计数、建立发送 claim、打开测量 sidecar 之前拒绝临时环境;后续 Goal/安装通道启动与发送摘要写回仍重查资格及原 generation。实际网络等待继续在锁外。UsageStatisticsSettings从真实blocked_by展示临时环境不发送,只有告知或明确同意是当前阻塞时才显示确认按钮。它继续通过同一 Chat API 回读,前端不能另行开启发送资格。
本轮独立对照使用相同类型化观察与真实本地 HTTP 收集器,源为上述 base 与 cddb47e88bb1319319a8290d36b28b55832fc29d:
| 输入 | 基线 | 本 head |
|---|---|---|
| 临时 HOME,丢失关闭标记 | 自动产生 ID;5 请求 | 不自动产生 ID;0 请求 |
| 临时 HOME,复制来的 enabled 状态 | 消耗状态并发送 | 状态字节不变;0 请求 |
| 正常持久 HOME,发送进程 CWD 临时 | 告知后 5 请求 | 同样 5 请求 |
| 显式数字回环传输正例 | 5 请求 | 5 请求 |
| CI / Do Not Track / 显式关闭 | 0 请求 | 0 请求 |
五个请求覆盖 heartbeat、CLI aggregate、diagnostic aggregate、Goal 和 installation;这是实际接收的 payload schema/route 对照,不只比较退出码。旧版本违反零请求/无自动 ID 的独立预期,新版本满足,因而反例具备回归敏感性。
对主干的风险 / Risks
主要风险是误伤持久安装或让旧 enabled 状态越过新防护。PASS:70 项 Node、65 项 Python 测试,无跳过;含真实 CLI、最小环境重建、standalone helper 覆盖顺序、Chat HTTP GET/告知/enable/disable 回读、别名与缺失路径、并发 claim、旧格式、撤销 generation、未知网络结果和显式关闭。根 TypeScript typecheck、diff/RFC 配对/编译、8 项风险 smoke 与全18文件公开边界扫描通过。原 sender/HTTP/store 真实执行;模型与线上收集服务没有参与。
FAIL:必要 native premerge 的 todo-readmodel-boundary-smoke.py 在 assert_status_compatibility_boundary 报 loopx.status.open_todo_items 缺失。同一命令在独立 base/head 的完整 traceback 仅归一化 checkout 前缀后完全相等,失败路径不在本 PR 改动中;当前遥测不变量另有上述通过证据。另有相同既有 interaction-contract 函数大小 advisory,未提高预算或登记豁免。已记录精确 CQR cqr_32f91207c52d3f86ec91,结果 fail,必要校验仍待其 owner 修复再验。按当前政策没有查询、轮询或等待远端 CI。
语义与 CI 对齐
temporary_path 是既有字符串状态投影中的 local_only 原因,不是共享工作状态或身份分类。双语说明和修复指导保留合成环境必须关闭的义务,并明确先合并调用方环境再强制关闭;物理路径防护不能取代该义务。未识别的自定义 scratch 要声明临时根或先持久关闭;不声称覆盖任意目录名。保留 v0/v1 机器状态兼容与原 notice/generation,未增加协议版本或另一套 Python 决策。必要红检查与审查结论分别保留。
我的整体评价 / Verdict
long_horizon 改善在于重复可丢弃环境不会继续制造统计和消耗待发数据,正常安装的后续活动、重放及撤销规则保持;user_experience 改善在于零新增必要确认轮次、临时环境状态真实且无无效确认入口。复用同一 head 的作者整页存档并用 Ego 独立查看:桌面和窄屏都把误导性的等待确认改为临时环境不发送,移除无效启用按钮;正文、接收方和详情仍可读。另行构建当前组件与原 CSS,在合成外壳中检查默认折叠、全部展开的预览及真实设置 owner 的不可用/关闭恢复。 已检查与改动相关的完整长内容页和下方区域,窄屏原有纵向滚动仍存在;关闭/不可用行为另有后端验证。组件补验使用合成外壳和真实 usage API/TS owner,不能替代完整应用布局或安装验证;未独立重建完整应用、验证已安装界面、原生 Windows 路径或所有页面。作者整页图也不证明后端持久性;该部分由实际 CLI/HTTP 对照覆盖。 当前没有布局、折叠或响应式改动,不要求重做所有未变页面。
这是一项完整、可回滚的临时遥测隔离修复;保留单一 owner 和小型物理路径 helper 的架构成本与复现风险相称。无需新设置、持久索引、额外工作流或扩大重构。必要校验和精确头合并就绪仍须分别通过;本评审不授予合并或安装权限。
English verdict: APPROVE — temporary routing blocks every telemetry channel without changing persistent-installation defaults. Required premerge/CQR remains held by an independently reproduced baseline failure.
临时 HOME 中直接运行 smoke,或者子进程重建环境丢掉关闭标记时,原来的自动告知流程会把测试当作普通使用并生成安装标识。用四次真实 CLI 调用和仅监听回环地址的 collector 复现:基线产生 3 次请求(心跳、调用诊断、安装快照),本次修改后为 0 次,首次自动告知也不创建标识。
本次在现有 TypeScript usage-statistics owner 中统一判断临时路径,覆盖所有发送通道及发送后的状态回写,避免复制一套 Python 判断。检测系统和显式声明的临时根目录,以及 HOME/USERPROFILE、状态路径、XDG/Codex 路由与已加载代码路径;解析符号链接和不存在文件的已有祖先,使用目录边界匹配。已开启或复制来的状态也不能绕过隔离。无法读取的路径交给现有 unavailable 边界处理。
普通持久安装的默认告知和发送行为保留。CWD 单独不作为抑制依据,因为正常的独立发送进程也使用临时工作目录。自建 scratch 目录若不在系统临时根下,需要声明 TMPDIR/TEMP/TMP 或在隔离环境持久关闭统计;不根据目录名称猜测测试身份。测试正向传输只有在显式
LOOPX_USAGE_PING=1且接收方为数字回环地址时才允许,仍服从 CI、关闭开关和告知策略。独立 connect-route smoke 在合并调用方环境后强制关闭统计。设置页增加中英文临时环境状态,隐藏无效的首次告知启用按钮;真实后端验证过开启仍受抑制、关闭可正确回读。开发文档与已有 self-repair 模式同时补齐独立入口、重建环境和自建临时根的契约。
验证(head
cddb47e88bb1319319a8290d36b28b55832fc29d,base98d7a9f361414a461897aca711a85dedd42e5611):todo-readmodel-boundary-smoke.py访问已不存在的loopx.status.open_todo_items。maintainability ratchet 另报告_admitted_interaction_next_cli_actions超限,并被现有 runner 标为 inherited advisory。已在上述 base 的独立干净 checkout 用同一解释器复现两项相同失败;本次未修改这些 owner、放宽检查或更改预算。其余选中的安装、升级、语义、投影、风险 profile 和公共边界检查通过。合并验证阻塞仍保留。视觉证据:最终 packaged Chat bundle 连接真实设置后端,工作区内容使用公共合成 fixture;不是已安装 Desktop 的证明。Before 使用 base 设置组件、相同的最终 temporary-blocked API 响应,展示之前“等待告知/启用”与现在状态的差异。桌面为中文 1440×1000,窄屏为英文 390×844;在包含长披露文本和其他能力的页面检查,窄屏状态可见且无横向溢出。
没有使用生产 collector、删除历史记录或推断历史安装标识的来源;本 PR 也未执行用户安装或发布。