# v0.2.1 修复与验收记录

> 此文件保留阶段性审计记录。后续网络/抓取策略及最终交付范围以 [v0.2.1 交付冻结说明](v0.2.1-delivery.md) 和 [网络策略](network-policy.md) 为准。

基线：`9c3d91f40b17f0a4fbab3bc6eb4271408bd3c8e1`（v0.2.0）。修复只在 `v0.2.1`，不合并 master、不发布 npm。原 `audit/jev-user-session-20260921` 分支已按要求删除。

## 原有问题逐项处理

| ID | 问题 | 修复位置与处理 |
| --- | --- | --- |
| U01 | 损坏 JSON 被当成不存在并覆盖 | `json-config.mjs`：只有 ENOENT 可回退；损坏/非对象配置明确拒绝。写入采用私有原子替换。 |
| U02 | Pi 覆盖用户同名扩展 | `agents/host-runtime.mjs`：写入前检查所有权；无标记文件（包括空文件）不覆盖。 |
| U03 | `ref=v1/v2` 缓存串页 | `search/fetch.js`：抓取使用完整 URL（仅忽略 fragment）；`results.js` 不再把 ref 视为通用跟踪参数，避免 Jev 证据池再合并版本。 |
| U04 | Codex root 开关落入 MCP 表 | `codex-native.mjs`：识别多行字符串/数组与根级赋值；管理块放在根级，保留原值恢复记录；按实际值显示状态；升级修复旧错位块。 |
| U05 | 精确短语的引号被删 | `search/fusion.js`：保留短语；短语内的 OR/site: 不再作为路由操作符。 |
| U06 | TUI 卸载遗漏项目级 Grok | `installer/index.mjs`：卸载同样询问 Grok scope。 |
| U07 | DSH 未安装却报告成功 | `agents/host-runtime.mjs`：缺失 CLI 作为失败传播，不报告虚构安装路径成功。 |
| U08 | --set 与 --engines 组合丢操作 | `installer/keys-wizard.mjs`：统一预检并一次性提交；冲突参数明确拒绝。 |
| U09 | 批量设置部分失败仍先写盘 | 同上：全部参数通过验证后一次原子 read-modify-write。 |
| U10 | npm 包缺公开 plugin 子命令依赖 | `package.json`：包含 build-plugin/sync-grok 两个运行入口，不把整个测试目录发布。 |
| U11 | dry-run 不校验或声称已保存/删除 | keys、Jev、X、native 配置路径共享合法性校验；预演只显示 would，不写盘。 |
| J01 | Vercel 与 TypeSafe 原生协议不兼容 | `jev/vercel.mjs`：按官方域名识别 Vercel，使用锁定版本的官方 AI SDK；Boolean/Noul、Choice confidence 和 usage 映射；TypeSafe 路径保留。 |
| J02 | answerCapable 总数恒为 0 | `search/adaptive/loop.mjs`：从与逐条结果相同的最终分类统计，不再读取不存在的字段。 |
| J03 | Retry-After 60 被截短至 4 秒 | `jev/client.mjs`：等待至少 Retry-After；超过本次任务预算则明确返回，不提前重试；等待可取消。 |
| J04 | 每阶段 attempts 错用累计次数 | `jev/client.mjs`：成功和失败均报告本次 ask 的增量，累计 HTTP 数单独保留。 |
| UP01 | 慢宿主串行挡住其他宿主刷新 | `upgrade/index.mjs`：独立资源以最多 3 条 lane 并行；共享 Pi/DSH 收据、相同配置/Grok 仍串行，避免回滚竞态。 |
| UP02 | 子孙进程/输出管道让超时不结束，测试调用真实 Grok | `process-tree.mjs`、`upgrade/process.mjs`、Pi 子代理、Grok 安装层：进程组/Windows taskkill、强杀、独立最终退出兜底；安装测试隔离 HOME，禁止隐式真实 Grok 探测。 |
| PI01 | 宿主 global fetch 与本包 dispatcher 跨版本混用 | `search/ipv4-fetch.js`：fetch/Agent/EnvHttpProxyAgent 均来自同一份 Undici；固定服务与 pinned 路径一致，不改宿主全局对象。 |

