Skip to content

feat: add native Step Code CLI Windows adapter - #59

Draft
imxyanua wants to merge 13 commits into
EvoMap:mainfrom
imxyanua:codex/step-code-windows
Draft

imxyanua wants to merge 13 commits into
EvoMap:mainfrom
imxyanua:codex/step-code-windows

Conversation

@imxyanua

@imxyanua imxyanua commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Draft; depends on #54. Please review the Step-only changes here. The branch currently includes #54; sync with main after that dependency merges.

Add a native resident extension for Step Code CLI 0.1.7 on Windows:

user prompt → Recipe recall → ephemeral model context
native tool call/result → executed arguments + exit evidence
agent_settled → reuse report + session range
captured native SDK route → validated IR → private draft

The adapter reuses the plugin channel, verification, reports, session ranges, private drafts and explicit publication commands. It pairs native calls/results, latches cancellation across model steps, and keeps Recipe context out of the saved transcript and subsequent prompts.

Private completion pins provider/model/thinking level/account, uses no tools or prior session transcript, rejects changed routes and late answers, and never persists credentials. Local package install/remove preserves plugin data. No new dependency or Desktop adapter is included.

Evidence

  • Before: Step Code had no reviewed host adapter. Boundary regressions reproduced false success reports when later native middleware changed a check command, tool identity, edit target or added an inline check.
    After: All four cases suppress reports/candidates; the final Step suite passes 37/37 on Windows Node 22.23.4 and 26.13.0, without skipped tests.
  • Upstream Test and release passed at 95c5b21352fae35f474c1f093f06d7fb047520d4: Linux Node 22 and 26 each ran 963 tests, 961 pass, 2 existing skips, then packed all 11 hosts. Windows/release jobs correctly skipped for this PR event.
  • Windows shared/MiniMax gate: 543 pass, 10 existing skips on each runtime. ZCode: 14/14 on each. Architecture/packed layout: 13/13; all 11 hosts pack on both runtimes.
  • Pinned native Step 0.1.7 Windows, disposable profiles, loopback model and Proxy fixtures: Recipe present throughout its prompt and absent from the next; native exit 0 leads to two reports bound to the same turn and one private draft; exit 1 remains failed. Esc/RPC abort after pass produces no report, candidate or draft. SDK request has no tools/session tool results and uses the expected fixture route/account.
  • Native local-package install → list → remove → list: all exit 0; plugin-data sentinel and package source survive.

Remaining acceptance gates: paid-provider and real Proxy/Hub acceptance; native transport/OAuth-refresh cleanup. Separate foreground run_command/bash checks are supported; inline then_run and background execution exclude the whole turn. Native double Ctrl-C can exit Step without a terminal event and leave its tool process alive: the adapter suppresses publication evidence but does not kill Step-owned processes. These limits keep this PR in draft.

Merge Danger

Door: two-way

Remove the extension to stop new work; its profile data remains. Do not merge before #54 and the remaining acceptance gates are reviewed.

Blast Radius: host

New Step host and packaging/CI coverage. Shared production code only re-exports the existing headless guard and host-command catalog from the plugin channel. PR CI runs the existing Linux matrix; Windows host suites remain in the existing tag gate and were run locally above.

Recheck dead-owner turns against native terminal status, keep delayed end handlers within their own session epoch, and only settle reuse evidence actually queued. Continue reading the completion handshake after stdout capture reaches its limit.
Keep verified report payloads in the injection ledger after a local queue failure. Retry using the original check evidence and leave unverified injections out of delivery.
Forward the supplied record after native terminal confirmation and handle a missing status reader. Give a dead owner a bounded grace for terminal metadata and omit any stale worktree. Isolated model declarations default to an empty environment.
Keep the cross-shell calibration regression already landed upstream in EvoMap#55.
Require an explicit regular ZCode CLI bundle for background completion. Install through CLI plugin directories, and exercise the package without a Desktop installation.
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.

(cherry picked from commit bbd7c68)
Preserve the pending native-terminal deadline after its owner exits, pass the private configuration path to unbound environment callbacks, reject escaping scratch-file paths, and tolerate a vanished dead-owner state lock.

Run the fixture Proxy independently of synchronous host work, preserve its request getter through the DSH wrapper, and track fixture-owned MiniMax workers for scoped teardown. Add regressions for the runtime contracts and native ZCode database discovery.

Validation on this exact tree: full Linux tests on Node 22.23.4 and 26.13.0 each passed 908 with one Windows-only skip. Windows test:minimax passed 528 with ten platform skips and test:zcode passed 14 on both Node versions. Packaging all ten hosts passed on both platforms. Assertions, suite workloads, and existing deadlines remain unchanged.
A throwing closeInputOn callback escaped the stdout EventEmitter, which could terminate the host before model completion cleaned its private files. Keep the original error, stop the owned process tree, and normally finish when the child closes. Preserve the same error through the existing timeout and process-error paths, and do not start a Windows handshake process when tree termination is unavailable.

Add regressions for child/grandchild termination, model error identity and private-file cleanup, and the missing Windows termination backend. The two exception tests failed uncaught before the fix. All five model-executor tests pass on Windows Node 22 and 26; each full Windows gate passes 531 common/MiniMax tests (10 platform skips), 14 ZCode tests, and packaging of all ten hosts. Existing assertions and deadlines are unchanged.
An older turn waiting for its host record could consume a later turn's untagged check notes and edit baselines. Store evidence by the plugin epoch and turn counter, snapshot only the opened generation, and leave failed-reader claims recoverable with their original hashes. Keep ambiguous legacy files in their own namespace and bound abandoned evidence claims with the existing TTL; report-queue claims are unchanged.

Carry prompt-opened and tool-recorded identities into monitor tasks instead of adopting the state current after asynchronous work. Pin that identity through polling and atomic turn close, separate generation lock keys, and prevent a delayed Git HEAD read from updating a replacement epoch.

Regressions exercise real prompt/tool/turn flows, missing native turn IDs, same-ID epoch replacement, delayed worker startup, reader rejection and claim recovery, legacy namespace isolation, and evidence-only pruning. Joint driver/app/store/monitor/ZCode tests pass 140/140 on Windows Node 22 and 26. The complete Windows gates pass 542 common/MiniMax tests (10 platform skips), 14 ZCode tests and packaging of all ten hosts on both versions.
@evomap-aiqa-bot

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

Copy link
Copy Markdown

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

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

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

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

由 Sentinel 审核 · 目标提交 95c5b21352fa

@evomap-aiqa-bot

Copy link
Copy Markdown

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

  • [P3] spawnSync 阻塞宿主事件循环,导致子进程请求无法被代理处理 — spawnSync 会同步阻塞父进程的 JavaScript 事件循环;如果 startProxy 的 HTTP server 与测试运行在...(truncated) · test/hosts/dsh/proxy.test.js · advisory_ab5966ad0c438d8f6542310f
  • [P2] 会话开始与结束在异步确认前即被标记完成,通道失败会永久丢失生命周期�...(truncated) — start() 在等待 channel.handle('session_start') 成功前就写入 started;一旦调用抛错,后续入口��...(truncated) · hosts/stepcode/dist/plugin.mjs · advisory_ecb9e5e15f4937b2ef1b5da1
  • [P3] 测试清理只终止 worker 根进程,可能遗留其子进程 — 新增清理逻辑仅按 PID 终止被记录的 worker。POSIX 上这不会终止同一进程树中的子进程,Window...(truncated) · test/hosts/minimax/hooks.test.js · advisory_77080010102f20ae77e9fac2
  • [P3] ZCode 的中间 Stop 事件会被误记为最终答案 — Stop 被映射为 EVENTS.TOOL_RESULT,而 toolNote 对所有 Stop 事件都会读取 responseText 或 last_a...(truncated) · hosts/zcode/profile.js·advisory_f1db6afe265d9a88b50ad2d5`
  • [P3] epoch 切换可使已入队报告失去 DRAIN 调度 — reportTurn 已把报告、待重试报告或 controls 写入 outbox 后,新增的 epoch 复查可直接返回 null...(truncated) · lib/app/turn-end.js · advisory_c90ec88f1000bf2e3ad65f26
  • [P3] 旧的 completed 状态可能被归属到复用 turn ID 的新一代任务 — PR 使用 expectedTurn.turn/sessionEpoch 隔离锁和本地 session,却仍仅以 sessionId + turnId 查询 turnSt...(truncated) · lib/runtime/turn-monitor.js·advisory_6b75cec034babeb5321613e1`
  • [P3] 显式模型路径绕过范围的配置绑定校验 — canJoinRange() 能阻止不同 configDigest/selection 的模型共享候选范围,但两处调用都被 if (model...(truncated) · ``lib/app/turn-end.js`` · advisory_f9461efa488816fa9e53eb44`
  • [P3] reset/clear 后可能缺少 in-flight completion 防护 — 状态链探针:reset/clear path touches async state but no abort/generation fence is visible for in-flight completion...(truncated) · test/app/memory-ports.js · slice:data_integrity_01:state_chain_a02dcabaca94d6c8
  • [P3] snake_case ZCode 事件会因无法读取 turn_id 被静默忽略 — 新 profile 明确兼容了 session_id、agent_id、tool_use_id、tool_name、tool_input、tool_response 和...(truncated) · hosts/zcode/profile.js · advisory_4b3bbbb728210a5ad3502e46
  • [P3] 失败分支可能清空 last-known-good 数据 — 状态链探针:failure branch writes data/cache-like state; verify it does not clear useful last-known-good content · lib/runtime/store/file-stores.js · slice:release_integrity_04:state_chain_8ea351ae8713ea3c
  • [P3] 异步工具与命令回调缺少终止后的二次校验 — 多个异步处理器只在第一次 await 前验证 frame/ended/closing。等待期间旧 frame 可被 finish() �...(truncated) · hosts/stepcode/dist/plugin.mjs · advisory_f238cb47e6d357b05dc57d14

需要完整证据时,可用行末 finding_key 查询 Sentinel PR review context。

由 Sentinel 审核 · 目标提交 95c5b21352fa

@imxyanua
imxyanua marked this pull request as ready for review November 9, 2026 06:44
@imxyanua
imxyanua marked this pull request as draft November 9, 2026 06:53
@cursor

cursor Bot commented Nov 9, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@evomap-aiqa-bot

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

Copy link
Copy Markdown

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

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

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

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

由 Sentinel 审核 · 目标提交 07b44c5381d0

@evomap-aiqa-bot

Copy link
Copy Markdown

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

  • [P2] epoch 切换后已入队报告不会触发 DRAIN — reportTurn 可先把新报告、待重试报告或 controls 写入 outbox;若随后检测到 sessionEpoch 已变��...(truncated) · lib/app/turn-end.js · advisory_f0fb6e24b71a7b7d50e40d69
  • [P2] 会话开始与结束状态过早提交,通道失败会永久丢失生命周期事件 — start() 在 channel.handle('session_start') 成功前写入 started,调用一旦 reject,后续入口会永久�...(truncated) · hosts/stepcode/dist/plugin.mjs · advisory_15e30a5fb7d20a123dde1500
  • [P2] 缺少 turnStatus 时孤儿会话恢复被完全禁用 — sessionStarted() 仅依据 confirmTurnCompletion 跳过原有 queueOrphanReports();但 recoverNativeTurns() ��...(truncated) · lib/app/session-start.js · advisory_e396ec22917a46c9573b2e64
  • [P2] 复用的 native turnId 可能用旧终态关闭新代际 — 监控锁和 watched 已按 turn/sessionEpoch 区分代际,但 turnStatus 查询仍仅传入 sessionId、turn...(truncated) · lib/runtime/turn-monitor.js·advisory_1438e578601bda4070873fe6`
  • [P3] 取消测试在 POSIX 上未验证并清理子进程,可能遗留后台进程 — 测试在所有平台都启动一个独立子进程,但只有 Windows 分支检查 child 已退出;在 POSIX 上��...(truncated) · test/hosts/zcode/hooks.test.js · advisory_28b4e2fe7eeb0783ec2b3d13
  • [P2] 非终态状态不会触发后续重试,稍后完成的 turn 将一直保持 open — recoverNativeTurns 在 reasonOfNativeStatus 返回空值时直接跳过该 turn,并正常完成后台任务;它�...(truncated) · lib/app/session-start.js · advisory_9bc3eb62314a8d0b6c7da7eb
  • [P3] spawnSync 阻塞代理所在进程,新增测试会超时失败 — spawnSync 会同步阻塞父进程的 JavaScript 事件循环。若 startProxy 使用当前 Node 进程的 HTTP serv...(truncated) · test/hosts/dsh/proxy.test.js · advisory_32be503824f278378acadf6a
  • [P3] 路由变更测试修改了错误的 fixture 字段 — 测试试图验证 route 变化,但修改的是 fixture.auth.baseUrl;fixture 中真正定义的路由字段是 fi...(truncated) · ``test/hosts/stepcode/model.test.js`` · advisory_16b468847616c11fcf741b84`
  • [P3] 会话关闭后未确认的 turn 永久失去恢复入口 — 开启 confirmTurnCompletion 后,sessionEnded() 只处理 pendingReportsOf() 返回的资产。该函数只返��...(truncated) · lib/app/session-end.js · advisory_0b0478360f6799e0d28a41b7
  • [P3] 空白数据目录使状态目录与 provider 配置读取到不同根路径 — homeOf() 使用 trim() || nativeHomeOf(env),将空白值视为未设置;但 providerConfigOf() 使用 trim() ...(truncated) · hosts/zcode/model.js·advisory_f16f190a9b42d55615aca1e6`
  • [P3] 测试清理仅终止 worker 根进程,可能遗留其子进程 — stopWorkers() 对记录到的每个 worker 仅执行 process.kill(pid)。POSIX 和 Windows 上该调用都不保证�...(truncated) · test/hosts/minimax/hooks.test.js · advisory_e7a02a23f90af30ac7e8350c
  • [P3] 中间 Stop 被作为最终回答写入 turn 证据 — 新增 toolNote 对每个 Stop 都生成 { kind: 'answer' },并将其映射到 EVENTS.TOOL_RESULT。同文件�...(truncated) · hosts/zcode/profile.js · advisory_f4e370cb6279fd57c3af608e
  • [P3] reset/clear 后可能缺少 in-flight completion 防护 — 状态链探针:reset/clear path touches async state but no abort/generation fence is visible for in-flight completion...(truncated) · test/app/memory-ports.js · slice:data_integrity_01:state_chain_a02dcabaca94d6c8
  • [P3] shutdown 在提交最终生命周期事件前关闭通道 — shutdown 先调用 channel.close(),之后才通过 finish() 提交 agent_settled,并直接提交 session_shut...(truncated) · hosts/stepcode/dist/plugin.mjs·advisory_05a98dc25a68479e8fc95320`
  • [P3] 失败分支可能清空 last-known-good 数据 — 状态链探针:failure branch writes data/cache-like state; verify it does not clear useful last-known-good content · lib/runtime/store/file-stores.js · slice:release_integrity_04:state_chain_8ea351ae8713ea3c

需要完整证据时,可用行末 finding_key 查询 Sentinel PR review context。

由 Sentinel 审核 · 目标提交 07b44c5381d0

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.

1 participant