{"_id":"@buddhilive/dsh-settings-file","name":"@buddhilive/dsh-settings-file","dist-tags":{"alpha":"0.1.2-alpha.3","latest":"0.1.2-alpha.3"},"versions":{"0.1.2-alpha.3":{"name":"@buddhilive/dsh-settings-file","description":"File-backed settings provider (settings.yaml) for the DeepSeek Harness","version":"0.1.2-alpha.3","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/Buddhilive/buddhi-ai-harness.git","directory":"packages/settings/settings-file"},"type":"module","main":"lib/index.js","types":"lib/types/index.d.ts","exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./invariant":{"types":"./lib/types/invariant.d.ts","default":"./lib/invariant.js"},"./src/*":"./src/*","./package.json":"./package.json"},"license":"MIT","peerDependencies":{"@deepseek-ai/cordis":"^4.0.2","@buddhilive/dsh-home-paths":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@buddhilive/dsh-atomic-write":"^0.1.2-alpha.3","@buddhilive/dsh-settings":"^0.1.2-alpha.3"},"dependencies":{"chokidar":"^4.0.3","yaml":"^2.9.0","@buddhilive/dsh-util-values":"^0.1.2-alpha.3","@deepseek-ai/schemastery":"^3.18.2"},"devDependencies":{"@deepseek-ai/cordis":"^4.0.2","@buddhilive/dsh-atomic-write":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@buddhilive/dsh-home-paths":"^0.1.2-alpha.3","@buddhilive/dsh-settings":"^0.1.2-alpha.3"},"_id":"@buddhilive/dsh-settings-file@0.1.2-alpha.3","bugs":{"url":"https://github.com/Buddhilive/buddhi-ai-harness/issues"},"homepage":"https://github.com/Buddhilive/buddhi-ai-harness#readme","_integrity":"sha512-oMU+9b5oVspsEWplViRomBXd7Nff9rm36Jj3jWnzW8iNDsHZnpUC0N4jSk4Ghj9sIhfZSTJxEIbyMDQZ8QboPw==","_resolved":"C:\\DevDojo\\Buddhi\\buddhi-ai-harness\\dist\\npm\\buddhilive-dsh-settings-file-0.1.2-alpha.3.tgz","_from":"file:C:/DevDojo/Buddhi/buddhi-ai-harness/dist/npm/buddhilive-dsh-settings-file-0.1.2-alpha.3.tgz","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-oMU+9b5oVspsEWplViRomBXd7Nff9rm36Jj3jWnzW8iNDsHZnpUC0N4jSk4Ghj9sIhfZSTJxEIbyMDQZ8QboPw==","shasum":"2e4e59540adf2b99b1b1dad3d55f7cceb79f2061","tarball":"https://registry.npmjs.org/@buddhilive/dsh-settings-file/-/dsh-settings-file-0.1.2-alpha.3.tgz","fileCount":9,"unpackedSize":41253,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDNBmhfp2thCHRuoYbw5kNrEriP0CntioKNJ3elVkTOzwIhAPdtcJYuB7Fjq7IM4b+hJ0dx8uGcz9gWQcK7bxLXCt9F"}]},"_npmUser":{"name":"buddhilive","email":"visitbudkavin@gmail.com"},"directories":{},"maintainers":[{"name":"buddhilive","email":"visitbudkavin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dsh-settings-file_0.1.2-alpha.3_1788165781209_0.4785009796148656"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-31T08:43:01.011Z","0.1.2-alpha.3":"2026-08-31T08:43:01.338Z","modified":"2026-08-31T08:43:01.628Z"},"maintainers":[{"name":"buddhilive","email":"visitbudkavin@gmail.com"}],"description":"File-backed settings provider (settings.yaml) for the DeepSeek Harness","homepage":"https://github.com/Buddhilive/buddhi-ai-harness#readme","repository":{"type":"git","url":"git+https://github.com/Buddhilive/buddhi-ai-harness.git","directory":"packages/settings/settings-file"},"bugs":{"url":"https://github.com/Buddhilive/buddhi-ai-harness/issues"},"license":"MIT","readme":"---\ndescription: \"面向用户与维护者的文件型设置提供方：选择、配置或排查 YAML/JSON 设置文档及其热重载。\"\nkind: \"package-reference\"\n---\n\n# @buddhilive/dsh-settings-file\n\n[English](README.md) | 中文\n\n## 概述\n\n`dsh-settings-file` 把所有 namespace 的用户设置保存在一个 YAML 或 JSON 文档中，默认是 harness home 下的 `settings.yaml`：用户可以直接编辑文档——变更实时生效——也可以经服务写入，后者会安全合并并发编辑。YAML 写入保留每个未触碰节点上的注释、锚点与排版，未加载插件所拥有的分节也绝不会被丢弃。启动时非法文档直接报错；运行中失败的热重载保留最后可用分节并告警，而不是拖垮进程。\n\n## 目录\n\n- [使用本包](#use-this-package)\n- [理解实现](#understand-the-implementation)\n- [进一步探索](#further-exploration)\n- [模型体验](#model-experience)\n- [已知限制与延期工作](#known-limitations-and-deferred-work)\n- [开发备注](#dev-note)\n\n-----\n\n<a id=\"use-this-package\"></a>\n## 使用本包\n\n当组合想要一份用户可编辑的设置文档时，挂载此提供方。常用路径是显式的：挂载提供方、经 `ctx.settings` 注册 namespace，然后让用户编辑文档或让配置界面经服务写入。\n\n### 何时选择\n\n把它当作默认的用户设置存储：一份用户可以在任意编辑器中打开的人类可读文档，变更无需重启即可生效。当文档中的注释与排版很重要时也选它，因为写入会保留它们。非文件存储（例如远程设置后端）不随本包提供；那需要另一个提供方。\n\n### 最小配置\n\n```yaml\n- name: '@buddhilive/dsh-settings-file'\n  config:\n    path: /absolute/path/to/settings.yaml\n```\n\n| 字段 | 默认值 | 含义 |\n|---|---|---|\n| `path` | `<harness home>/settings.yaml` | 设置文档路径；扩展名决定格式（`.yaml`、`.yml` 或 `.json`） |\n| `dshHome` | `$DSH_HOME` 或 `~/.dsh` | `path` 省略时使用的 harness home |\n| `watch` | `true` | 监听文档并热发布外部编辑 |\n| `debounceMs` | `100` | watcher 写入稳定窗口（毫秒） |\n\n生成的[配置目录](../../../docs/config-catalog.zh.md#buddhilivedsh-settings-file)是每个受支持字段及其 JSDoc 的穷尽式真源。\n\n### 编辑文档\n\n文档是 namespace 到用户分节的 YAML 或 JSON 映射。用户可以直接编辑：任何变更都会自动生效，删除文件则让所有 namespace 回到默认值与 `base`。存在但非法的文档在启动时使插件加载失败——提供方绝不会静默忽略或覆盖它。运行中不可读或不可解析的编辑只告警并保留最后可用分节，因此手改出错不会拖垮进程。\n\n### 经服务写入\n\n经 `ctx.settings` 的写入绝不会丢失并发变更：仍在途中的外部编辑、watcher 漏掉的变更或另一个进程的写入，都会在写入落地前并入文档。YAML 编辑是叶子级 diff：只设置变化的值、只删除被移除的键，因此每个未触碰节点以及每个被改键值对的键上的注释、锚点与排版都得以保留；被改的数组或其他非 map 值整体替换。JSON 文档重新序列化，无注释。若磁盘上的文档已变为非法，写入会明确报错，而不是覆盖用户的手工编辑。\n\n锁有 2 秒的获取期限，带指数退避；超时的竞争者不会移除现有锁，因为锁龄无法区分崩溃的所有者与被暂停但仍存活的写入方——遗留锁恢复须由操作者执行。文档以 `0600` 权限创建在仅属主可访问的 `0700` 目录下，并通过一个绝不跟随预埋符号链接的随机后缀临时文件原子替换。\n\n### 失败与恢复\n\n- 不支持的扩展名在加载时报错——格式由扩展名决定（`.yaml`、`.yml`、`.json`）。\n- 文档缺失即空存储；删除文件即回到该状态。\n- 运行中磁盘文档非法不会阻塞任何操作，但保留最后可用分节；写入拒绝覆盖它。\n- `prepareDocument()` 在原生编辑器打开前，把缺失的文档物化为空的仅属主可访问文件。\n\n-----\n\n<a id=\"understand-the-implementation\"></a>\n## 理解实现\n\n<details>\n<summary>实现细节——点击展开</summary>\n\n本节解释提供方背后的设计决策并指出实现它们的代码位置；可观察行为已在[使用本包](#use-this-package)中完整说明。\n\n### 设计理念\n\n- **一步显式默认化。** `resolveSpec(config)` 在一步内解析文件名、格式、watch 标志与防抖窗口，因此绕过 Schemastery 规范化的程序化构造也得到同样的默认值。\n- **启动明确报错，重载保留最后可用值。** 存在但非法的文档使插件加载失败；运行中不可读或不可解析的编辑只告警并保留最后可用分节。\n- **每次写入都是读-改-写。** persist 先从磁盘对账并把任何差异发布进 seam，再基于这份新鲜文本渲染，因此写入绝不会复活陈旧文档或丢掉未观察到的同级分节。\n- **写入持有跨进程写锁。** 读-渲染-rename 流程在以 `wx` 创建的同级 `<file>.lock` 保护下运行，带指数退避与 2 秒的获取期限；读取方从不取锁，因为 rename 提交是原子的。\n- **YAML 编辑是叶子级 diff。** 只设置变化的值、只删除被移除的键，保留未触碰节点上的注释、锚点与排版。\n- **重载与写入共享一条操作链。** watcher 刷新与来自各 namespace 队列的 persist 按队列顺序逐个执行；每次渲染都基于上一次操作提交后的文本。\n- **按内容抑制自写。** 提供方缓存最后可用文本；watcher 事件内容与缓存相同（含自己的写入）即为 no-op。\n\n### 源码地图\n\n| 文件 | 职责 |\n|---|---|\n| [`src/index.ts`](src/index.ts) | 提供方：spec 解析、加载/解析、写锁下的读-改-写、watcher 生命周期、YAML/JSON 渲染 |\n| [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件（无运行时不变式；文件往返、watcher 时序与原子写入行为由包测试证明，进程内提交关系归 `dsh-settings` 所有） |\n\n### 文档生命周期\n\n基类服务 init 在服务可注入前加载并发布文档；随后提供方启动 watcher，并在 ready 时对账一次，补上「初始读取与 watcher 生效之间写入的变更永不触发事件」的启动缺口。每个 watcher 事件与每次 persist 都排上同一条独占操作链。`reconcileFromDisk` 把磁盘文本与缓存比较，发布任何差异（缺失即空文档），只在解析失败时抛出，让每个调用方自行选择策略——重载告警并保留最后可用文档，写入明确报错。卸载先把提供方标记为已关闭，关闭 watcher，再等待所有已排队或进行中的操作完成，之后不再有任何发布。\n\n### 渲染路径\n\nYAML 渲染把缓存文本解析成可变的保留注释树，再对一个 namespace 施加叶子级编辑；JSON 渲染替换一个 namespace 键后以两个空格缩进重新序列化。在 Chokidar 打开目标之前，提供方对层级最深的现有祖先路径执行 realpath 解析，再拼回缺失的后缀，从而避免 Windows 在 libuv 内部混用 8.3 别名与长格式事件路径。\n\n</details>\n\n-----\n\n<a id=\"further-exploration\"></a>\n## 进一步探索\n\n当提供方级约定不够用时阅读以下页面。它们从 seam 约定逐步进入原子写入原语与穷尽式配置面。\n\n- [用户设置服务](../settings/README.zh.md)——namespace 注册、分层解析、写入与本提供方所供的事件。\n- [设置子系统参考](../../../docs/subsystems/settings.zh.md)——namespace、解析顺序、descriptor 与变更提交。\n- [设置包映射](../README.zh.md)——用户设置能力的两个包。\n- [原子写入](../../util/atomic-write/README.zh.md)——每次写入都使用的写锁与原子替换。\n- [主目录路径](../../util/home-paths/README.zh.md)——`$DSH_HOME` 解析与规范化监听路径。\n- [生成配置目录](../../../docs/config-catalog.zh.md#buddhilivedsh-settings-file)——每个受支持配置字段及其源声明。\n\n-----\n\n<a id=\"model-experience\"></a>\n## 模型体验\n\n间接生效：经由 `ctx.settings` 的消费方，它们拥有存储值所喂给的任何模型面行为；本文件提供方只存储并发布 namespace 分节，自身不注册任何模型面内容。\n\n#### KV Cache 影响\n\n无直接失效；请求前缀的任何变更均由消费方插件负责。\n\n## 已知限制与延期工作\n\n<a id=\"known-limitations-and-deferred-work\"></a>\n\n\n这些限制说明本提供方何时不合适或需要特别的运维注意。它们是当前包约束，不是任务积压。\n\n- **同 namespace 冲突仍是后写胜出**——写锁加读-改-写让并发写入者不会丢掉彼此的 namespace，但两个写入者编辑同一个 namespace 时仍以较后的写入为准；没有按值合并，也没有修订检查。\n- **漏掉的 watcher 事件在下一个信号前保持不可见**——读取从不重新 stat 文件，因此 watcher 漏报的变更只会在下一个事件、下一次写入或重启时被并入。\n- **注释保留仅限 YAML 且仅限 map 形状**——JSON 文档重新序列化，无注释，且被改数组内部的注释（或行内附着在被改标量值上的注释）随其所描述的值一同被换掉。\n- **无值间接引用**——分节存字面值；面向密钥的 `${env:VAR}` 式引用是暂缓实现的 seam 层功能。\n\n<a id=\"dev-note\"></a>\n### 开发备注\n\n<details>\n<summary>维护者的工作上下文——点击展开</summary>\n\n本开发备注是维护者的工作上下文：尚未决定的暂缓方向。它明确非权威——已发布的行为、限制与已接受的理由见上文各节与包代码。暂缓方向：`${env:VAR}` 式值间接引用是 seam 层功能——落地时应归属设置服务约定，而非本提供方。遗留锁恢复按设计仍是操作者动作，因为锁龄无法区分崩溃的所有者与被暂停但仍存活的写入方。\n\n</details>\n","readmeFilename":"README.zh.md","_rev":"1-055ff36e772076f59ce54797d06942e6"}