Skip to content

feat: support Kimi Code Desktop on Windows - #56

Open
imxyanua wants to merge 45 commits into
EvoMap:mainfrom
imxyanua:codex/kimi-desktop-windows
Open

imxyanua wants to merge 45 commits into
EvoMap:mainfrom
imxyanua:codex/kimi-desktop-windows

Conversation

@imxyanua

@imxyanua imxyanua commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Extend the Windows Kimi Code CLI adapter to local Desktop sessions. Depends on #31. Desktop-only diff

Desktop client + Desktop process owner
  → shared native hook and turn evidence
  → isolated Kimi CLI ACP
  → private draft

The same installer, package and ACP runner serve both clients. This draft targets upstream main for CI. The Desktop-only comparison isolates the eight changed files while the CLI base is under review.

Evidence

  • The CLI base ignores the Desktop client. This patch admits the observed Desktop client identifier and process name, and the packed-hook fixture runs the same recall and verified-turn path for both clients.
  • Windows Node 22 and 26 each passed 635 tests with 11 platform skips, and all host packages built on both. Upstream test and pack run.
  • Earlier Windows acceptance used the native Desktop 1.2.1 app with fixture services, including process ownership and ACP cleanup. The split has not been rerun with the native UI or a live Desktop backend.

Merge Danger

Two-way. The package and its data stay shared. The added Desktop event and owner recognition is confined to Kimi. Keep the draft stacked on #31 until the CLI base has landed.

Retain the Kimi-only integration prepared for review. Use main for TOML vendoring and route-blocked candidate retention, including TTL. Preserve the existing PR head as the first parent.

