更新锁不再在你的目录里留垃圾 / Update locks no longer litter your directory
ops_* 写入时在目标旁创建的协作锁 .dsh-ops-update-<名字 sha256>.lock 以前永不删除:写一次留一个,ops_replace 甚至为它扫描过的每个文件各留一个。Windows 上 . 开头既不是隐藏属性、也不被 git/编译器忽略,于是项目里到处是这些文件(#319,四位用户报告,其中一人禁用插件)。与权限模式无关。
现在锁仍然在目标旁(PTC 受限沙箱只放行工作区 + 会话临时目录,锁不能挪到全局位置),但释放时由持有者删除,用两条规则堵住原来的漏洞,而不是靠留下文件:
- 发布前绑定校验:拿到独占锁后重新打开该名字,比较
(device, inode) 与已锁 inode;名字已不指向自己锁住的 inode(前一个持有者刚发布并删除)就丢弃句柄重新获取。只有绑定成功的持有者才能发布,所以打开过旧 inode 的等待者写不进去。
- 释放时仍持锁、且名字仍指向自己的 inode 才 unlink,因此别人重建的锁不会被误删。
结果:成功写入不留、锁后被拒不留(含被 write_roots 拦住的整目录 replace)、不累积;只有被硬杀(SIGKILL/断电)的写者会留一个,而它不是死锁——下一个同名写入会锁它、用它发布并删掉它。旧版本遗留的文件也在这些写入里被顺带清掉;长期不再写入的目录可以手工删一次:
:::powershell
Get-ChildItem -Recurse -Force -Filter .dsh-ops-update-*.lock | Remove-Item
Same in English: the lock file was kept forever on purpose (#240 P5) because unlinking it on release could let a waiter that had already opened the old inode publish under an orphaned lock. UpdateLock now closes that window instead: it binds the locked inode to the name (reopening the name and comparing (device, inode)) before publishing, and unlinks only while still holding the lock on the inode the name carries. A published write, a refusal after the lock and a directory-wide replace leave the directory exactly as they found it; the only residue is a writer killed between locking and release, which the next write of that name reuses and removes. The lock stays beside the target because no shared location is writable in every PTC confinement mode (bwrap's /tmp is a private tmpfs; the Windows ACL grant covers the workspace and a per-session temp directory).
顺带修复:0.4.0 里三个没回到 main 的提交 / Also carried: three 0.4.0 commits that never reached main
v0.4.0 的 tag 不是 main 的祖先(git merge-base --is-ancestor v0.4.0 origin/main 失败),main 缺了三个已随 0.4.0 发出去的修复。若直接从 main 发版会把它们退回去,所以本版把它们收回来(原作者与提交信息保留):
fix(shell): ops_bash 的后台任务恢复。main 一直是旧的 ctx.get('jobs') === jobs 身份比较,而被跟踪的 Cordis 服务每次读取都返回新的 traceable proxy,于是 run_in_background 必然报 EXECUTOR_UNAVAILABLE;改为经 ctx.inject(['jobs'], …) 绑定一次注册表并传入工具定义。
test(credential): 凭据拒绝用例自己持有工作区 fixture,修提权 Windows runner 上的失败。
ci(release): publish job 补 checkout,否则 gh 无法解析仓库,Release 资产传不上去。
安装 / Install
GitHub 渠道产物(本 Release):dsh-ops-0.4.1.tgz、dsh-ops-bash-win32-x64-0.2.1.tgz、SHA256SUMS。三个平台的 native worker 都在主包里(win32-x64 / linux-x64 / darwin-arm64),Windows 另带 Bash IPC 代理。
npm 是另一个渠道,本 Release 不含 npm 发布:npm view dsh-ops version 仍是 0.4.0,npm publish 需要在维护者机器上用 NPM_TOKEN 单独执行(见 docs/PROVENANCE.md、docs/release-process.md)。
验证 / Verification
* refactor!: remove FastCtx and the background component by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/121
* feat(activity): project bounded OPS session activity (1/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/122
* feat(tui): add an opt-in read-only OPS sidebar (2/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/123
* feat(tui): surface bounded native result diagnostics (3/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/124
* test(tui): verify native file results through the real DSH loop (4/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/125
* feat(tui): add bounded all-session anomaly badges (5/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/126
* feat(tui): add focused filters and local activity pages (6/6) by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/127
* fix(cross-platform): 三平台门禁收敛 —— 修复 [#130] + 可见跳过 + Windows 清单更正 + 门禁脚本 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/134
* ci: 合并自动验证,门禁数字不再写死 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/142
* fix(config-updates): 结合 [#138] 的 patch 层持久化与 [#136] 的内存优先克制(#108, [#91]) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/140
* ci: 保证功能正常 + 能构建(门禁进 CI,并校验发行物) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/153
* ci: 增加"工具尝试"作业(非强制),并收下 [#101]/#102 的贡献 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/155
* ci: 套件时限可配 + 超时重试一次(默认关闭) + 取消在途/缓存/改名 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/165
* ci: 让 master 镜像自动快进到 main(仅快进,不覆盖) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/166
* docs: 让 0.3.1 的文档/声明面与当前 main 的实现一致(#174) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/176
* build(native): 前置落地 windows-metadata crate(解除 [#179] 的 Windows 阻塞) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/182
* feat(#169): 新增 opt-in 的严格官方工具接管组件(hide-official),注册为默认关闭 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/178
* ci: 把门禁收敛成一个可被分支保护引用的检查(并让承诺变成断言) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/186
* feat(issue-167): 原生文件工具面扩到 11 项(工具 + 参数 schema/契约) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/179
* feat(issue-168): 写出安全与原子性层(叠在 [#179] 之上) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/187
* merge: promote validated safety stack [#187] into main by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/199
* fix(ptc): bounded owned paging and discoverable SDK contracts (#171) by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/195
* feat(defaults): enable PTC enhancement and retain shell on every platform (#170) by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/196
* ci(#162): 重写 release.yml 为门禁化的 GitHub Release 发布,并补发布流程文档 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/177
* test: make the [#151] suites pass for the right reason on all three hosts, and write a bilingual CONTRIBUTING (#172) by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/181
* bench(p11a): 统计判决核心 —— pass-drop 先行 + 只在双方通过的配对上比成本 + A/A 噪声底 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/215
* bench(p7): 运行器 A —— 单发会话驱动与归档(NDJSON + trace) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/214
* bench(p9): setup A —— 两侧 profile 幂等准备(含 env 全局 npm 兜底) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/216
* bench(int): 接线 tools target,并让 CLI tripwire 与切片合并顺序无关 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/222
* bench(p8a): run.json 契约对齐(放宽 usage/轨迹槽位)+ 封存 seal by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/220
* bench(p13): 工具级确定性对比(收编 [#103],判定不含时间) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/211
* bench(p10): setup B —— preflight(权限组合 / PSModulePath / 构建前置)+ CLI 入口 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/219
* bench(p11b): 报告渲染(结论条 + 配对表 + 噪声带 + 归因) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/218
* bench(int2): pending tripwire 接受两种 pending 文案 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/223
* bench(p12): 数据面板(读 JSON 的单文件查看器 + 模板胚子) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/217
* bench(p8b): AB/BA 交错调度 + A/A 噪声跑 + ab 入口 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/224
* bench(wire): 任务语料 + tools 入口 + 多臂封存 + 单进程 ab by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/226
* bench(p15): CI opt-in 冒烟 + artifact + .gitignore by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/221
* bench(p16): 文档收口 + 示例 overlay + JSDoc 还原 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/225
* bench(polish): README 接线现状刷新 + 去重复打印 + lock 边车忽略 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/227
* bench(p14): 运行时可开关的数据采集(设置「启动数据检测」)+ 面板落盘 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/229
* bench(test): 让 sweep 测试不依赖宿主机全局安装的 dsh by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/232
* bench(test): dry-run 路径比较用 POSIX 分隔符(修 Windows leg) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/233
* feat(bench): 把 #[173/#103/#183](https://github.com/173/#103//issues/183) 合成一套 bench + 数据面板(#205) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/228
* docs(credits): 记录 [#103]/#183 的共同署名(Co-authored-by) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/241
* feat(bench): Add benchmark to measure the plugin's token cost against a clean baseline by @Richeir in https://github.com/T-Auto/dsh-ops/pull/183
* fix(hide-official): 不再因范围外工具缺等价物而阻塞会话就绪(#238) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/242
* test(bench): add file-tool comparison harness and baseline fixtures by @OldLigant in https://github.com/T-Auto/dsh-ops/pull/103
* [0.3.2] F1/F2/F3/F6 真机四切片 + ≤1000 行拆分整合 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/254
* refactor(cli): 拆分 bin/dsh-ops.mjs(1071 行)为 lib/cli 子模块 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/246
* refactor(test): 拆分 test/shells.test.mjs(1710 行)为五个套件 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/248
* refactor(shells): 拆分 lib/shells.js(1498 行)为 lib/shells/* 子模块 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/250
* refactor(build): 拆分 scripts/build-platform-packages.mjs(1535 行)为模块 by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/252
* build(deps): bump windows-sys from 0.59.0 to 0.61.2 in /native by @dependabot[bot] in https://github.com/T-Auto/dsh-ops/pull/188
* build(deps): bump the actions group across 1 directory with 5 updates by @dependabot[bot] in https://github.com/T-Auto/dsh-ops/pull/202
* fix(file): refuse before the update sidecar, and document the credential fence (#240) by @WTStarMark in https://github.com/T-Auto/dsh-ops/pull/244
* fix(shell): pwsh 接管改为原地写 volatile 引用,不再重挂 pwsh-sandbox 行(#29 [#104] [#129]) by @little3tar in https://github.com/T-Auto/dsh-ops/pull/154
* fix(shell): session workdir and verified backlog integration by @Y-fyan in https://github.com/T-Auto/dsh-ops/pull/197
* fix(hide-official): integrate the explicit takeover scope follow-up by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/255
* docs: finish inspect capability cleanup and pin routing claims by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/256
* fix(file): SDK types, honest grep pages and compact model output by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/259
* feat(settings): [14b/16] add optional host configuration pages by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/283
* feat(documents): [15b/16] add bounded DOCX paragraph readers by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/285
* feat(documents): [15d/16] add bounded PDF text readers by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/287
* refactor(types): [16a/16] complete strict TypeScript source migration by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/288
* test(bench): [16b/16] verify acceptance and preserve Native source fidelity by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/289
* chore(release): [16c/16] prepare the 0.4.0 candidate and acceptance record by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/290
* build: [1/16] compile plugin sources into existing lib paths by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/264
* refactor: [2/16] centralize typed capability and outcome contracts by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/265
* refactor(native): [4a/16] split the kernel into workspace crates by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/266
* feat(native): [4b/16] version one-shot worker requests by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/267
* feat(file): [3/16] render bounded Native text results by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/268
* feat(config): [13/16] select verified official replacements by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/269
* feat(search): [5a/16] report coverage and validate continuations by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/270
* feat(file): [5b/16] batch file reads and atomic edits by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/271
* feat(results): [6a/16] add private session snapshot references by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/272
* feat(results): [6b/16] preserve oversized output in session references by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/273
* feat(results): [6c/16] bind storage and call budgets to live sessions by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/274
* feat(file): [6d/16] page owned result references in Native mode by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/275
* feat(ptc): [7/16] expose typed outcomes and load scoped SDKs on demand by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/276
* feat(discovery): [8/16] activate scoped Native tools on the next step by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/277
* feat(native): [9/16] slim the resident file surface by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/278
* feat(native): [10/16] deduplicate reads with current-context evidence by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/279
* feat(shell): [11/16] reuse host execution and make Bash optional by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/280
* refactor(shell): [12/16] leave PowerShell with its host by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/281
* feat(settings): [14a/16] preserve profiles and expose validated controls by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/282
* feat(documents): [15a/16] add bounded CSV and TSV readers by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/284
* feat(documents): [15c/16] validate bounded classic PDF containers by @Haoming9527 in https://github.com/T-Auto/dsh-ops/pull/286
* chore(release): 0.4.0 — integrate the full 16-step stack into main by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/293
* docs: DSH 工具注入分析合集 by @Nicholas023 in https://github.com/T-Auto/dsh-ops/pull/299
* feat(shell): restore the Windows Bash npm payload and enable the shell row everywhere (#301) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/307
* docs: require one CI run per pull request (#303) by @Thatgfsj in https://github.com/T-Auto/dsh-ops/pull/308
* refactor: rename 0.4.0 tools for consistent verb_noun naming by @Nicholas023 in https://github.com/T-Auto/dsh-ops/pull/305
* fix(profile): validate CLI launchers before dry-run by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/311
* feat(panel): serve captured reports with one command by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/314
* Update README.md by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/320
* fix(ptc): omit references for uncreated batch audit jobs by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/312
* fix(panel): preserve capture limits and completeness on recovery by @ccch1mneyyy in https://github.com/T-Auto/dsh-ops/pull/313
* fix(file): remove the update-lock sidecar on release (#319), prepare 0.4.1 by @T-Auto in https://github.com/T-Auto/dsh-ops/pull/327
## New Contributors
* @ccch1mneyyy made their first contribution in https://github.com/T-Auto/dsh-ops/pull/122
* @Richeir made their first contribution in https://github.com/T-Auto/dsh-ops/pull/183
* @OldLigant made their first contribution in https://github.com/T-Auto/dsh-ops/pull/103
* @dependabot[bot] made their first contribution in https://github.com/T-Auto/dsh-ops/pull/188
* @little3tar made their first contribution in https://github.com/T-Auto/dsh-ops/pull/154
* @Y-fyan made their first contribution in https://github.com/T-Auto/dsh-ops/pull/197
* @Nicholas023 made their first contribution in https://github.com/T-Auto/dsh-ops/pull/299
Full Changelog: https://github.com/T-Auto/dsh-ops/compare/v0.3.1...v0.4.1