Skip to content

[Experimental / RFC] Windows fail-closed、native typed argv/逐流输出与Agent显式选路 - #26

Open
KouzakiUmi wants to merge 6 commits into
KannaKuron:mainfrom
KouzakiUmi:experiment/windows-native-argv-path-routing
Open

KouzakiUmi wants to merge 6 commits into
KannaKuron:mainfrom
KouzakiUmi:experiment/windows-native-argv-path-routing

Conversation

@KouzakiUmi

@KouzakiUmi KouzakiUmi commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

[Experimental / RFC] Windows fail-closed、native typed argv/逐流输出与 Agent 显式选路

Draft / RFC,尚未完成正式验收。
已 rebase 到上游 v0.39.3 与 PR #28 后续修复后的 main。前置 PR #24 已合并;PR #28 的兼容与 scope 清理改进已被上游吸收。本 PR 的完整 diff 现在仅包含实验增量。
最新所有权修复与验证更新。包版本跟随基线 0.39.3,实验功能未正式发布。

行为与维护者裁决

按照维护者裁决,gitbash-shell 行 Config 提供 volatile 布尔 experimentalNative,默认 true(旧配置缺键同样开启),统一控制 fail-closed 和两个 companions。

设置路径:设置 → 插件 → dsh-gitbash-shell → 实验原生执行 / fail-closed。

状态 自有 Windows Bash 两个新工具
ON(默认) RO/WW/未确定策略执行前拒绝;实际 resolved danger-full-access 才执行 公开能力可用且不冲突时注册
OFF 恢复旧版明确标注 enforcement:unconfined 的 Bash 及实例级日志;未确定策略保留旧宿主委派 实时注销,旧 SDK 引用也拒绝

修改作用于现有会话后续调用,无需重启;已开始的后台 producer 保留生命周期。关闭后 shell 文件写入限制不执行,不能视为恢复真 Windows 围栏。路径方言/codePaths/子代理方言开关独立。

拒绝错误说明设置关闭路径以及用户在会话访问模式控件选择 danger-full-access 的路径;Agent 不得自行放宽权限、换工具或文件 I/O 绕拒绝。native 在准备入口、异步准备后、执行入口和最终 spawn 重验开关与 policy。

实验实现

  • gitbash_to_native_path: 完整 caller-declared MSYS 值转 native_path,复用 fresh mount facts,不转换 route/search/code,不授文件权限。
  • gitbash_native: 绝对 typed executable/cwd 与 literal/path argv;literal 不经过 MSYS,只显式 path 转换。复用公开 Core LocalBashExecutor.executeArgv、managed provider、Jobs 与 credential scrub。
  • 输出: stdout/stderr 独立 utf8/gbk/utf16le/raw、incremental decoding、raw/normalized UTF8 artifacts、独立 byte cursor、closed facts DTO。未知同流混编码不猜;显示失败保留真实 producer outcome,不盲目重跑。
  • 生命周期: operation-owned cancel、准备有界期限、有限 drain;默认两流 raw+decoded 磁盘 8MiB、自有 payload 16MiB。不是 RSS/跨调用硬 quota;完成 artifacts 保留,无自动 purge。
  • Agent 路由: shell 语法优先 bash;精确 native argv/已知编码选可见 native;完整 MSYS 值交 Node 选可见 helper;真 cmdlet/WMI 选可见且开关允许的 pwsh。普通提示与 PTC SDK 有送达验证。

沿用 route B 的 agent-owned 工具 scope 与 operation-owned 执行 scope,官方 root PowerShell/provider 保留。已有同名工具不覆盖;缺 native 公开能力不撤 Bash/path。官方未来开放对应 native/encoding/closed DTO API 时,按官方优先纪律整体迁移并退役插件私有实现。Artifact ownership/quota/retention 由插件自管;后台 Jobs/controller admission 不可用时明确拒绝,不静默改前台重复执行。

本轮进展(2026-10-14)

  1. 完成到最新 main 的 rebase,保留 v0.39.3 的工作目录、sidebar 命名空间与失败 scope 清理修复;正式 CHANGELOG 原文保留。
  2. Bash/native 共用可选目录读取适配器:有服务使用官方 ensure,错误不降级;缺服务走 policy.workspaceRoot ?? session.header.cwd。native 不再硬 inject workingDirectory。
  3. Companion 要求 apply 已执行;scope 就绪、实际注册成功和让位分别记录。每次初始挂载、开关更新及 native Jobs 刷新均检查当前 agent 的工具所有权,外部同名工具让位,避免关闭/冲突状态的假成功日志。
  4. 21 份字典已完成开关本地化;欢迎维护者继续校对译文。测试检查关键工具名、UNCONFINED 和 danger-full-access 事实齐备。
  5. 新增旧宿主缺服务形状下的三入口注册/cwd/双向开关,以及真实 native producer 的 policy/header 默认目录。
  6. 真实 Git Bash 验证 RO/WW 中 OFF 执行并标注 unconfined、ON 再拒绝,以及未确定 policy 的拒绝;代表性解释器抽测 cmd.exe literal /c 和 PowerShell EncodedCommand + UTF16 中文输出。