async function pending(options = {}) {
const made = memoryPorts(options);
await promptSubmitted(made.ports, { sessionId: 'session', prompt: PROMPT, waitMs: 500 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

新增测试文件从函数体中段开始,导致测试套件无法解析

🔴 严重程度:高(P1)
新文件的首行直接是测试函数体内的语句,但没有对应的 test(..., async () => { 开头;随后新增的 }); 因缺少匹配的开放结构而成为非法语法。

Finding:finding_d5422277cb974ef9e7bdf0df

Copying the index advances its mtime, which can make Git trust a cached stat entry for a same-size edit. Use the source index timestamp rounded down before adding untracked entries. A deterministic regression checks both diff parts and the untouched source index.
@evomap-aiqa-bot

evomap-aiqa-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Sentinel 已审核此变更,并发现 1 个已核验问题。

另有 29 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。

审核覆盖提示: 14 个 hunk/条目缺少完整输入;它们不作为 bug 报告。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="eb45846d66c98b2cbffcb89d87a80a9293f178f9",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 eb45846d66c9

@evomap-aiqa-bot

Copy link
Copy Markdown

Sentinel 保留了 29 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
开发 agent:请 review 以下 advisory,并逐条给出“已验证无风险 / 已修复 / 转为后续事项”的结论;不要只做整体确认。

  • [P1] 移除冲突回合后仍永久保留旧路由阻塞 — withoutWorkTurn 已得到移除后的 turns 和 model,却对移除前的 range 调用 rangeRouteProblem。��...(truncated) · lib/distill/range.js · advisory_940e2b66d6f0db2e205c4555
  • [P1] 标签发布不执行也不等待 Windows Kimi 发布门禁 — 新增断言明确要求 windows-kimi 仅在 pull_request 或 workflow_dispatch 事件运行,排除了标签的 ...(truncated) · test/release.test.js · advisory_d3aa5f85157c38deaa895b39
  • [P2] 目录换链竞态可绕过 native facts 的根目录限制 — confined() 逐段拒绝符号链接并执行 realpathSync() 后即返回字符串路径;后续 statSync/openSync...(truncated) · lib/runtime/native-facts.js · advisory_d5472824ab6ae80b22cd92ba
  • [P3] 收据替换失败回归测试没有真正注入 EPERM — preload 仅在 to === process.env.FIXTURE_RECEIPT 且第二次调用 renameSync 时抛出 EPERM,但测试没有�...(truncated) · test/runtime/acp-receipt.test.js · advisory_ac285d4891fe952f5e2cf7c9
  • [P3] 旧 native 会话结束后 correctedTurn 变为 NaN — endedSession() 先从 EMPTY_SESSION 得到 correctedTurn: 0,但 native 分支又用旧 session 的 session.corr...(truncated) · ``lib/session/state.js`` · advisory_c576a8f95a538e81e376bdc2`
  • [P3] 启动标记读取了不存在的顶层字段 — 解码器将标记写入 nativeFacts.bind.mark,但 turnStart 读取 nativeFacts.mark。因此即使成功解码�...(truncated) · hosts/kimi/evidence.js · advisory_f2b716f5dcbd25e0c86642b0
  • [P3] 标签发布不会等待 Windows Kimi 验证 — 当前 PR 新增的 windows-kimi job 只在 pull_request 或 workflow_dispatch 运行,而标签发布路径不��...(truncated) · .github/workflows/release.yml · advisory_005e9a5cb5c81bbf609e676d
  • [P3] 空的初始 mark 永久阻断 native 回合终态对账 — capturePrompt 在首次 facts 不是 status: 'ok' 时仍创建 native 回合,但把 native.mark 写成 null。...(truncated) · lib/app/native-turn.js · advisory_2f5ff95f3519de09c8e1824e
  • [P3] guardian 释放超时后没有强制终止兜底 — release() 只用 within(closed, 2000) 等待 guardian;超时后返回 false,调用方仅改写为 ACP_CLEANUP...(truncated) · lib/runtime/acp-model.js·advisory_0c9c6dfde63b418b74cfc18f`
  • [P3] 回滚删除失败会保留未提交的新包并跳过后续恢复 — 激活后若 updateState(registryFile, ...) 失败,代码先删除新 target,再把 backup 恢复回来。若 ...(truncated) · scripts/install-kimi.mjs · advisory_52ae6f8c65066eb0f8a3b779
  • [P3] 恢复扫描遗漏旧 epoch 的 provisional work — activateWorkTurn 已支持通过 session.sessionEpoch !== expected.sessionEpoch 识别并删除失效 work,但恢�...(truncated) · lib/app/native-turn.js · advisory_a0dae657950e3ac5e1d021cd
  • [P3] 校正状态更新失败后仍会继续写入旧会话候选数据 — correctedTurnOf 先通过 sessions.update 检查 current.sessionEpoch === session.sessionEpoch,但没有记录��...(truncated) · lib/app/prompt.js · advisory_683ee8813db49b60d9fcb949
  • [P3] 省略 effort 时思考模型的默认配置会被错误拒绝 — 对支持 thinking 的模型,缺省 hint.effort 被设为 null;后续校验只接受 'off' 或 support_effort...(truncated) · hosts/kimi/model.js·advisory_47dd0fba3ecd277a330786e0`
  • [P3] 远程明文 HTTP BYOK 端点会暴露 API 凭据 — selectRoute 允许任意主机使用 http:,没有将明文协议限制为 loopback;prepareRoute 随后原样��...(truncated) · hosts/kimi/model.js · advisory_6fd1020a4c81ca40f1461936
  • [P3] ACP fixture 的配置解析器与序列化器格式不一致 — 新增 declaration 明确使用 smol-toml 作为 parseConfig,但使用 JSON.stringify 作为 serializeConfig��...(truncated) · test/fixtures/acp/declaration.mjs · advisory_39a1e475a3fd2909eb8ca8cd
  • [P3] 任务身份测试复用了已被改成拒绝解码的 fixture — 测试先将 f.declaration.decode 替换为始终返回 { status: 'unsupported' },完成第一条断言后没有��...(truncated) · test/runtime/native-facts.test.js · advisory_f479ca96a377cb9b3b584257
  • [P3] native 进程结束后 guardian 可能永久等待 release,导致 scratch 和 guardian 泄漏 — native 子进程关闭后,guardian 在 await released 处无限等待。release 只会由 IPC 消息、disconnect...(truncated) · ``lib/runtime/process/acp-child.js`` · advisory_2149af3a4db839b6a49b6f2c`
  • [P3] owner 启动标记的生产、读取和禁用清理契约不一致 — Kimi 客户端侧读取不存在的顶层启动字段,而 session-start 侧在禁用 owner 跟踪时又不清除旧 s...(truncated) · ``hosts/kimi/profile.js`` · advisory_e2d7db5f3193fb0b56b53497`
  • [P3] profile scope 未参与 native 身份绑定校验 — 新增的 NativeFacts.scope 只被返回为观察对象的元数据;readFacts 调用 ports.native.read(payload, ....(truncated) · ``lib/app/native-turn.js`` · advisory_75fe80d0281a8b8cc1c31b0c`
  • [P3] reset/clear 与异步完成回调之间缺少统一代际隔离 — reset/clear 防护问题分别出现在模型生命周期切片和 native 进程切片,而且两边给出了完全��...(truncated) · lib/runtime/acp-model.js · advisory_0ca2e5de9ce664dbfcbc6ed4

另有 9 条候选未在评论中展开;可通过下方 Sentinel PR review context 查询全部条目。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="eb45846d66c98b2cbffcb89d87a80a9293f178f9",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 eb45846d66c9

Comment thread lib/app/native-turn.js Outdated
const pending = rangeOf(await candidates.read(), at.sessionId)?.pendingNativeCheck;
const attached = await sessions.update(at.sessionId, stored => {
if (!stored.open || stored.turn !== turn || stored.sessionEpoch !== sessionEpoch || stored.pid !== owner.current()) return undefined;
return { ...stored, native: { turn, mark: facts?.status === 'ok' ? facts.mark : null, turnId: null, model,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

首次读取失败会永久阻断后续有效终态对账

🔴 严重程度:高(P1)
首次 facts 不是 status: 'ok' 时,代码仍建立 native turn,但将 native.mark 保存为 null。后续读取即使成功,身份校验仍要求 facts.mark.fileId === native.mark?.fileId;右侧恒为 undefined,正常的非空 fileId 必然被拒绝。当前状态机没有用后续 facts 补写初始 mark 的路径。

Finding:finding_63cfbfff4315daad2f4ff3ea

Retain admitted unresolved native turns across the next prompt. Finalize from their original identity and evidence, without consuming the newer turn notes or replacing its model route. Keep pending entries recoverable until reports and candidate work have settled.
Leave a turn to native recovery when its snapshot overlaps the next prompt. Keep the newer range intact when an older turn falls outside the retained window.
A worker can exit before fork, leaving an owner marker without a native child receipt. Give the guardian and orphan recovery mutually exclusive claims on the startup marker so recovery can remove a prelaunch directory while keeping claimed scratch without closure proof.
An older dist/kimi can outlive a newer managed installation. Compare the staged and currently installed versions under the activation lock before replacing the package. Keep explicit version requests available for intentional source builds.
Keep the Kimi native monitor wiring and the ledger delivery changes from upstream PR EvoMap#58.
Bring over late native terminal handling, ACP prelaunch scratch recovery, and the installer downgrade guard while preserving the Desktop adapter and acceptance fixtures.
@evomap-aiqa-bot

evomap-aiqa-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Sentinel 已审核此变更,未发现已核验问题,但发现需要人工确认的风险。

另有 26 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。

审核覆盖提示: 16 个 hunk/条目缺少完整输入;它们不作为 bug 报告。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="bf5f6c586d53c82a60188a4fbe186e612b53f965",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 bf5f6c586d53

@evomap-aiqa-bot

Copy link
Copy Markdown

Sentinel 保留了 26 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
开发 agent:请 review 以下 advisory,并逐条给出“已验证无风险 / 已修复 / 转为后续事项”的结论;不要只做整体确认。

  • [P1] 标签发布不执行也不等待 Windows Kimi 验证 — 新增契约明确要求 windows-kimi 仅在 pull_request 或 workflow_dispatch 事件运行,排除了标签对�...(truncated) · test/release.test.js · advisory_5590124b31e72dd050e3ffc9
  • [P2] 目录换链竞态可绕过 native facts 的根目录限制 — confined() 校验各级目录及 realpath 后返回字符串路径,随后 jsonOf()/recordsOf() 再通过该路...(truncated) · lib/runtime/native-facts.js · advisory_5833c7855dbe4d7ead78db50
  • [P2] 未完成的 deferred native turn 会被容量截断并永久失去终态 — deferNativeTurn() 无条件对 deferredNativeTurns 执行 slice(-MAX_TURN_IDS),但数组中的条目仍在等待...(truncated) · lib/session/state.js · advisory_be9bbb4bcaa00e0de70af521
  • [P3] 测试先用 Git 的 stat 缓存掩盖了同尺寸文件修改 — 测试显式设置 core.checkStat=minimal 和 core.trustctime=false,然后把工作区文件恢复到与索引相�...(truncated) · test/runtime/project.test.js · advisory_79d489704f8c9f6af860e439
  • [P3] 私有凭据环境隔离测试没有经过被测 runner — 该测试标题声称验证 modelRunnerOf(...).complete() 创建的私有凭据环境不会执行宿主 Node preload��...(truncated) · test/runtime/acp-model.test.js · advisory_8c09fd5d93312a58c2d4feb6
  • [P3] TurnStarted 永远无法输出 native turn 标记 — turnStart 读取的是 nativeFacts.mark,但 decodeNativeFacts 返回的对象没有顶层 mark 字段;它只...(truncated) · hosts/kimi/evidence.js · advisory_44af00b019f5dc51936c61a5
  • [P3] 移除冲突回合后仍保留旧路由阻塞,范围会被错误停放至 TTL 到期 — withoutWorkTurn() 在移除回合后仍对旧的 range 调用 rangeRouteProblem(range)。该函数首先直接返�...(truncated) · lib/distill/range.js · advisory_a405cabb41d5b3c641628cab
  • [P3] 超出输出上限后仍可无限累积 stdout 缓冲 — stdout 回调先将每个 chunk 解码并拼接到 buffer,随后才检查累计 bytes 是否超过 OUTPUT_MAX。...(truncated) · lib/runtime/acp-model.js · advisory_647d2bbae38fc2e2d3f9127b
  • [P3] 首次 native facts 读取失败会永久阻断终态对账 — capturePrompt() 在首次读取失败时仍创建 native turn,但将 native.mark 保存为 null。后续 reconc...(truncated) · ``lib/app/native-turn.js`` · advisory_5eb12ce13fc51d35e4de841a`
  • [P3] 收据替换失败回归测试未实际注入 EPERM — preload 只有在目标路径等于 process.env.FIXTURE_RECEIPT 且第二次替换时才抛出 EPERM,但当前测�...(truncated) · test/runtime/acp-receipt.test.js · advisory_bbfc27755b2e9fe61df84718
  • [P3] trackOwner: false 不会清除旧的 startedUnder — trackOwner: false 时条件展开不会写入新的 startedUnder,但对象展开仍保留 sessionOf(stored) 中�...(truncated) · lib/app/session-start.js · advisory_370530156c50102b51d5fb50
  • [P3] Windows 作业的固定临时文件不会清理,导致同一目录无法重试或启动后续任��...(truncated) — 函数使用固定路径 .evolver-job.ps1、.evolver-job.json 和 .evolver-job-stop,全部通过 { flag: 'wx' }...(truncated) · ``lib/runtime/process/windows-job.js`` · advisory_3c5ed4af741f64cc79a85436`
  • [P3] status 未持有安装锁,会读取到包与注册表的中间状态 — 激活过程在安装锁内依次移动旧包、放入新包并更新 installed.json,但 status 在锁外先读注...(truncated) · scripts/install-kimi.mjs · advisory_2c7f111baefc67c1f43df489
  • [P3] session epoch 闸门失败后仍继续写入旧 correction 状态 — sessions.update() 在发现当前 session 的 sessionEpoch 或 turn 已变化时返回 undefined,表示不应�...(truncated) · lib/app/prompt.js · advisory_9a9d35b6a9309d6283631a4a
  • [P3] 旧版 native 会话会把 correction 高水位写成 NaN — endedSession 虽先展开带有 correctedTurn: 0 的 EMPTY_SESSION,但 native/deferred-native 分支又用旧对...(truncated) · lib/session/state.js · advisory_dbbfd1fe3a7db78e3ccc810f
  • [P3] 旧终态清理可能删除并发写入的 deferred 候选 — dropWorkTurn 只验证候选中仍存在相同 turn + sessionEpoch,没有验证该候选是否仍是当前异步��...(truncated) · lib/app/turn-end.js · advisory_cae11b8f47e000de47b2d0e5
  • [P3] 空的初始 mark 会导致延迟回合对账崩溃 — capturePrompt() 在 facts?.status !== 'ok' 时明确保存 mark: null;随后 reconcileDeferredTurn() 在完成...(truncated) · lib/app/native-turn.js · advisory_0990e72e38d40abfd100a6b8
  • [P3] 缺省 thinking effort 导致已配置的 Kimi 路由无法解析 — selectRoute 在未提供 hint.effort 时,对支持 thinking 的模型生成 effort = null,既没有采用模��...(truncated) · hosts/kimi/model.js · advisory_a4b08e1266be1830a3d2a431
  • [P3] Windows Job 停止失败时只终止 helper,可能遗留 native 进程树 — Windows 路径中 job.stop() 抛错后,fallback 仅执行 child.kill('SIGKILL')。代码通过 helperPid: child.p...(truncated) · lib/runtime/process/acp-child.js·advisory_da923f1f620b9779be8aef89`
  • [P3] native turn 入场延迟超过 30 秒后监控永久退出 — 监控循环在 !result?.native?.turnId && now() - start >= MISSING_MS 时直接 return,没有 abort、重试、��...(truncated) · lib/runtime/native-monitor.js · advisory_c895438fe968d8accebb9b8d

另有 6 条候选未在评论中展开;可通过下方 Sentinel PR review context 查询全部条目。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="bf5f6c586d53c82a60188a4fbe186e612b53f965",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 bf5f6c586d53

@imxyanua
imxyanua marked this pull request as ready for review November 8, 2026 05:50
Bind only a fresh native TurnStarted matching the submitted prompt, owner, and file anchor when available. Keep the route binding captured at submit rather than selecting current credentials for an older turn.
Reevaluate the captured binding of the remaining work. Omit the old worktree diff for the repaired range and retain only runtime blocks tied to the same binding.
@evomap-aiqa-bot

evomap-aiqa-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Sentinel 已审核此变更,并发现 2 个已核验问题。

无法定位到 diff 的已核验问题

所有权收据写入失败会触发 TDZ 异常并遗留脱离 guardian 的 native 子进程

🔴 严重程度:高(P1)
remember() 在 writeFileSync() 失败后立即执行 void terminate(),但 terminate 是后面才声明的 const。Unix 路径中 remember(child.pid) 在 terminate 初始化前同步执行,因此会抛出 `ReferenceError: Cannot access 'termin...(truncated)

Finding:finding_bbfd77c04794f737e15743fc · 文件:lib/runtime/process/acp-child.js · 详情:/api/v1/aiqa/findings/finding_bbfd77c04794f737e15743fc

当前为 advisory 仓库:这些 item 会逐条保留,但不阻塞合并。

另有 32 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。

审核覆盖提示: 16 个 hunk/条目缺少完整输入;它们不作为 bug 报告。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="b308ffac97a4d20d17c8e297dfaa80c5478980b8",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 b308ffac97a4

@evomap-aiqa-bot

Copy link
Copy Markdown

Sentinel 保留了 32 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
开发 agent:请 review 以下 advisory,并逐条给出“已验证无风险 / 已修复 / 转为后续事项”的结论;不要只做整体确认。

  • [P1] 补齐缺失路由后仍保留 route_not_captured 阻塞 — withWorkTurn 和 withoutWorkTurn 都先对旧 range 调用 rangeRouteProblem();该函数优先返回旧的 ra...(truncated) · lib/distill/range.js·advisory_e9619b59aa18ad0b87059678`
  • [P2] 目录换链竞态可绕过 native facts 根目录约束 — confined() 验证路径各级均非符号链接并执行 realpathSync(),但只返回字符串路径;jsonOf() �...(truncated) · lib/runtime/native-facts.js · advisory_6bb2e1380f9b3bace018cf98
  • [P2] 容量截断会使延迟回合的资产被错误归因到后续回合 — deferNativeTurn() 使用 slice(-MAX_TURN_IDS) 无条件删除最旧的未完成回合。删除后,finishDeferredN...(truncated) · lib/session/state.js·advisory_d8455cb9ec95c21fc62a6f77`
  • [P2] 启动标记读取了 decoder 未输出的字段 — decoder 将起始偏移量输出为 nativeFacts.bind.mark,但 turnStart 读取的是不存在的 nativeFacts.mark...(truncated) · hosts/kimi/evidence.js·advisory_5a96e633d6cf5ea66a3123df`
  • [P3] preload 隔离测试绕过了被测 runner — 该测试直接使用 spawn(process.execPath, ['--import', poisonPreload, owner.mjs, ...]) 启动 fixture,并没有�...(truncated) · test/runtime/acp-model.test.js · advisory_fffc1664903a1e046604b60a
  • [P3] 任务 ID 不匹配测试被解码器拒绝断言掩盖 — 测试先将 f.declaration.decode 替换为始终返回 { status: 'unsupported' },随后没有恢复该函数就��...(truncated) · test/runtime/native-facts.test.js · advisory_3620e4e4c88bc25beb744f92
  • [P3] 收据替换失败回归测试没有真正触发 EPERM — preload 只有在 to === process.env.FIXTURE_RECEIPT 且第二次调用 renameSync 时才抛出 EPERM,但当前�...(truncated) · test/runtime/acp-receipt.test.js · advisory_f1a6915f70f2c946c1b219ab
  • [P3] 新增 Git 快照测试会被 Git stat 缓存提前判定为无修改 — 测试显式设置 core.checkStat=minimal、core.trustctime=false,把工作区文件和 .git/index 设置为相�...(truncated) · test/runtime/project.test.js · advisory_5fd5998c2abd674fa4634924
  • [P3] 旧 native 会话缺少 correctedTurn 时会被恢复为 undefined — endedSession() 先展开含 correctedTurn: 0 的 EMPTY_SESSION,但 native/deferred 分支随后无条件写入 ...(truncated) · ``lib/session/state.js`` · advisory_af1da435b0120c8900abf192`
  • [P3] profile 校验会重复报告同一错误 — 本次修改新增了 turnEnd.statusRecord 和 commands.background 的校验,但这两项校验在同一个函数�...(truncated) · lib/agent/profile.js · advisory_83e303ffe1d8723bccc0af35
  • [P3] session 过期后仍继续写入旧 correction 状态 — correctedTurnOf() 通过 ports.sessions.update() 检查 current.sessionEpoch === session.sessionEpoch 且 current...(truncated) · ``lib/app/prompt.js`` · advisory_0401c2b689e2eafb96e1aa4d`
  • [P3] 无阻塞结算会保留旧的运行时阻塞 — 新逻辑在没有新的 blocked 原因时,将已有的 previousBlock 原样重新写回结果。运行时阻塞��...(truncated) · lib/distill/range.js · advisory_c29995bc1ab52a113fd66fef
  • [P3] 标签发布未纳入 Windows Kimi 发布门禁 — 当前 PR 新增的契约明确表明 windows-kimi 仅在 pull_request 或 workflow_dispatch 时运行,而标签...(truncated) · .github/workflows/release.yml · advisory_25be9f09574c6914eb5a0470
  • [P3] BYOK 路由允许向任意明文 HTTP 端点发送 API Key — selectRoute() 接受任意主机的 http: URL;随后 prepareRoute() 将 API Key 环境变量和该端点写入��...(truncated) · hosts/kimi/model.js · advisory_b9640705052ca4d5766c8acc
  • [P3] Kimi 会话 ID 未使用工作区作用域,可能发生跨会话状态串写 — hosts/kimi/paths.js 新增了带 nativeScope 的 sessionIdOf(),用于生成 [nativeScope, session_id] 的隔��...(truncated) · hosts/kimi/profile.js · advisory_31879cb3ed647fcfd53dfe40
  • [P3] stdin 队列瞬时满载会误杀正常 Windows 任务 — Ingress() 使用容量为 4 的 BlockingCollection,但写入时调用的是非阻塞的 TryAdd()。当 native ��...(truncated) · lib/runtime/process/windows-job.js · advisory_3671f2e1cdc8c91f3560f384
  • [P3] 会话失效与候选激活之间存在 TOCTOU 竞态 — activateWorkTurn() 在候选更新前读取一次 session,并据此计算 invalidated、committed;随后异步...(truncated) · lib/app/native-turn.js · advisory_83c7e863640b45cfcd25efda
  • [P3] 单个会话恢复异常会阻断后续全部会话 — 恢复循环直接依次 await reconcileNativeTurn()、releasePendingCheck() 和 activateWorkTurn(),没有按 se...(truncated) · lib/app/native-turn.js · advisory_1c7461b4f307930237e8b2d0
  • [P3] 同一工作目录无法启动第二个 Windows Job — 启动时以独占创建方式写入固定名称的 .evolver-job.ps1 和 .evolver-job.json,但 helper 和 Node 侧...(truncated) · lib/runtime/process/windows-job.js · advisory_3675f2a1a9aa5e0747112109
  • [P3] 新 epoch 覆盖范围 epoch 后遗忘旧的待完成 native 检查 — withWorkTurn 对新的 native turn 写入 context.sessionEpoch,却保留旧的 pendingNativeCheck。isProvision...(truncated) · lib/distill/range.js·advisory_30bea7112567672866515f39`

另有 12 条候选未在评论中展开;可通过下方 Sentinel PR review context 查询全部条目。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="b308ffac97a4d20d17c8e297dfaa80c5478980b8",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 b308ffac97a4

Comment thread lib/runtime/process/acp-child.js Outdated
process.stdin.on('data', chunk => { if (!child.stdin.destroyed) child.stdin.write(chunk); });
process.stdin.on('end', endInput);
process.on('message', message => {
if (message?.type === 'stop') { failure ??= 'cancelled'; void terminate(); }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

完成后的迟到取消仍会终止陈旧 PID 并改写结果

🟠 严重程度:中(P2)
close 已将 result 设置为终态,但 stop、SIGTERM 和 owner-watch 仍无条件调用 terminate();非 Windows 路径随后对已退出子进程保存的 child.pid 执行 process.kill(-pid, ...)。stop 还会在已经发送成功 closed 消息后把 failure 改为 cancelled,使 guardian 最终以失败码退出。若该 PID/进程组号在等待 release 期间被复用,还会向无关进程组发送 SIGTERM/SIGKILL。

Finding:finding_5f9ae6f56a7ec3dc1d397714

@evomap-aiqa-bot

evomap-aiqa-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Sentinel 已审核此变更,并发现 2 个已核验问题。

无法定位到 diff 的已核验问题

未完成的 deferred native turn 会被容量截断并永久丢失终态

🟠 严重程度:中(P2)
deferNativeTurn() 将仍等待 native 终态的回合放入 deferredNativeTurns,但无条件执行 slice(-MAX_TURN_IDS)。当延迟 native 回合数量超过容量时,最旧回合会被删除。之后 finishDeferredNativeTurn() 通过 `hasDeferredT...(truncated)

Finding:finding_93897eb57e5c1b2e29182c78 · 文件:lib/session/state.js · 详情:/api/v1/aiqa/findings/finding_93897eb57e5c1b2e29182c78

TurnStarted 无法读取 decoder 生成的回合启动标记

🟠 严重程度:中(P2)
decodeNativeFacts() 在 hosts/kimi/transcript.js 中将启动偏移量写入 bind.mark:bind: { ..., mark: prompt.$offset ?? null };但 kimiEvidence.turnStart() 读取的是 context.nativeFacts?.mark,而不是 context.nativeFacts?.bind?.mark...(truncated)

Finding:finding_73ae8c81b1ce5e5059d6a209 · 文件:hosts/kimi/evidence.js · 详情:/api/v1/aiqa/findings/finding_73ae8c81b1ce5e5059d6a209

当前为 advisory 仓库:这些 item 会逐条保留,但不阻塞合并。

另有 35 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。

审核覆盖提示: 16 个 hunk/条目缺少完整输入;它们不作为 bug 报告。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="46c14ecdf9e15356fdbcfc2907dfab65cee31038",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 46c14ecdf9e1

@evomap-aiqa-bot

Copy link
Copy Markdown

Sentinel 保留了 35 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
开发 agent:请 review 以下 advisory,并逐条给出“已验证无风险 / 已修复 / 转为后续事项”的结论;不要只做整体确认。

  • [P1] 标签发布不执行也不等待 Windows Kimi 验证 — 新增契约明确要求 windows-kimi 仅在 pull_request 或 workflow_dispatch 时运行,排除了正式标签�...(truncated) · test/release.test.js · advisory_256331e1417721a15fe8c702
  • [P2] 延迟 native 回合在 owner 消失时未被终态化 — observedNativeTurn(session, at.turn) 可以找到非当前的 deferred 回合,但 owner 消失分支仅在 session....(truncated) · lib/runtime/native-monitor.js·advisory_648017cdcde2352b42cf555f`
  • [P2] trackOwner=false 未清除旧 owner,重用会话可能被误判为 orphan — trackOwner=false 只是不写入新 owner,但 { ...sessionOf(stored) } 会保留持久化会话中的旧 startedU...(truncated) · lib/app/session-start.js·advisory_9f46e66334c4899b1b4349fb`
  • [P3] preload 隔离测试没有经过实际 runner,无法验证私有凭据环境的生命周期边界 — 新增测试直接通过 spawn(process.execPath, ['--import', poisonPreload, owner.mjs, ...]) 启动 fixture。--impo...(truncated) · ``test/runtime/acp-model.test.js`` · advisory_f69604f0cb90935caa65b3bc`
  • [P3] Windows job 的固定临时文件会阻塞后续启动并继承旧的取消状态 — 每次启动都使用同一组固定路径 .evolver-job.ps1、.evolver-job.json 和 .evolver-job-stop,并通过 ...(truncated) · lib/runtime/process/windows-job.js · advisory_02fcebd53374ecdf6cde1824
  • [P3] native facts 路径检查存在目录换链竞态 — confined() 先通过 lstatSync、realpathSync 检查目录和文件是否位于 root 内,但只返回字符串...(truncated) · lib/runtime/native-facts.js · advisory_50d1f73ab8e4b91b59c36a98
  • [P3] 旧 native 会话的 correctedTurn 会被覆盖为 undefined — endedSession() 先展开包含 correctedTurn: 0 的 EMPTY_SESSION,但对存在 native 或 deferredNativeTurns...(truncated) · ``lib/session/state.js`` · advisory_44235ba5acc6123d7882a054`
  • [P3] 标签发布跳过 Windows Kimi 验证 — 新增的 windows-kimi 仅允许 pull_request 和 workflow_dispatch,明确排除了标签发布使用的 push ...(truncated) · .github/workflows/release.yml · advisory_e9c42a81a8e002666dc164a7
  • [P3] 重判补齐模型绑定后仍保留旧路由阻塞 — withWorkTurn() 已构造出包含新 binding 的 next,但先调用 rangeRouteProblem(range);该函数优先返...(truncated) · lib/distill/range.js · advisory_95aa32e71e53290e79fa2635
  • [P3] guardian 释放超时后仍保持引用,可能阻止宿主退出 — release() 等待 guardian 退出最多 2 秒;超时后只返回失败,没有终止、断开或 unref() 仍存活...(truncated) · lib/runtime/acp-model.js · advisory_435819aa7112b466ef5c5874
  • [P3] 回退到 Windows PowerShell 时,编译阶段无法取消且可能遗留编译器进程 — Windows Job 及原子 JOB_LIST 只在 C# 编译完成、进入 Run() 后创建;但 Windows PowerShell 的 Add-Typ...(truncated) · lib/runtime/process/windows-job.js·advisory_c6ac9ecb6fea6a912abddc3b`
  • [P3] 多个完成测试把异步 capture() Promise 直接传给 complete() — runner.capture() 在本文件的首个测试中明确通过 await 获取 route snapshot,但当前测试使用 con...(truncated) · ``test/runtime/acp-model.test.js`` · advisory_4092b08c53b1c31a5a4bbaaa`
  • [P3] 收据替换失败回归测试未实际注入 EPERM — preload 只有在 to === process.env.FIXTURE_RECEIPT 且第二次重命名时才抛出 EPERM,但测试没有设置...(truncated) · test/runtime/acp-receipt.test.js · advisory_9349650f8a69a70624b81121
  • [P3] nativeFacts 的路径校验与读取之间存在换链竞态 — nativeFacts 先通过 lstatSync、realpathSync 和 isSymbolicLink() 检查目录及文件,之后又使用原��...(truncated) · lib/runtime/acp-model.js · advisory_aad939526aaad664510d3a61
  • [P3] 延迟激活可在会话纠正或换代后提交过期工作 — activateWorkTurn() 先从 session store 读取 session 并计算 invalidated,随后在独立的 candidates store...(truncated) · lib/app/native-turn.js · advisory_6a5aca71beee859a378b7585
  • [P3] 成功结算时会保留旧的 blocked 状态 — 本次修改将旧的 blocked 保存为 previousBlock,并在 reason === undefined 时令 block = previousBlock...(truncated) · lib/distill/range.js · advisory_9d806dfd10f401694be9ce7e
  • [P3] 新 epoch 会解除旧 native 检查的完成屏障 — PR 允许 native range 跨 sessionEpoch 累积,但将 range 的顶层 sessionEpoch 更新为最新 epoch。isProv...(truncated) · ``lib/distill/range.js`` · advisory_2b217d190877af1f2cd842ea`
  • [P3] 更新期间已注册的插件路径会短暂消失 — 更新已有插件时,代码先将当前 target 重命名为 backup,随后才把 prepared 重命名为 target...(truncated) · scripts/install-kimi.mjs·advisory_ce514ad56ebe7d09e4ba8fe5`
  • [P3] 重复 prompt 身份会截断回合记录 — unique 使用 turnId:promptId 去重并保留最后一条 prompt,却不验证重复记录内容是否一致;随�...(truncated) · hosts/kimi/transcript.js · advisory_d69052cbe4512bed4dd07f2e
  • [P3] 提交起始 HEAD 的 epoch 防护读取了未解包状态 — 新增的过期写入防护直接读取 stored.sessionEpoch,但同文件其他 sessions.update() 回调均先通��...(truncated) · lib/app/prompt.js · advisory_937d86f3f12614957bb20278

另有 15 条候选未在评论中展开;可通过下方 Sentinel PR review context 查询全部条目。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="46c14ecdf9e15356fdbcfc2907dfab65cee31038",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 46c14ecdf9e1

@forrestlinfeng forrestlinfeng left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the Desktop delta over #31 (8 files, +42/-28): the kimi_code_desktop client, the Kimi Code.exe owner pattern, docs and tests — clean and Kimi-only, no changes needed. It's blocked only on #31, which still needs the rework described in #31 (latest review). Once the reworked CLI PR lands, re-apply these 8 files on top and this can merge.

@evomap-aiqa-bot

evomap-aiqa-bot Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Sentinel 已审核此变更,并发现 1 个已核验问题。

另有 26 个需要人工确认的风险;黄色 advisory 不阻塞合并,建议开发 agent review advisory 评论并逐条确认。

审核覆盖提示: 16 个 hunk/条目缺少完整输入;它们不作为 bug 报告。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="8e0f03565689605b0cb24c3bb4ba33cbd04e6ff1",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 8e0f03565689

@evomap-aiqa-bot

Copy link
Copy Markdown

Sentinel 保留了 26 个尚未确认的审核候选。这些黄色条目不阻塞合并;红色 P0/P1 与其他独立硬门禁不受影响。 单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
开发 agent:请 review 以下 advisory,并逐条给出“已验证无风险 / 已修复 / 转为后续事项”的结论;不要只做整体确认。

  • [P1] 同一测试中保留拒绝 decoder,导致断言状态错误 — 测试先将 f.declaration.decode 覆盖为恒返回 { status: 'unsupported' },随后只设置 taskIds 与 task...(truncated) · test/runtime/native-facts.test.js·advisory_07e2f3d7e5d2bc5d3045a923`
  • [P1] 标签发布不运行也不等待 Windows Kimi 验证 — 新增断言明确要求 windows-kimi 只在 pull_request 或 workflow_dispatch 时运行,排除了正式标签�...(truncated) · test/release.test.js · advisory_d596f7a14328d92f7e22957b
  • [P1] 迟到的 native 写入会删除并发生成的修正候选 — rememberWorkTurn() 写入后会重新读取 session;若并发 correction 已把 correctedTurn 推进到当前回��...(truncated) · lib/app/turn-end.js · advisory_8ba569e1b8d6439443af8c9d
  • [P2] 显式 SessionStart 会继承旧进程的 owner 标记 — trackOwner=false 时只是不写入当前 owner;{ ...sessionOf(stored) } 仍会保留旧的 startedUnder。随��...(truncated) · lib/app/session-start.js · advisory_90cbe3ba3309b5c341753ed7
  • [P2] 未完成的 deferred native 回合会被容量截断并失去正常终态路径 — deferNativeTurn() 对仍在等待终态的 deferredNativeTurns 无条件执行 slice(-MAX_TURN_IDS)。最旧条目...(truncated) · lib/session/state.js · advisory_d18d9572f99c5d02da01fb5c
  • [P2] 迟到终态只被补捕获,终态对应的答案和工具结果仍被截断 — boundTurn 分支会在下一条 prompt 之后继续查找旧回合的 turn.ended,但 turn 仍被截断在下一�...(truncated) · hosts/kimi/transcript.js · advisory_ec4b4fb7bcc649625ef45ea3
  • [P2] 纠正流程部分失败后会持久化半完成状态 — 新流程依次写入 session 的 corrected 状态、draft correction 标记和 candidate range,三个独立 await �...(truncated) · lib/app/prompt.js · advisory_39f4f29b3b1f9b3b5535ce3a
  • [P3] preload 隔离测试绕过了实际 runner — 测试显式把 poison preload 传给被启动的 fixture,却没有经过实际的 ACP/model runner 创建私有凭据...(truncated) · test/runtime/acp-model.test.js · advisory_390ba5ac535db58ac51b9cc1
  • [P3] receipt 替换失败测试未注入 FIXTURE_RECEIPT — preload 只有在 to === process.env.FIXTURE_RECEIPT 且第二次匹配时才抛出 EPERM,但测试中没有设置...(truncated) · test/runtime/acp-receipt.test.js · advisory_6cfd7c8b2039619c5de80de2
  • [P3] 固定的桥接文件未清理,第二次启动必然失败 — 每次启动都以固定名称创建 .evolver-job.ps1、.evolver-job.json 和停止标记;前两个文件使用 f...(truncated) · lib/runtime/process/windows-job.js·advisory_bf8cd4e67e609ab49dadcf3e`
  • [P3] 重试补齐路由后仍保留 route_not_captured 阻塞 — withWorkTurn() 会生成已补齐 modelBinding 的 next,但随后先调用 rangeRouteProblem(range);该函��...(truncated) · lib/distill/range.js · advisory_c97fc62a2f9c487181a815d3
  • [P3] native facts 目录校验存在换链竞态,可读取隔离目录外的记录 — 代码先以 lstatSync() 确认目录不是符号链接,再单独调用 realpathSync() 检查解析路径是否以...(truncated) · lib/runtime/acp-model.js · advisory_fb65f81218ac9476a70de6d9
  • [P3] 根目录检查与实际打开之间存在目录替换竞态 — confined() 校验路径各级不是符号链接并返回字符串路径;调用者随后重新按该路径 statSync...(truncated) · lib/runtime/native-facts.js · advisory_6ad244162875dff46f775f74
  • [P3] 返回值保留了原始 API Key — credentialOf() 已提取凭据为独立的 secret,但最终仍原样返回 selected。当配置使用内联 API ...(truncated) · lib/runtime/native-config.js · advisory_98783e5e6794c027abfcfd28
  • [P3] preload 隔离测试在凭据被清理时可能静默失效 — preload 是否被执行只通过 process.env.EVOLVER_MODEL_API_KEY 判断。如果 runner 正确清除了该环境变�...(truncated) · test/fixtures/acp/poison-preload.mjs · advisory_c96183dc9c1a7ace92b0b3a8
  • [P3] Deferred native 回合在 owner 退出后仍无终态 — 新增测试明确禁止 deferred monitor 调用终态回调,并期望它在发现旧 owner 已退出后直接返回��...(truncated) · test/runtime/native-monitor.test.js · advisory_ac9a8afc192ddd2e4a0ec7c4
  • [P3] status 可读取尚未提交且随后回滚的包版本 — 包目录替换与注册表更新位于安装锁内,但普通 status 在目标目录存在时不获取该锁。它��...(truncated) · scripts/install-kimi.mjs · advisory_ff9acba943dd31e405c31f65
  • [P3] status 未参与安装锁,会暴露激活中的瞬时状态 — 写路径在安装锁内先把现有 target 移到 backup,再把新包移到 target;status 则在锁外分��...(truncated) · scripts/install-kimi.mjs · advisory_db65ef4ac12d856fc8e10844
  • [P3] 中断更新遗留的旧备份可能在后续恢复中复活 — 更新先把旧包移动到随机 staging 目录,再激活新包;若进程在激活后、清理 staging 前退出,...(truncated) · scripts/install-kimi.mjs · advisory_5b37169c8b1ac5903a74b1a1
  • [P3] 候选未写入时仍将 native 回合标记为已生成候选 — eligible 只表示该终态具备生成 work candidate 的资格,并不表示 turnEnded() 实际成功生成了候...(truncated) · lib/app/native-turn.js · advisory_f3961f097c8eac5e77e05847

另有 6 条候选未在评论中展开;可通过下方 Sentinel PR review context 查询全部条目。

开发 agent 查询详情: 调用 MCP 工具 sentinel_pr_review_context,传入 owner_repo="evomap/evolver-agent-plugin"、pr_number=56、head_sha="8e0f03565689605b0cb24c3bb4ba33cbd04e6ff1",并按条目追加 finding_id 或 finding_key。

由 Sentinel 审核 · 目标提交 8e0f03565689

Comment thread scripts/install-kimi.mjs
if (version === undefined && currentPackage && isOlderVersion(next.version, currentPackage.version)) {
throw new Error(`Refusing to downgrade Kimi plugin from ${currentPackage.version} to ${next.version}. Use a current bundle or specify --version to build the checkout intentionally.`);
}
if (currentPackage) { fs.renameSync(target, backup); moved = true; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已激活更新的中断现场不会被重试清理

🟠 严重程度:中(P2)
更新先把旧包移入 staging 的 previous,再激活新包。若进程在激活后、提交及 finally 清理前退出,target 已存在且旧备份仍留在 staging。重试时 packageOf(target) 成功,短路掉 recoverPackage(),因此旧现场永远不会被识别或清理。后续再次中断并需要恢复时,多个 staging 备份会触发 “Multiple interrupted Kimi updates found”,阻断自动恢复。

Finding:finding_c36fec8e265f115749e66c1f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants