# R14 任务报告

## 结论

已修复 [UniDesk #2355](https://github.com/pikasTech/unidesk/issues/2355)：POSIX `trans apply-patch v2` 更新已有文件时会保留原 mode，不再把 `0755` 可执行脚本替换成受临时文件 umask 影响的 `0644`。新建文件仍服从目标端既有 umask，不根据文件名或扩展名猜测权限。

实现 PR 为 [pikasTech/unidesk#2357](https://github.com/pikasTech/unidesk/pull/2357)，Artificer 提交为 `e49b2e03864bae5830609afe062efd4475d8293b`。

## 实现

- POSIX bulk replacement 在读取原内容时同时取得完整 mode，把 mode 应用到 replacement 临时文件后再执行原有 `shutil.move`。
- POSIX write fallback 为已有目标读取 GNU/BSD `stat` mode，在 `mv -f` 前应用到临时文件；无法读取时显式失败，不静默降权。
- `unidesk-trans` skill 固化稳定合同：host/workspace 更新已有文件保留 mode，新建文件继续服从 umask。
- 未改变 Windows ACL、Git index、route、SSH 权限、CI/CD 或运行面。

## Smoke

执行一次定向测试：

```bash
bun test scripts/src/apply-patch-v2.test.ts -t 'POSIX replacement writers preserve existing file modes'
```

结果为 `1 pass`、`0 fail`、`7 expect() calls`：

- bulk replacement 更新 `0755` 脚本后 mode 仍为 `0755`，脚本可直接执行并输出更新内容。
- write fallback 更新 `0644` 普通文件后 mode 仍为 `0644`。
- `git diff --check` 通过。

## 工具调用改进

修复前，每次 patch 可执行脚本后需要额外执行权限失败确认、Git index mode 核对、`chmod` 和重跑；本次现场发生两轮 `exit 126`。修复后的同类任务只需执行原 `apply-patch`，随后可以直接运行脚本，去掉这些补救调用。