J01 是新增后端兼容性，不是原来承诺过却失效的功能。以上按原 18 项追踪，不把同一根因的每个调用点重复计数。

## 最终复核补充处理

1. **API Key 向导取消后仍留下修改**：把保存推迟到最后的引擎选择完成之后；仅写用户改变的键，保留无关配置。
2. **凭证随固定服务 307/308 转发**：带请求体、Authorization/Cookie/API-Key/订阅令牌的请求不得自动跟随跳转；Jev 显式手动处理并拒绝跳转。普通无凭据 HTML GET 保留重定向能力。
3. **搜索响应释放/大小边界**：非成功状态释放响应体；HTML/JSON 引擎响应设置 8 MB 上限，避免无界缓冲。
4. **错误误报与传播**：未知 fetch 异常分类为 transport_error，不再伪称 connect_refused；Jev 读取正文期间超时不伪装成格式错误；嵌入 TUI 中的安装失败也设置失败退出码；Grok 插件失败不冒充成功。
5. **Pi 重复注册和子进程缓冲**：已有 package 注册时移除自有旧 shim（用户文件保留）；子代理只保留最后的非空文本回复，并设置 4 MB JSONL 帧上限。
6. **Jev URL 输入隐私**：拒绝 URL 中的用户名、密码、查询参数与 fragment，非法地址错误不回显原始输入。

## 验证方法与已取得的结果

验证不只依赖原有脚本：修复后操作了真实 CLI、Clack TUI、打包后的公开子命令，以及真实本地 HTTP origin/CONNECT proxy。受控外部错误和 typed response 验证明确使用 fixture，不冒充真实公网调用。

- 本地原有及新增 `23` 组 npm 检查/回归入口全部通过（`test:v021` 新增 15 个 CLI/网络/进程边界场景；Jev loop 原有 49 项通过并补充 answerCapable 断言）。
- 真实 TUI：填写 Tavily Key、保留其余 Key，在最终引擎选择按 Ctrl+C，退出 0，未创建 keys.json。
- 真实 TUI：进入卸载选择 Grok，再选择 project scope，项目 MCP 配置已删除。
- 独立解包 `npm pack --ignore-scripts` 产物后，`plugin build`、`plugin sync-grok` 退出 0（运行依赖由已安装的锁定依赖提供）。
- 真实 loopback CONNECT 验证在宿主全局 fetch 被替换为必抛异常时，本包网络仍能通过配置的代理。
- 真实双服务 307 验证：携带 API-Key 或含 Key 的 POST 不会向第二服务发送请求。
- 实际 Node 挂起/继承输出管道场景：runCommand 有限结束，POSIX 进程组清理；Windows 对应路径纳入 CI，不用 Linux 结果代替 Windows 验收。
- Vercel 官方 SDK fixture 验证独立 Choice confidence（0.73，而非最大概率 0.8）和 usage；真实联网结果见下节，未使用外置协议转换器。

## GitHub 与真实联网验收（2026-09-21）

生产修复提交：`3b50768a0ac12281b3704d248b270c1991503ca4`。CI/联网记录提交：`2d33a81399725bc19521ebb78789f6dc7ce90efd`。两者生产源码相同，后者仅调整 CI 并增加临时会话记录器。会话记录器、临时验证工作流和密文传递文件在验收结束后从交付分支当前文件树删除；保留脱敏 evidence artifact。

- GitHub 全新环境 `npm ci --ignore-scripts`、`npm ls --all`、`test:v021`、`prepublishOnly` 均成功：run `35578306703`。
- GitHub Node 22 的 Ubuntu、Windows 全部 CI 步骤成功：run `35578701913`。不是用 Linux 结果代替 Windows。
- 真实用户入口联网记录：run `35578701922`，artifact `v021-online-user-evidence`（ID `10628876818`）；`sessions.jsonl` 包含完整工具返回，源码前后 status/diff 均为空。