独立审查与本轮修复

未继承对话历史的子代理重新审查完整增量,确认一项 P2:OFF 期间外部注册同名工具,恢复 ON 后全局工具被遮蔽,同 agent 工具则抛 duplicate 异常并阻断后续 companion 注册。本轮已修复全部确认问题:

  • gitbash_to_native_path 与 gitbash_native 共用按 agent 检查所有权的注册入口,每次刷新先注销自身注册,再检查外部全局/同 agent 所有者。实际 Core 的 knownNames 包含隐藏工具;旧宿主回退 schemas 检查,旧宿主隐藏工具行为尚未独立验证。
  • 冲突时保留待命 scope 并记录让位;外部所有者移除后,下次刷新恢复。所有权检查或注册失败明确记录,不向 volatile 事件抛错,也不阻断另一工具更新。
  • 新增六项实际 Core 回归覆盖两工具×两注册层级、重复开关、恢复、Jobs 刷新及隐藏工具,另新增一项普通回归覆盖失败隔离与恢复。
  • 独立子代理复核原始所有权复现与新增专项 9/9 通过,未发现新的确认缺陷;这些专项与完整回归有重叠,不累加覆盖数。
  • 最初疑似 Bash policy 时序问题已依据宿主逐操作快照契约撤回,本轮保持该行为。正式四项验收仍待,继续保持 Draft/RFC。

分步审查建议

继续建议两步 review:① Bash fail-closed、唯一 Config 开关/UI、拒绝引导与旧行为回退;② native/path、输出生命周期与可见性路由。第二步复用第一步的同一字段。当前保留完整 Draft/RFC 和跨层回归,尚未另开子 PR。

验证

环境:Windows / Node 24.13.0 / Core 0.2.1-alpha.2。

项目 结果 证据范围
普通完整回归 232/232,exit0,无 skip/cancel 原护栏、本地化、旧 SDK 拒绝、policy/header 与 ensure 错误不降级
实际 Core 完整 preview 85/85,exit0,无 skip/cancel 实际 ToolRuntime/Cordis;包括真实 Git Bash/Node/cmd/PowerShell 进程及受控 provider/Jobs 场景
syntax / diff / npm pack dry-run 通过 新适配器、native/live gate 与文档均进入包清单;不是发布

已安装实验构建的三入口实机报告提供有限外部证据:入口主路径、RO/WW 拒绝、单次 Bash 批准不粘滞。报告未记录精确提交,也明确未覆盖开关 OFF、真实 LLM 自主选路、生产 GUI 与非 CRT 矩阵,不作为当前 rebase 构建的完整生产验收。

正式 review / release 尚待

  • 默认开启的 volatile 运行时开关、拒绝引导与旧行为回退。
  • 前置合并后 rebase、同步旧宿主兼容与激活验证。
  • 21 份设置文案本地化。
  • 分步审查范围评估。
  • 真实 Agent 自主选路。
  • 生产 GUI(非 preview)。
  • 维护者 Windows 真机全量验证(维护者执行)。
  • 非 CRT 解释器矩阵正式确认。 已有 cmd/PowerShell 固定脚本抽测,但不代表任意引号/元字符/parser 均可用。

四项齐后才谈 ready for review → release。真 Windows confinement/ACL/token/IPC/VM、SSH/PTY、真实磁盘耗尽/吞吐/RSS/跨任务 quota/purge 仍无完整验收,不据测试绿色宣称生产可用。

@KannaKuron

Copy link
Copy Markdown
Owner

感谢这份 RFC——克制的标注(Experimental/RFC、明确「不是恢复真正 Windows 围栏」、不因测试绿请求合并)和两份设计文档正是我们希望看到的提交方式。维护者已对核心问题做出裁决:

裁决:接受 fail-closed 方向,但必须加运行时开关,且默认开启

  1. 开关是硬性前置:受限模式从「绕过+标注」改为「拒绝」是推翻仓库既有裁决(【Bug】Git Bash 执行器在 workspace-write 沙箱模式下"假成功"(exit 0、无输出、无文件副作用) #1/[BUG] README「保留官方沙箱语义」与 Windows 受限模式的实际行为不一致(0.33.0) #14)的产品行为变更,不允许「装上即生效」。请为 fail-closed 行为与两个新工具(gitbash_to_native_path/gitbash_native)提供行 Config 的 volatile 布尔开关(可与既有开关同卡),默认 true。你 PR 中「不改 Config/UI 或 21 语言设置词典」的自我约束需要为这一个开关解禁——开关文案可先行,词典不齐的部分我们合并前一起补。
  2. 默认开启、可随时关闭:维护者评估后的取舍是——现状(假围栏+标注)与 fail-closed(拒跑)之间,后者更诚实;出问题时用户在设置里一键回到旧行为,升级风险可控。拒绝路径的报错文案请写明「如何在设置中关闭」与「如何切换会话访问模式」,别让用户只看到一堵墙。
  3. 其余讨论项的答复:
    • Q3(上移 Core):native typed argv / 逐流 encoding / closed DTO 这类能力,若官方未来开放对应公开 API,本插件按「官方优先」纪律整体切换并退役私有实现——先记录为长期跟踪项,不阻塞本 PR。
    • Q4(artifact ownership/quota/retention):插件层自管,不要求宿主承担。
    • Q5(Jobs/controller 缺失):拒绝并如实报错,不得静默改前台重复执行——与你现行设计一致,保持。
    • Q6(实验转正式最小验收集):真实 Agent 自主选路 + 生产 GUI(非 preview)+ 维护者 win32 真机全量验证(我方执行)+ 非 CRT 解释器矩阵抽测。四项齐了才谈 ready for review→release。
    • Q7(合并顺序):修复:MSYS兼容边界、run_code路径扫描与unconfined反馈 #24 先行(已核实、即将 review);本 PR 在 修复:MSYS兼容边界、run_code路径扫描与unconfined反馈 #24 合并后 rebase,并请评估拆分——fail-closed 行为变更与 native 工具/选路提示至少值得拆成两步走,降低单次 review 的裁决密度。

在开关落地 + rebase 之前,本 PR 保持 RFC 状态,不进入正式 review。 再次感谢克制与文档质量——这正是这个仓库需要的贡献方式。

@KouzakiUmi

KouzakiUmi commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

实机测试报告(本机已装插件,非源码/单元脚本)

针对本 PR 已部署到本机 desktop profile 的 dsh-gitbash-shell@0.39.2 做了 Agent 实机调用(bash / gitbash_to_native_path / gitbash_native)。未跑仓库 npm test / test:preview。

环境:Windows 10 / Git for Windows Bash 5.3.15(MSYSTEM=UCRT64),git 2.56.0.windows.2。路径与账户在下文用占位符:<user>、<host>、<home>、<repo>。

会话政策分三段:

  • 先在 danger-full-access 下测三条入口主路径与门控
  • 再切到 workspace-write 补 fail-closed / 单次升权
  • 再切到 read-only 重复 fail-closed / 单次升权

结论

三条入口在本机 主路径可用,关键门控有效。bash 仍会做 MSYS /all、/c 转换;对应场景必须走 gitbash_native 字面 argv。

workspace-write 与 read-only 下自有 bash 与 gitbash_native 均为 执行前拒绝、命令未启动、无 unconfined 降级。单次批准 danger-full-access 后同一条 bash 探测可以跑通;随后不带升权再次调用,两条入口重新拒绝。gitbash_to_native_path 不 spawn,受限模式下仍可用。没有关 experimentalNative,未测开关 OFF 的旧 unconfined 回退。


1. bash(Git Bash)

用例 结果
身份:BASH_VERSION / uname / git --version Bash 5.3.15,MINGW64_NT,git 2.56.0.windows.2
~ /tmp /dev/null 盘根 解析正常
管道、glob(/usr/bin/bash*)、重定向、中文 UTF-8 通过
workdir=/tmp pwd → /tmp
后台 sleep 3 completed,exit 0,输出含 bg-done-*
false 后 $? 1
ipconfig /all 失败 exit 1(MSYS 吃掉 /all,打印用法)
ipconfig //all 成功,但 bash 按 UTF-8 收 GBK,中文乱码
cmd /c echo ... 失败(/c 被当成盘根,进入交互 cmd)
cmd //c echo ... 成功

2. gitbash_to_native_path

输入 结果
/c/Users/<user> C:/Users/<user>
~ / $HOME <home>(C:/Users/<user>)
/tmp C:/Users/<user>/AppData/Local/Temp
/dev/null \\.\NUL
/usr/bin/bash c:/program files/git/usr/bin/bash
/c/Program Files/Git/usr/bin/bash(空格) C:/Program Files/Git/usr/bin/bash
/c/Users/<user>/测试 目录#hash(中文/空格/#) 原样映射到 C:/Users/<user>/测试 目录#hash
已是原生 C:\Users\<user> 保留反斜杠
相对路径 foo/bar 原样返回
/ucrt64/bin/git 拒绝 NO_MOUNT_MAPPING(不把 POSIX 原样冒充 native)
https://example.com/path 拒绝 [URL]
空字符串 拒绝 [EMPTY]

3. gitbash_native

用例 结果
ipconfig.exe + 字面 /all,stdout=gbk exit 0,中文「Windows IP 配置」正常(未记录适配器/地址)
whoami.exe utf-8 <host>\<user>
可执行文件用 MSYS 路径 /c/Windows/System32/whoami.exe 同样成功
git.exe --version git version 2.56.0.windows.2
git -C + kind:path 指向本机一个 git worktree + rev-parse --short HEAD exit 0,打印该 worktree 的 short HEAD(路径 argv 已翻译)
typed cwd = /tmp whoami 仍成功
cmd.exe /c 未声明 entrypoint: interpreter 拒绝(已知解释器必须显式 interpreter)
补上 entrypoint: interpreter 后字面 /c echo native-cmd-ok native-cmd-ok,/c 未被转成盘根
foo.cmd / foo.bat 拒绝:only native .exe;never wrap .cmd/.bat
非绝对路径 whoami 拒绝:unresolved or non-absolute typed path
stdout=raw(whoami) exit 0;reliableText=false,保留 raw bytes,不把原文当 UTF-8 文本
stdout=utf16le 套在实际并非 UTF-16 的 whoami 上 exit 0 仍保留;解码呈乱码(声明编码被应用,不是自动探测)
后台 ping.exe 127.0.0.1 -n 2,encoding=gbk completed,exit 0;中文 Ping 统计正常

4. 沙箱 / fail-closed

4.1 workspace-write

用例 结果
WW 下 bash(echo + pwd + 写 /tmp/dsh-pr26-ww-probe.txt),不升权 执行前拒绝。无可用 Windows Git Bash 围栏;命令未启动;禁止 unconfined 降级;禁止换工具绕过
WW 下 gitbash_native whoami.exe,不升权 执行前拒绝。无 confined backend adapter;RO/WW/缺失策略在 spawn/artifact 前拦截
WW 下 gitbash_to_native_path /c/Users/<user> 仍可用:C:/Users/<user>(纯转换,不启动进程)
对同一条 bash 探测单次批准 danger-full-access 真正执行:pwd → 会话工作区;写出 /tmp/dsh-pr26-ww-probe.txt,内容 sandbox-write-probe
升权之后、不再带批准再打 bash 再次 fail-closed,命令未启动(单次批准未变成长期 full-access)
升权之后、不再带批准再打 gitbash_native 再次 fail-closed。该工具无 per-call 升权参数,WW 下只能拒绝

4.2 read-only

用例 结果
RO 下 bash(echo + pwd),不升权 执行前拒绝。文案与 WW 同类:无可用 Windows Git Bash 围栏;命令未启动;禁止 unconfined 降级;禁止换工具绕过。错误串标明 requested mode 为 read-only
RO 下 gitbash_native whoami.exe,不升权 执行前拒绝。无 confined backend adapter;RO/WW/缺失策略在 spawn/artifact 前拦截
RO 下 gitbash_to_native_path /c/Users/<user> 仍可用:C:/Users/<user>
对同一条 bash 探测单次批准 danger-full-access 真正执行:输出 ro-should-refuse,pwd → 会话工作区
升权之后、不再带批准再打 bash 再次 fail-closed,命令未启动
升权之后、不再带批准再打 gitbash_native 再次 fail-closed。无 per-call 升权参数

WW 与 RO 的拒绝语义一致,仅 requested mode 字符串不同。


仍未覆盖(不能当成通过)

  • 未解析 / 缺失策略的实机 fail-closed(本机只打到明确的 danger-full-access / workspace-write / read-only)
  • 关闭 experimentalNative 后的旧行为回退
  • 真实 LLM 自主选路、生产 GUI、非 CRT 解释器 quoting 矩阵
  • 真 Windows confinement / ACL / token / IPC
  • gb_* FastCtx、变体 preset、pwsh 显隐(不是本 PR 三条入口的实机范围)

在上述缺口补齐前,这份报告只证明:本机已装实验构建上,三条路由入口和所列门控可工作;workspace-write 与 read-only 下自有 Bash/native 会 fail-closed,单次 full-access 批准可以放行 bash 且不粘滞。 不能当作发布或安全放行。

@KouzakiUmi
KouzakiUmi force-pushed the experiment/windows-native-argv-path-routing branch from ddf82cf to 771c618 Compare October 13, 2026 17:34
@KouzakiUmi
KouzakiUmi marked this pull request as ready for review October 14, 2026 05:30
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