| 实际操作 | 观察到的结果 |
| --- | --- |
| MCP fused_search，指定 4 个免费引擎 | 1.578 秒、5 条结果；Yahoo HTTP 500 明确作为警告，其他引擎继续。 |
| MCP adaptive_search：TaskGroup 加入版本 + AbortSignal.timeout 返回值 | 3.560 秒、1 轮、2/2 covered；模型覆盖判断 0.95/0.90；总 answerCapable=8，与逐条证据一致。发生 1 次 Jev 重试，最终成功。 |
| MCP adaptive_search：虚构 zqxv-2099 接口 | 12.953 秒、6 轮后 budget_rounds，insufficient、answerCapable=0；没有编造已覆盖。模型动作置信度 0.23 低于阈值时明确提示采用默认顺序。 |
| MCP fetch_page：Python 官方 TaskGroup focus | Jina 正常返回 853 词，3.098 秒。 |
| MCP 调用超时取消后继续使用 | 2.003 秒客户端超时后，search_stats 3 毫秒返回。 |
| 安装真实 Undici 8.10.2 为宿主全局 fetch，再调用分支内 Pi adapter fused_search | 1.466 秒返回搜索材料；Bing/Exa 成功，DDG 202 challenge、Yahoo 500 单独报告。 |
| 同一 Pi adapter adaptive_search：官方 Python list.sort 返回值 | 10.487 秒、3 轮、抓取 3 页后 covered；依据 Python 官方正文，answerCapable=1。模型覆盖判断 0.86，Jev 10 次 HTTP 尝试中 2 次重试。 |
| 同一 Pi adapter fetch_page：Node 官方 AbortSignal.timeout focus | Jina 正常返回 239 词，0.953 秒。 |
| 独立 Jev Choice 诊断对照 | choice=stop，provider confidence=0.99，合法映射；1 次 HTTP，服务报告 input/output tokens=344/31。这是诊断对照，不算额外用户场景。 |
| 不重启 MCP、清空 Jev 配置后再次调用 | 2 毫秒返回 not_configured，0 次网络请求，能力资源同步更新。 |

模型返回的覆盖概率不是经过独立校准的正确率。公网服务受时间、限流、反爬影响：本次 Yahoo 500、DDG 202 是真实上游响应，未隐瞒，也未归因于 Pi transport；免费引擎并非承诺每次全部成功。

## 明确边界

这不是“所有网络环境绝无故障”的保证。代理模式下 arbitrary-page 本地回退的 DNS pinning 限制保留，不为了“成功”绕开代理或 SSRF 检查。升级下载/替换包本身必须先验证，因此不是所有步骤都并行。Pi/DSH 共享状态的迁移仍串行。

本轮 Pi 证据是实际 adapter execute 在 Undici 8 宿主全局下发起真实网络请求，不是完整 Pi UI/LLM 会话；DSH 正向宿主启动、登录态 X、macOS、用户自己的代理客户端没有全量实机验收。多轮 Jev 已有真实成功案例，但不代表任意问题的决策质量都已验证。不能把安装文件存在或 CI 通过等同于全部真实宿主已验收。

## 官方协议依据

- Vercel Jev + AI SDK（Evaluation API、Boolean/Choice 与 providerMetadata confidence）：https://vercel.com/kb/guide/typesafe-jev-and-ai-sdk
- Node subprocess/process group 行为：https://nodejs.org/api/child_process.html
- Undici Fetch API：https://undici.nodejs.org/

新增 SDK 依赖锁定版本：`ai 7.0.107`、`@ai-sdk/gateway 4.0.87`。明文凭据不进入仓库、报告或测试夹具，生产只读取规范用户级 Jev 配置。
