dominds 1.27.6 → 1.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/dialog.js +1 -1
  2. package/dist/docs/team_mgmt-toolset.md +21 -20
  3. package/dist/docs/team_mgmt-toolset.zh.md +21 -20
  4. package/dist/docs/txt-editing-tools.md +196 -122
  5. package/dist/docs/txt-editing-tools.zh.md +171 -97
  6. package/dist/llm/gen/failure-classifier.js +60 -11
  7. package/dist/llm/kernel-driver/drive.js +1 -1
  8. package/dist/tool.d.ts +2 -0
  9. package/dist/tool.js +52 -0
  10. package/dist/tools/app-reminders.js +1 -1
  11. package/dist/tools/builtins.js +31 -12
  12. package/dist/tools/prompts/team_mgmt.en.md +13 -29
  13. package/dist/tools/prompts/team_mgmt.zh.md +13 -29
  14. package/dist/tools/prompts/ws_mod/en/errors.md +45 -42
  15. package/dist/tools/prompts/ws_mod/en/index.md +10 -10
  16. package/dist/tools/prompts/ws_mod/en/principles.md +27 -34
  17. package/dist/tools/prompts/ws_mod/en/scenarios.md +42 -29
  18. package/dist/tools/prompts/ws_mod/en/tools.md +43 -46
  19. package/dist/tools/prompts/ws_mod/zh/errors.md +45 -42
  20. package/dist/tools/prompts/ws_mod/zh/index.md +10 -10
  21. package/dist/tools/prompts/ws_mod/zh/principles.md +27 -34
  22. package/dist/tools/prompts/ws_mod/zh/scenarios.md +42 -29
  23. package/dist/tools/prompts/ws_mod/zh/tools.md +42 -45
  24. package/dist/tools/prompts/ws_mod.en.md +77 -47
  25. package/dist/tools/prompts/ws_mod.zh.md +77 -47
  26. package/dist/tools/team_mgmt.d.ts +7 -6
  27. package/dist/tools/team_mgmt.js +379 -220
  28. package/dist/tools/txt.d.ts +20 -9
  29. package/dist/tools/txt.js +2365 -1880
  30. package/dist/utils/taskdoc.js +2 -2
  31. package/package.json +5 -5
  32. package/webapp/dist/assets/{main-NXVX2KTO.js → main-YWP5PWOM.js} +62 -1
  33. package/webapp/dist/assets/{main-NXVX2KTO.js.map → main-YWP5PWOM.js.map} +4 -4
  34. package/webapp/dist/index.html +1 -1
package/dist/dialog.js CHANGED
@@ -649,7 +649,7 @@ class Dialog {
649
649
  visibleReminders.sort(tool_1.compareReminderDisplayOrder);
650
650
  return visibleReminders.map((r) => ({
651
651
  content: r.content,
652
- meta: r.meta,
652
+ meta: (0, tool_1.serializeReminderContentMeta)(r),
653
653
  reminder_id: r.id,
654
654
  renderRevision: (0, tool_1.computeReminderRenderRevision)(r),
655
655
  echoback: (0, tool_1.reminderEchoBackEnabled)(r),
@@ -109,26 +109,27 @@ The `team_mgmt` toolset mirrors a minimal subset of `fs`/`txt`, but **hard-scope
109
109
 
110
110
  Recommended tools (names are suggestions; use `snake_case` to match existing tools):
111
111
 
112
- | Tool name | Based on | Purpose | Default allowlist scope |
113
- | -------------------------------------- | -------- | --------------------------------------------------------------------------------- | ----------------------- |
114
- | `team_mgmt_list_dir` | `fs` | List directories/files under `.minds/` | `.minds/**` |
115
- | `team_mgmt_read_file` | `txt` | Read a text file under `.minds/` | `.minds/**` |
116
- | `team_mgmt_create_new_file` | `txt` | Create a new file under `.minds/` (empty content allowed; refuses overwrite) | `.minds/**` |
117
- | `team_mgmt_overwrite_entire_file` | `txt` | Overwrite an existing file under `.minds/` (guarded exception path) | `.minds/**` |
118
- | `team_mgmt_prepare_file_range_edit` | `txt` | Prepare a single-file edit by line range under `.minds/` (returns a diff hunk id) | `.minds/**` |
119
- | `team_mgmt_prepare_file_append` | `txt` | Prepare an append-to-EOF edit under `.minds/` (returns a diff hunk id) | `.minds/**` |
120
- | `team_mgmt_prepare_file_insert_after` | `txt` | Prepare inserting after an anchor under `.minds/` (returns a diff hunk id) | `.minds/**` |
121
- | `team_mgmt_prepare_file_insert_before` | `txt` | Prepare inserting before an anchor under `.minds/` (returns a diff hunk id) | `.minds/**` |
122
- | `team_mgmt_prepare_file_block_replace` | `txt` | Prepare a block replace between anchors under `.minds/` (returns a diff hunk id) | `.minds/**` |
123
- | `team_mgmt_apply_file_modification` | `txt` | Apply a planned modification by hunk id under `.minds/` | `.minds/**` |
124
- | `team_mgmt_mk_dir` | `fs` | Create directories under `.minds/` | `.minds/**` |
125
- | `team_mgmt_move_file` | `fs` | Move/rename files under `.minds/` | `.minds/**` |
126
- | `team_mgmt_move_dir` | `fs` | Move/rename directories under `.minds/` | `.minds/**` |
127
- | `team_mgmt_rm_file` | `fs` | Delete files under `.minds/` | `.minds/**` |
128
- | `team_mgmt_rm_dir` | `fs` | Delete directories under `.minds/` | `.minds/**` |
129
- | `team_mgmt_validate_priming_scripts` | new | Validate path constraints and script format under `.minds/priming/**.md` | `.minds/**` |
130
- | `team_mgmt_validate_team_cfg` | new | Validate `.minds/team.yaml` and publish issues to the Problems panel | `.minds/**` |
131
- | `man({ "toolsetId": "team_mgmt" })` | builtin | Handbook entrypoint for the `team_mgmt` toolset (see below) | N/A |
112
+ | Tool name | Based on | Purpose | Default allowlist scope |
113
+ | -------------------------------------- | -------- | ---------------------------------------------------------------------------- | ----------------------- |
114
+ | `team_mgmt_list_dir` | `fs` | List directories/files under `.minds/` | `.minds/**` |
115
+ | `team_mgmt_read_file` | `txt` | Read a text file under `.minds/` | `.minds/**` |
116
+ | `team_mgmt_create_new_file` | `txt` | Create a new file under `.minds/` from content or pad (refuses overwrite) | `.minds/**` |
117
+ | `team_mgmt_overwrite_entire_file` | `txt` | Overwrite an existing file under `.minds/` from content or pad (guarded) | `.minds/**` |
118
+ | `team_mgmt_file_range_edit` | `txt` | Directly write a single-file line range under `.minds/` from content or pad | `.minds/**` |
119
+ | `team_mgmt_file_append` | `txt` | Append to a file under `.minds/` directly | `.minds/**` |
120
+ | `team_mgmt_file_insert_after` | `txt` | Insert after an anchor under `.minds/` directly | `.minds/**` |
121
+ | `team_mgmt_file_insert_before` | `txt` | Insert before an anchor under `.minds/` directly | `.minds/**` |
122
+ | `team_mgmt_file_block_replace` | `txt` | Replace an anchor-delimited block under `.minds/` directly | `.minds/**` |
123
+ | `team_mgmt_prepare_occurrence_replace` | `txt` | Prepare a literal occurrence replacement under `.minds/`, aimed at batch use | `.minds/**` |
124
+ | `team_mgmt_apply_occurrence_replace` | `txt` | Apply a prepared literal occurrence replacement plan under `.minds/` | `.minds/**` |
125
+ | `team_mgmt_mk_dir` | `fs` | Create directories under `.minds/` | `.minds/**` |
126
+ | `team_mgmt_move_file` | `fs` | Move/rename files under `.minds/` | `.minds/**` |
127
+ | `team_mgmt_move_dir` | `fs` | Move/rename directories under `.minds/` | `.minds/**` |
128
+ | `team_mgmt_rm_file` | `fs` | Delete files under `.minds/` | `.minds/**` |
129
+ | `team_mgmt_rm_dir` | `fs` | Delete directories under `.minds/` | `.minds/**` |
130
+ | `team_mgmt_validate_priming_scripts` | new | Validate path constraints and script format under `.minds/priming/**.md` | `.minds/**` |
131
+ | `team_mgmt_validate_team_cfg` | new | Validate `.minds/team.yaml` and publish issues to the Problems panel | `.minds/**` |
132
+ | `man({ "toolsetId": "team_mgmt" })` | builtin | Handbook entrypoint for the `team_mgmt` toolset (see below) | N/A |
132
133
 
133
134
  Notes:
134
135
 
@@ -87,26 +87,27 @@
87
87
 
88
88
  推荐工具(名称是建议;使用 `snake_case` 以匹配现有工具):
89
89
 
90
- | 工具名称 | 基于 | 用途 | 默认白名单作用域 |
91
- | -------------------------------------- | ----- | ----------------------------------------------------------- | ---------------- |
92
- | `team_mgmt_list_dir` | `fs` | 列出 `.minds/` 下的目录/文件 | `.minds/**` |
93
- | `team_mgmt_read_file` | `txt` | 读取 `.minds/` 下的文本文件 | `.minds/**` |
94
- | `team_mgmt_create_new_file` | `txt` | 在 `.minds/` 下创建新文件(允许空内容;拒绝覆写) | `.minds/**` |
95
- | `team_mgmt_overwrite_entire_file` | `txt` | 覆写 `.minds/` 下的现有文件(受保护的异常路径) | `.minds/**` |
96
- | `team_mgmt_prepare_file_range_edit` | `txt` | 准备在 `.minds/` 下进行单文件行范围编辑(返回差异 hunk id) | `.minds/**` |
97
- | `team_mgmt_prepare_file_append` | `txt` | 准备在 `.minds/` 下进行追加到 EOF 编辑(返回差异 hunk id) | `.minds/**` |
98
- | `team_mgmt_prepare_file_insert_after` | `txt` | 准备在 `.minds/` 下的锚点后插入(返回差异 hunk id) | `.minds/**` |
99
- | `team_mgmt_prepare_file_insert_before` | `txt` | 准备在 `.minds/` 下的锚点前插入(返回差异 hunk id) | `.minds/**` |
100
- | `team_mgmt_prepare_file_block_replace` | `txt` | 准备在 `.minds/` 下的锚点之间进行块替换(返回差异 hunk id) | `.minds/**` |
101
- | `team_mgmt_apply_file_modification` | `txt` | 通过 hunk id 在 `.minds/` 下应用计划的修改 | `.minds/**` |
102
- | `team_mgmt_mk_dir` | `fs` | `.minds/` 下创建目录 | `.minds/**` |
103
- | `team_mgmt_move_file` | `fs` | 移动/重命名 `.minds/` 下的文件 | `.minds/**` |
104
- | `team_mgmt_move_dir` | `fs` | 移动/重命名 `.minds/` 下的目录 | `.minds/**` |
105
- | `team_mgmt_rm_file` | `fs` | 删除 `.minds/` 下的文件 | `.minds/**` |
106
- | `team_mgmt_rm_dir` | `fs` | 删除 `.minds/` 下的目录 | `.minds/**` |
107
- | `team_mgmt_validate_priming_scripts` | 新建 | 校验 `.minds/priming/**.md` 的路径约束与脚本格式 | `.minds/**` |
108
- | `team_mgmt_validate_team_cfg` | 新建 | 验证 `.minds/team.yaml` 并将问题发布到问题面板 | `.minds/**` |
109
- | `man({ "toolsetId": "team_mgmt" })` | 内置 | `team_mgmt` 工具集的手册入口(见下文) | N/A |
90
+ | 工具名称 | 基于 | 用途 | 默认白名单作用域 |
91
+ | -------------------------------------- | ----- | --------------------------------------------------------- | ---------------- |
92
+ | `team_mgmt_list_dir` | `fs` | 列出 `.minds/` 下的目录/文件 | `.minds/**` |
93
+ | `team_mgmt_read_file` | `txt` | 读取 `.minds/` 下的文本文件 | `.minds/**` |
94
+ | `team_mgmt_create_new_file` | `txt` | 用 content 或 pad 在 `.minds/` 下创建新文件 | `.minds/**` |
95
+ | `team_mgmt_overwrite_entire_file` | `txt` | 用 content 或 pad 覆写 `.minds/` 下的现有文件 | `.minds/**` |
96
+ | `team_mgmt_file_range_edit` | `txt` | content 或 pad 直接按行号范围写入 `.minds/` 文件 | `.minds/**` |
97
+ | `team_mgmt_file_append` | `txt` | 直接在 `.minds/` 下文件末尾追加内容 | `.minds/**` |
98
+ | `team_mgmt_file_insert_after` | `txt` | 直接在 `.minds/` 下锚点后插入内容 | `.minds/**` |
99
+ | `team_mgmt_file_insert_before` | `txt` | 直接在 `.minds/` 下锚点前插入内容 | `.minds/**` |
100
+ | `team_mgmt_file_block_replace` | `txt` | 直接替换 `.minds/` 下锚点限定的块内容 | `.minds/**` |
101
+ | `team_mgmt_prepare_occurrence_replace` | `txt` | 规划 `.minds/` 下字面量 occurrence 替换,偏向多点批量用途 | `.minds/**` |
102
+ | `team_mgmt_apply_occurrence_replace` | `txt` | 应用 `.minds/` 下已规划的字面量 occurrence 替换 plan | `.minds/**` |
103
+ | `team_mgmt_mk_dir` | `fs` | `.minds/` 下创建目录 | `.minds/**` |
104
+ | `team_mgmt_move_file` | `fs` | 移动/重命名 `.minds/` 下的文件 | `.minds/**` |
105
+ | `team_mgmt_move_dir` | `fs` | 移动/重命名 `.minds/` 下的目录 | `.minds/**` |
106
+ | `team_mgmt_rm_file` | `fs` | 删除 `.minds/` 下的文件 | `.minds/**` |
107
+ | `team_mgmt_rm_dir` | `fs` | 删除 `.minds/` 下的目录 | `.minds/**` |
108
+ | `team_mgmt_validate_priming_scripts` | 新建 | 校验 `.minds/priming/**.md` 的路径约束与脚本格式 | `.minds/**` |
109
+ | `team_mgmt_validate_team_cfg` | 新建 | 验证 `.minds/team.yaml` 并将问题发布到问题面板 | `.minds/**` |
110
+ | `man({ "toolsetId": "team_mgmt" })` | 内置 | `team_mgmt` 工具集的手册入口(见下文) | N/A |
110
111
 
111
112
  注意:
112
113
 
@@ -1,15 +1,15 @@
1
1
  ---
2
- title: Text Editing Tools (ws_mod) — Design Doc
2
+ title: 文本编辑工具(ws_mod)— 设计文档
3
3
  status: implemented
4
- updated: 2026-01-24
4
+ updated: 2026-06-12
5
5
  ---
6
6
 
7
7
  # 文本编辑工具(ws_mod)设计文档(以当前实现为准)
8
8
 
9
- Chinese version: [中文版](./txt-editing-tools.zh.md)
9
+ 英文版:[English](./txt-editing-tools.md)
10
10
 
11
11
  > 中文语义为准;英文段落仅为同步摘要(由中文派生)。
12
- > 本文是“整体/综合”设计文档;运行时会把相同层级的综合指南注入到 `ws_mod` toolset 的系统提示里,因此每个工具自身的 `usageDescriptionI18n` 只保留“本工具接口契约”,不再重复综合工作流与大量示例。
12
+ > 本文是"整体/综合"设计文档;运行时会把相同层级的综合指南注入到 `ws_mod` toolset 的系统提示里,因此每个工具自身的 `usageDescriptionI18n` 只保留"本工具接口契约",不再重复综合工作流与大量示例。
13
13
 
14
14
  ## 0. 当前状态与实现入口
15
15
 
@@ -19,45 +19,54 @@ Chinese version: [中文版](./txt-editing-tools.zh.md)
19
19
  - toolset 元信息(含 prompt):`dominds/main/tools/builtins.ts`、`dominds/main/tools/registry.ts`、`dominds/main/tools/prompts/*`
20
20
  - prompt 注入机制:`dominds/main/tools/registry.ts`、`dominds/main/minds/load.ts`
21
21
 
22
- ## 1. 背景:为什么要“prepare-first + apply”
22
+ ## 1. 背景:为什么从 prepare-first 调整为 direct edit + pad source
23
23
 
24
- 历史上文本编辑工具存在“直接写入 vs 先 plan 再 apply”等多套心智并存,导致:
24
+ 历史上文本编辑工具存在"直接写入 vs 先 plan 再 apply"等多套心智并存,导致:
25
25
 
26
- - agent 在低注意力状态下容易“误写”或难以复核(缺少 diff/evidence)。
27
- - prepare→apply 之间存在竞态:同一条消息中工具并行执行,可能出现“prepare 基于旧文件,但另一工具已写入”的时序问题。
26
+ - agent 在低注意力状态下容易"误写"或难以复核(缺少 diff/evidence)。
27
+ - prepare→apply 之间存在竞态:同一条消息中工具并行执行,可能出现"prepare 基于旧文件,但另一工具已写入"的时序问题。
28
28
  - apply 入口分裂,学习成本高、回归成本高。
29
29
 
30
- 因此统一为:
30
+ 第一版统一为 prepare-first + single apply 后,安全性有所提升,但大文本/单点范围编辑暴露出新问题:
31
31
 
32
- - **prepare-first**:所有增量编辑先规划(输出可审阅 diff + evidence + hunk_id)。
33
- - **single apply**:所有计划类编辑仅通过 `apply_file_modification({ "hunk_id": "<hunk_id>" })` 落盘。
32
+ - 单个确定范围的编辑被迫拆成 prepare/apply 两步,交互拖沓。
33
+ - 预览正文与 diff 容易把大块内容反复注入历史,尤其是 LLM 已经在 pad 中精修好正文时。
34
+ - 误改防护的主要收益实际集中在"目标不确定/多 occurrence/锚点匹配"类场景;确定行号范围反而更适合一步写入。
35
+
36
+ 因此当前统一为:
37
+
38
+ - **direct range edit**:精确行号范围优先用 `file_range_edit` 一步写入;默认 YAML-only/redacted,不回显正文或 diff。
39
+ - **direct single-block edit**:末尾追加、锚点插入、锚点块替换也直接写入,分别使用 `file_append`、`file_insert_after` / `file_insert_before`、`file_block_replace`。
40
+ - **batch occurrence replace**:同一字面量多点批量替换保留 `prepare_occurrence_replace` → `apply_occurrence_replace` 两步流程;单点也可成功生成 plan,但结果会返回 `notice: NOT_MULTI_OCCURRENCE`,提示通常应改用 direct file 工具。
41
+ - **preview as display option**:需要审阅时显式 `preview/show_diff`,不再为单块编辑创建 hunk/apply 流程。
34
42
  - **移除旧工具**:`append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace` 已彻底删除(无 alias、无兼容层)。
35
43
 
36
44
  ## 2. 目标与非目标
37
45
 
38
46
  ### 2.1 目标
39
47
 
40
- - 把增量编辑统一为:`prepare_*` `apply_file_modification`。
41
- - 提供可复核输出:YAML summary + evidence(plan)/apply_evidence(apply) + unified diff
42
- - 明确并发/时序约束:避免在同一条消息中把 prepare apply 混在一起。
43
- - 给出稳定的失败模式与下一步建议(尤其是锚点歧义与 apply rejected)。
48
+ - 把确定行号范围编辑统一为:`file_range_edit` 直接写入,支持 inline content 与 pad source。
49
+ - 把单块末尾追加/锚点插入/锚点块替换统一为 direct 工具,支持 inline content pad source
50
+ - prepare/apply 的设计中心收敛到多 occurrence 批量字面量替换:`prepare_occurrence_replace` / `apply_occurrence_replace`。不再技术硬拦单 occurrence,但成功结果会返回 `notice: NOT_MULTI_OCCURRENCE` 做用法提醒。
51
+ - 提供可复核输出:direct 工具默认 YAML-only;显式 `preview/show_diff` 才输出 diff;pad-sourced 写入默认 redacted,避免回显大块正文。
52
+ - 明确并发/时序约束:同一文件的写入工具在进程内串行化。
53
+ - 给出稳定的失败模式与下一步建议(尤其是锚点歧义)。
44
54
 
45
55
  ### 2.2 非目标
46
56
 
47
57
  - 不做复杂 patch DSL(仍以 unified diff 为主)。
48
- - 不保证跨进程/重启的 hunk 持久化(当前 hunk registry 为进程内内存 + TTL=1h)。
49
- - 不承诺“自动格式化/自动空行风格对齐”;只做可观测(style_warning)与最小必要规范化(EOF 换行)。
58
+ - 不承诺"自动格式化/自动空行风格对齐";只做可观测(style_warning)与最小必要规范化(EOF 换行)。
50
59
 
51
- ## 3. Toolset Prompt(i18n)设计
60
+ ## 3. 工具集提示(i18n)设计
52
61
 
53
62
  ### 3.1 需求
54
63
 
55
- - “综合使用指南/示例/工作流”应由 toolset 提供(因为它是组合能力,不属于单一工具)。
64
+ - "综合使用指南/示例/工作流"应由 toolset 提供(因为它是组合能力,不属于单一工具)。
56
65
  - 单个工具的 `usageDescriptionI18n` 只需要描述该工具自身的接口契约与最小注意事项。
57
66
 
58
67
  ### 3.2 机制(当前实现)
59
68
 
60
- - `ToolsetMeta` 支持 toolset 级 prompt(`I18nText`,目前 `en|zh`),用于 **man\_<toolset> 手册** 的按需读取(不是自动注入到 system prompt)。
69
+ - `ToolsetMeta` 支持 toolset 级 prompt(`I18nText`,目前 `en|zh`),用于 **man\_<toolset> 手册** 的按需读取(不自动注入 system prompt)。
61
70
  - 当前实现使用 `promptFilesI18n`:把综合指南放到 markdown 文件中,**仅在调用 man\_<toolset> 时读取**(no cache)。
62
71
  - `ws_mod`:
63
72
  - `dominds/main/tools/prompts/ws_mod.zh.md`
@@ -72,29 +81,33 @@ Chinese version: [中文版](./txt-editing-tools.zh.md)
72
81
 
73
82
  ### 4.2 原始写入工具(例外)
74
83
 
75
- - `create_new_file`(函数工具):创建新文件(不走 prepare/apply),允许空内容。
76
- 设计定位:解决“创建空文件/新文件”不应被迫走增量编辑;同时避免误用 `overwrite_entire_file`(它的语义是覆盖既有文件)。
84
+ - `create_new_file`(函数工具):创建新文件,允许空内容。
85
+ 设计定位:解决"创建空文件/新文件"不应被迫走增量编辑;同时避免误用 `overwrite_entire_file`(它的语义是覆盖既有文件)。
86
+ 来源:小正文可直接传 `content`;大正文优先先进入 pad,再传 `pad_id/pad_range`。
77
87
  行为:若目标已存在则拒绝(`FILE_EXISTS`/`NOT_A_FILE`);不存在则创建父目录并写入内容。
78
- 规范化:若 `content` 非空且末尾缺少 `\n`,则补齐并在输出中显示 `normalized_trailing_newline_added=true`。
79
- 输出:成功/失败均为 YAML(便于脚本化与回归)。
88
+ 规范化:若来源正文非空且末尾缺少 `\n`,则补齐并在输出中显示 `normalized_trailing_newline_added=true`。
89
+ 输出:成功/失败均为 YAML;pad 来源输出不回显正文,只返回 pad 元信息与 hash。
80
90
 
81
- - `overwrite_entire_file`(函数工具):整文件覆盖写入(**不走 prepare/apply**)。
91
+ - `overwrite_entire_file`(函数工具):整文件覆盖写入(直接写盘)。
82
92
  使用建议:先用 `read_file` 获取 `total_lines/size_bytes` 作为 `known_old_total_lines/known_old_total_bytes` 的对账输入。
83
- 设计定位:用于“新内容很小(例如 <100 行)”或“明确为重置/生成物”的场景;其他情况优先 prepare/apply。
93
+ 设计定位:用于"新内容很小(例如 <100 行)"或"明确为重置/生成物"的场景;大正文优先先进入 pad,再传 `pad_id/pad_range`。
94
+ 来源:小正文可直接传 `content`;大正文优先传 `pad_id/pad_range`。
84
95
  护栏(强制):必须提供 `known_old_total_lines/known_old_total_bytes`(旧文件快照)才允许执行;若对账不匹配则拒绝覆盖。
85
96
  `content_format`:可选文本提示,任意非空字符串都可接受(例如 `yaml` / `toml` / `json` / `markdown`)。
86
- 护栏(默认拒绝):若正文疑似 diff/patch,且未显式声明 `content_format=diff|patch`,则默认拒绝并引导改用 prepare/apply(避免把 patch 文本误写进文件)。
87
- 限制:不负责创建文件;创建空文件/新文件请用 `create_new_file`;创建“带非空初始内容”的新文件可用 `prepare_file_append create=true` → `apply_file_modification`。
97
+ 护栏(默认拒绝):若正文疑似 diff/patch,且未显式声明 `content_format=diff|patch`,则默认拒绝;实际编辑应使用 direct edit 工具,只有要把 patch 文本按字面量写入时才声明 diff/patch。
98
+ 限制:不负责创建文件;创建空文件/新文件请用 `create_new_file`。
88
99
 
89
- ### 4.3 增量编辑(prepare-first
100
+ ### 4.3 增量编辑(direct edit
90
101
 
91
- - `prepare_file_range_edit`:按行号范围预览 replace/delete/append(append 通过 `N~` 且 `N=(last_line+1)`)。
92
- - `prepare_file_append`:预览追加到 EOF(可选 `create=true|false`)。
93
- - `prepare_file_insert_after` / `prepare_file_insert_before`:按锚点行预览插入(prepare 阶段严格处理歧义;锚点多次出现必须指定 `occurrence`)。
94
- - `prepare_file_block_replace`:按 start/end 锚点预览块替换(可配置 `include_anchors` / `require_unique` / `strict` / `occurrence` 等)。
102
+ - `file_range_edit`:按精确行号范围直接 replace/delete/append(append 通过 `N~` 且 `N=(last_line+1)`),支持 `content` 或 `pad_id/pad_range` 作为来源;默认不输出 diff,不回显正文。
103
+ - `file_append`:直接追加到 EOF,可选 `create=true|false`,支持 `content` 或 `pad_id/pad_range`。
104
+ - `file_insert_after` / `file_insert_before`:按锚点行直接插入;锚点多次出现必须指定 `occurrence`;支持 `content` 或 `pad_id/pad_range`。
105
+ - `file_block_replace`:按 start/end 锚点直接块替换(可配置 `include_anchors` / `require_unique` / `strict` / `occurrence` 等),支持 `content` 或 `pad_id/pad_range`。
95
106
  - `include_anchors=true`(默认):保留 start/end anchor 行,仅替换两者之间的内容。
96
107
  - `include_anchors=false`:替换范围包含 start/end anchor 行(会删除 anchor 行并以新内容替换)。
97
- - `apply_file_modification`:唯一 apply,能应用来自上述任意 `prepare_*` hunk(range/append/insert/block_replace)。
108
+ - `prepare_occurrence_replace` / `apply_occurrence_replace`:单文件内的字面量 occurrence 替换,设计中心是多点同字面量批量替换。默认替换所有 occurrence,也可通过 `occurrence_indexes` 指定 1-based occurrence 列表;少于两个选中 occurrence 时不拒绝,但成功结果会返回 `notice: NOT_MULTI_OCCURRENCE`,提示单点通常使用 `file_range_edit` 或 `file_block_replace` 更清晰。apply 时若文件 hash 已变化,则拒绝并要求重新 prepare。
109
+ - `create_new_file` / `overwrite_entire_file` / `file_range_edit` / `file_append` / `file_insert_*` / `file_block_replace` 都支持 `content` 与 `pad_id/pad_range` 两类来源;小正文直供 `content`,大正文优先使用 pad 来源以减少重复历史注入。
110
+ - `pad_write` / `pad_load_file_range` / `pad_copy` / `pad_move` 支持轻量自然语言元信息:`intent`(当前任务用途)、`completion`(何时可删除/采纳/废弃)、`source_note`(来源说明)、`delete_when_done`(默认 true)。这些字段服务于提醒项可读性,不是文件绑定或生命周期调度系统。
98
111
 
99
112
  ## 5. 关键并发约束与顺序建议
100
113
 
@@ -102,49 +115,29 @@ Chinese version: [中文版](./txt-editing-tools.zh.md)
102
115
 
103
116
  同一条消息中的多个工具调用会并行执行,互相不可见输出/写入。因此:
104
117
 
105
- - **prepare apply 必须分两条消息**(否则 apply 可能“看不到”本轮刚生成的 hunk)。
106
-
107
- ### 5.2 apply 的并发安全(当前实现)
108
-
109
- - 同一文件的多个 `apply_file_modification` 会在进程内按队列串行化(按 `createdAtMs`、再以 `hunkId` 作为 tie-breaker)。
110
- - 不同文件的 apply 可并行,不共享锁。
111
-
112
- ## 6. hunk registry 与生命周期
113
-
114
- ### 6.1 生命周期与所有权
115
-
116
- - 每个 plan hunk 带 TTL(输出 `expires_at_ms`)。
117
- - hunk 存储于进程内内存;进程重启后丢失。
118
- - prepare 结果在 apply 前不会落盘;此时再次读取文件仍只能看到旧内容。若想基于该结果继续下一笔修改,必须先 apply 当前 hunk,再重新 prepare。
119
- - `apply_file_modification` 会检查:
120
- - hunk 是否存在且未过期
121
- - hunk 是否由当前成员规划(`WRONG_OWNER` 拒绝)
122
- - 当前成员是否有写权限(`hasWriteAccess`)
118
+ - 若目标是精确行号范围,直接用 `file_range_edit`;若目标是单块追加/插入/替换,直接用对应 `file_*` 工具。
119
+ - 若目标是同一字面量的多处批量替换,先 `prepare_occurrence_replace` 检查候选,再 `apply_occurrence_replace` 应用。
120
+ - 需要审阅时显式 `preview/show_diff`。
123
121
 
124
- ### 6.2 “覆写同一规划”的规则(重要)
122
+ ### 5.2 写入并发安全(当前实现)
125
123
 
126
- 支持“带 `existing_hunk_id` 重新 plan 覆写”的工具与规则:
124
+ - 同一文件的多个 direct 写入会进入同一类队列串行化(按入队时间、再以内部 tie-breaker)。
125
+ - 不同文件的写入可并行,不共享锁。
127
126
 
128
- - `prepare_file_range_edit`:支持 `existing_hunk_id`,但该 id 必须已存在、归属当前成员、且模式匹配(不能拿别的 prepare 模式的 id 来覆写)。
129
- - `prepare_file_append` / `prepare_file_insert_after` / `prepare_file_insert_before`:同样支持 `existing_hunk_id` 覆写同模式预览。
130
- - `prepare_file_block_replace`:支持 `existing_hunk_id` 覆写同模式预览(同 owner / 同 kind;跨模式拒绝)。
131
- - 所有 plan 工具都**不允许自定义新 id**:只能通过“省略/清空 `existing_hunk_id`”来生成新规划;只有当你想覆写既有规划时才传入 `existing_hunk_id`。
132
-
133
- > 注意:有些 provider(例如 Codex)会要求函数工具的参数字段都“必填”(schema 全 required)。
134
- > 如果你用的是这类 provider,但语义上想表达“未指定/使用默认”,再用哨兵值表达“未指定”;否则(大多数 provider)**省略可选字段即可**:
127
+ > 注意:有些 provider(例如 Codex)会要求函数工具的参数字段都"必填"(schema required)。
128
+ > 如果你用的是这类 provider,但语义上想表达"未指定/使用默认",再用哨兵值表达"未指定";否则(大多数 provider)**省略可选字段即可**:
135
129
  >
136
- > - `existing_hunk_id: ""`:不覆写旧规划(生成新 hunk)。
137
130
  > - `occurrence: ""` 或 `0`:不指定 occurrence。
138
131
  > - `match: ""`:使用默认 `contains`(注意:`match` 是 match mode,不是要匹配的文本/正则)。
139
- > - `read_file({ range: "", max_lines: 0 })`:分别表示“不指定范围 / 使用默认 500 行”。
140
- > - `overwrite_entire_file({ content_format: "" })`:表示“未显式声明内容格式”(此时若正文强特征疑似 diff/patch 将默认拒绝写入);若显式提供任意非空标签(例如 `yaml`),工具会原样接受,但只有 `diff` / `patch` 具有放行 diff/patch 字面量的特殊语义。
141
- > - `ripgrep_*({ path: "", case: "", max_files: 0, max_results: 0 })`:分别表示“默认路径 '.' / 默认 smart-case / 使用默认上限”。
132
+ > - `read_file({ range: "", max_lines: 0 })`:分别表示"不指定范围 / 使用默认 500 行"。
133
+ > - `overwrite_entire_file({ content_format: "" })`:表示"未显式声明内容格式"(此时若正文强特征疑似 diff/patch 将默认拒绝写入);若显式提供任意非空标签(例如 `yaml`),工具会原样接受,但只有 `diff` / `patch` 具有放行 diff/patch 字面量的特殊语义。
134
+ > - `ripgrep_*({ path: "", case: "", max_files: 0, max_results: 0 })`:分别表示"默认路径 '.' / 默认 smart-case / 使用默认上限"。
142
135
 
143
136
  ## 7. 规范化策略(当前实现)
144
137
 
145
138
  ### 7.1 EOF 换行规范化(硬规则)
146
139
 
147
- 写入遵循“每行以 `\n` 结尾(包括最后一行)”:
140
+ 写入遵循"每行以 `\n` 结尾(包括最后一行)":
148
141
 
149
142
  - 若文件末尾无换行,写入前会补齐 `\n`(`normalized_file_eof_newline_added`)。
150
143
  - 若正文末尾无换行,写入前会补齐 `\n`(`normalized_content_eof_newline_added`)。
@@ -152,122 +145,203 @@ Chinese version: [中文版](./txt-editing-tools.zh.md)
152
145
 
153
146
  ### 7.2 空行风格(仅可观测)
154
147
 
155
- 对 append/insert,prepare 阶段会输出 `blankline_style` 与 `style_warning`,用于提示“可能产生双空行/粘行”等风险;当前不主动改变正文空行风格。
148
+ 对 append/insert,prepare 阶段会输出 `blankline_style` 与 `style_warning`,用于提示"可能产生双空行/粘行"等风险;当前不主动改变正文空行风格。
156
149
 
157
150
  ## 8. YAML 输出契约(以当前实现为准)
158
151
 
159
152
  > 目标:低注意力可扫读;稳定字段便于工具链/回归。
160
153
 
161
- ### 8.1 Plan(共同字段)
154
+ ### 8.1 Direct Range Edit
155
+
156
+ - `status: ok|error`
157
+ - `mode: file_range_edit`
158
+ - `preview: true|false`
159
+ - `path`
160
+ - `source: content|pad`
161
+ - `redacted: true|false`
162
+ - pad 来源时包含 `pad_id` / `pad_range` / `pad_hash` / `pad_selected_*`
163
+ - pad 来源成功输出还会补充 `pad_intent` / `pad_completion` / `pad_source_note` / `pad_delete_when_done` / `pad_cleanup_suggestion`,用于在文件写回节点提示是否应清理临时 pad。`preview: true` 时提示保留 pad;实际写入完成后,若 completion 条件已满足,应主动 `pad_delete`。
164
+ - `action: replace|delete|append`
165
+ - `range.input` / `range.applied.start|end`
166
+ - `lines.old|new|delta`
167
+ - `file.old_total_*` / `file.new_total_*` / `file.*_hash`
168
+ - `normalized.*`
169
+ - `summary`
170
+ - 只有 `show_diff=true` 时才追加 unified diff;这可能回显正文或 pad 内容。
171
+
172
+ ### 8.2 Direct 锚点/追加工具(共同字段)
162
173
 
163
174
  - `status: ok|error`
164
- - `mode: prepare_file_range_edit|prepare_file_append|prepare_file_insert_after|prepare_file_insert_before|prepare_file_block_replace`
175
+ - `mode: file_append|file_insert_after|file_insert_before|file_block_replace`
165
176
  - `path`
166
- - `hunk_id`、`expires_at_ms`
167
177
  - `action: replace|delete|append|insert|block_replace`
168
178
  - `normalized.*`(EOF 换行分析)
169
179
  - `summary`(1–2 句可扫读)
170
- - 紧随 YAML ` ```diff ` unified diff(审阅用)
180
+ - 只有 `show_diff=true` 时才追加 unified diff;这可能回显正文或 pad 内容。
171
181
 
172
- ### 8.2 Plan(按工具/动作的关键字段)
182
+ ### 8.3 Direct 锚点/追加工具(按动作的关键字段)
173
183
 
174
- - `prepare_file_range_edit`:
175
- - `range.input` / `range.resolved.start|end`
176
- - `lines.old|new|delta`
177
- - `evidence.before|range|after`
178
- - `prepare_file_append`:
184
+ - `file_append`:
179
185
  - `file_line_count_before|after`、`appended_line_count`
180
186
  - `blankline_style.file_trailing_blank_line_count` / `content_leading_blank_line_count`
181
187
  - `evidence_preview.before_tail|append_preview|after_tail`
182
- - `prepare_file_insert_*`:
188
+ - `file_insert_*`:
183
189
  - `position`、`anchor`、`match`
184
190
  - `candidates_count`、`occurrence_resolved`
185
191
  - `inserted_at_line`、`inserted_line_count`、`lines.old|new|delta`
186
192
  - `blankline_style.*`、`evidence_preview.*`
187
- - `prepare_file_block_replace`:
193
+ - `file_block_replace`:
188
194
  - `start_anchor` / `end_anchor` / `match`
189
195
  - `include_anchors` / `require_unique` / `strict`
190
196
  - `candidates_count` / `occurrence_resolved`
191
197
  - `block_range`、`replace_slice`、`lines.old|new|delta`
192
198
  - `evidence_preview.before_preview|old_preview|new_preview|after_preview`
193
199
 
194
- ### 8.3 Apply(共同字段)
195
-
196
- - `status`
197
- - `mode: apply_file_modification`
198
- - `path`、`hunk_id`
199
- - `action`
200
- - `context_match: exact|fuzz|rejected`
201
- - `apply_evidence`(必须)
202
- - `summary` - 紧随 YAML 的 unified diff(基于 apply 时“当前文件 + 解析到的目标位置”重算;若 `context_match=exact` 则与 plan diff 一致)
203
-
204
- ### 8.4 Apply(按动作的关键字段)
205
-
206
200
  - `append`:`append_range.start|end` + tail previews
207
201
  - `insert`:`position` / `anchor` / `inserted_at_line` / `inserted_line_count`
208
202
  - `replace|delete`(range):`applied_range.start|end` + `lines.*`
209
203
  - `block_replace`:`block_range` / `replace_slice` / `lines.*`
210
204
 
211
- ### 8.5 read_file / overwrite_entire_file(结构化头部)
205
+ ### 8.6 create_new_file / overwrite_entire_file(结构化输出)
212
206
 
213
207
  为提升可脚本化与回归稳定性:
214
208
 
215
209
  - `read_file` 输出开头包含 YAML header(随后是代码块正文),其中会给出:
216
210
  - `total_lines`(用于对账护栏:空文件为 0,可直接用于 `overwrite_entire_file.known_old_total_lines`)
217
- - `overwrite_entire_file` 的成功/失败输出均使用 YAML(便于程序化处理与重试)。
211
+ - `create_new_file` / `overwrite_entire_file` 的成功/失败输出均使用 YAML(便于程序化处理与重试)。
212
+ - 两者成功输出包含 `source: content|pad` 与 `redacted`;pad 来源还包含 `pad_id`、`pad_range`、`pad_hash`、`pad_selected_*`、`pad_intent`、`pad_completion`、`pad_source_note`、`pad_delete_when_done`、`pad_cleanup_suggestion`,不回显 pad 正文。
218
213
 
219
- 为提升可脚本化与回归稳定性:
214
+ ## 9. Scratch Pad 决策记录与阶段实现
220
215
 
221
- - `read_file` 输出开头包含 YAML header(随后是代码块正文),其中会给出:
222
- - `total_lines`(用于对账护栏:空文件为 0,可直接用于 `overwrite_entire_file.known_old_total_lines`)
223
- - `overwrite_entire_file` 的成功/失败输出均使用 YAML(便于程序化处理与重试)。
216
+ Scratch Pad ws_mod 的大文本编辑缓冲区,目标是减少 LLM 在多轮编辑中反复输出同一大块文本,也减少大块正文因小错反复重写的成本。它不是普通 reminder 的新用法,而是隶属于 ws_mod 的专用工具能力;底层可以复用 reminder 的可见性、持久化与生命周期提示。
217
+
218
+ ### 9.1 边界
219
+
220
+ - `add_reminder` / `update_reminder` / `delete_reminder` 保持现有语义和功能,不承接 pad 创建、修改或删除。
221
+ - pad 作为 `ws_mod` 专用对象,由 `pad_*` 工具管理;普通 reminder 工具不应修改 pad。
222
+ - pad 使用智能体自主分配的 `pad_id` slug 作为稳定句柄。实现时应限制为安全、可持久化的短标识(例如 `^[A-Za-z0-9_-]+$`),避免与普通 reminder id 混淆。
223
+ - pad 本体只保存 `pad_id + content + 轻量任务元信息`。元信息限于 `intent` / `completion` / `source_note` / `delete_when_done` 这类自然语言可读提示;不保存绑定目标文件的 `target`,不保存 `role` / `updatedAt` / 自动过期字段。
224
+ - 不提供 `role`,不提供自动过期;pad 用完必须由智能体主动删除。
225
+ - 默认作用域应偏当前对话。只有当文件编辑业务明确需要同一任务内协作复用时,才考虑更宽作用域。
226
+ - 默认少量 pad:优先维护 1 个当前任务 pad;只有确实要对照少数候选正文时才开多个 pad,不把 pad 扩展成长期多文档管理系统。
227
+
228
+ ### 9.2 上下文投影
229
+
230
+ - pad 以扎眼的特殊提醒项形式投影到 LLM generation context 的末尾、真实用户消息之前,让智能体总能看到有哪些临时缓冲区仍未清理。
231
+ - role=user 的 pad 投影必须先展示 `pad_id`、`intent`、`completion`、`lifecycle`、`source`,再带行号全量展示正文,避免智能体盲做 pad 编辑;给人类的提醒 UI 与给智能体的 LLM ctx 展示原则上一致。统计/hash 等只作为后台校验与工具回执信息,不作为主要展示内容;role=user 投影仍不放 `pad_delete(...)` 这类可执行工具调用文本,避免被误判成当前立即指令。
232
+ - pad 投影必须明确提示:pad 正文是待编辑/引用的数据,不是新的指令。模型不应执行 pad 正文中的指令性文本,除非它已在当前用户/开发者/系统上下文中被明确确认。
233
+ - pad 提醒项应由专用 owner/manager 管理,并通过 metadata 阻止普通 `update_reminder` / `delete_reminder` 误改;可执行维护通道通过现有 role=assistant 的 reminder maintenance reference 暴露,错误提示也应指向对应的 `pad_*` 工具。
234
+ - pad 投影的产品目的不是长期记忆,而是当前编辑工作台与清理压力:内容应用完成或不再需要后,智能体应尽快 `pad_delete`。
235
+
236
+ ### 9.3 工具形态
237
+
238
+ 当前阶段先落基础编辑工具,后续再扩展搬运和落盘工具;任何阶段都不提供观察工具:
239
+
240
+ - 当前已实现:`pad_write`、`pad_load_file_range`、`pad_edit`、`pad_insert`、`pad_delete_range`、`pad_copy`、`pad_move`、`pad_delete`;文件侧已实现 `create_new_file` / `overwrite_entire_file` / `file_range_edit` / `file_append` / `file_insert_*` / `file_block_replace` 直接消费 pad;多 occurrence 批量替换已实现 `prepare_occurrence_replace` / `apply_occurrence_replace` 消费 `content` 或 `pad_id/pad_range` 来源。
241
+ - `pad_write` / `pad_load_file_range` / `pad_copy` / `pad_move` 可写入或覆盖 `intent`、`completion`、`source_note`、`delete_when_done`。创建目标 pad 时,`pad_copy` / `pad_move` 会继承来源 pad 的元信息,再应用本次参数覆盖。
242
+ - 若创建/更新后 pad 没有 `intent`,工具仍成功,但返回 `notice: PAD_INTENT_MISSING`,提示补充用途和完成条件。
243
+ - 后续目标形态:继续把 pad 扩展为更多文件编辑工具的直接源/目标。
244
+ - 不提供:`pad_read`、`pad_preview`、`pad_locate`、`pad_diff`、`pad_stat`、`pad_list` 等会把 pad 内容或额外观察路径带回对话历史的工具。
245
+ - 文件编辑工具应能直接把 pad 当作源或目标:文件范围可装入 pad,`pad_load_file_range({ pad_id, path })` 省略 `range` 时默认装入全文件;pad 范围可作为 `create_new_file` / `overwrite_entire_file` / `file_range_edit` / `file_append` / `file_insert_*` / `file_block_replace` 的新内容;pad 之间可复制/剪切/移动文本。
246
+ - 文件工具使用 pad source 成功写入或预览时,会在输出里带出 pad 元信息摘要与 `pad_cleanup_suggestion`。这只是显式提醒,不自动删除;`preview: true` 时建议保留 pad,实际写入后若 completion 条件已满足则主动删除。
247
+ - pad 工具结果默认只返回操作是否成功与下一步提示,不回显大块正文,也不把统计信息当作主要展示;pad 正文的当前真源视图由提醒项全量展示。
248
+
249
+ ### 9.4 大文本入参的现实取舍
224
250
 
225
- ## 9. 错误与拒绝(稳定方向)
251
+ - 不能禁止 LLM 写出大块新内容;很多业务场景需要直接生成文案、代码或配置。
252
+ - `pad_write` / `pad_edit` / `pad_insert` 接收大文本时,这些正文仍会以函数调用参数形式进入持久历史;当前没有完美办法完全消除这类一次性成本。
253
+ - 设计目标不是让大文本从不进入持久上下文,而是避免同一大文本在后续编辑、搬运、应用阶段反复进入历史。
254
+ - 因此推荐路径是:必要时一次性写入 pad,之后尽量用 pad/file/pad 之间的句柄式搬运、`pad_copy` / `pad_move` 和 range edit 完成后续操作,最后主动删除 pad。
226
255
 
227
- ### 9.1 prepare 阶段(常见)
256
+ ## 10. Backlog(后两档,防遗忘)
257
+
258
+ - 第二档:继续扩展文件工具对 pad 的直接源/目标支持。已完成:`pad_load_file_range` 支持文件全量/范围写入 pad;`create_new_file` / `overwrite_entire_file` / `file_range_edit` / `file_append` / `file_insert_*` / `file_block_replace` 支持 `pad_id/pad_range` 作为来源,同时保留 `content` 直供。待做:将更多文件编辑工具的输出目标改为 pad 的变体。落地时仍保持"无 pad_read / 无观察工具"原则。
259
+ - 第三档:在使用数据稳定后,审视并瘦身文本编辑工具形状。`pad_edit` / `pad_insert` / `pad_delete_range` / `pad_copy` / `pad_move` 是否可以收敛为更少的 range operation,需要基于实际调用负担与错误模式再定;低价值或会引入歧义的合并先不做。
260
+
261
+ ## 11. 错误与拒绝(稳定方向)
262
+
263
+ ### 11.1 direct range edit 阶段(常见)
264
+
265
+ - `FILE_NOT_FOUND`:目标文件不存在;`file_range_edit` 不负责创建文件。
266
+ - `INVALID_RANGE`:行号范围非法或 append 位置不是 `last_line+1`。
267
+ - `NOT_A_FILE`:路径不是文件。
268
+ - `WRITE_FAILED`:写入阶段异常;输出会带失败摘要。
269
+
270
+ ### 11.2 direct single-block edit 阶段(常见)
228
271
 
229
272
  - `FILE_NOT_FOUND`:文件不存在(某些工具如 append 可用 `create=true` 处理)。
230
273
  - `CONTENT_REQUIRED`:正文为空但该工具需要正文(insert/append/block_replace)。
231
274
  - `ANCHOR_NOT_FOUND` / `ANCHOR_AMBIGUOUS`:锚点缺失或歧义(提示指定 occurrence 或换用更精确方法)。
232
275
  - `OCCURRENCE_OUT_OF_RANGE`:occurrence 超范围。
233
276
 
234
- ### 9.2 apply 阶段(常见)
277
+ ### 11.3 batch occurrence replace 阶段(常见)
235
278
 
236
- - `HUNK_NOT_FOUND`:hunk 过期/已应用/不存在。
237
- - `WRONG_OWNER`:hunk 非当前成员规划。
279
+ - `NOT_MULTI_OCCURRENCE`:成功结果里的用法提示,不是错误;表示只选中了单个 occurrence。单点编辑通常使用 `file_range_edit` 或 `file_block_replace`,多点同字面量替换使用 `prepare_occurrence_replace`。
280
+ - `OCCURRENCE_NOT_FOUND` / `OCCURRENCE_OUT_OF_RANGE`:字面量未找到,或 `occurrence_indexes` 超出范围。
281
+ - `FILE_CHANGED_SINCE_PREPARE`:prepare 后文件 hash 变化;拒绝 apply,需重新读取并重新 prepare。
238
282
 
239
- ## 10. 示例(copy/paste 可用)
283
+ ## 12. 示例(copy/paste 可用)
240
284
 
241
- - 末尾追加:
285
+ - 精确行号范围替换(`content` 可为空字符串表示删除):
242
286
 
243
287
  ```text
244
- Call the function tool `prepare_file_append` with:
245
- { "path": "notes/prompt.md", "content": "## Tools\n- Use prepare_* + apply_file_modification for incremental edits.\n" }
288
+ 按以下参数调用函数工具 `file_range_edit`:
289
+ { "path": "README.md", "range": "10~12", "content": "New line 10\nNew line 11\n" }
246
290
  ```
247
291
 
248
- - 行号范围替换(`content` 可为空字符串表示删除):
292
+ - 使用 pad 作为来源:
249
293
 
250
294
  ```text
251
- Call the function tool `prepare_file_range_edit` with:
252
- { "path": "README.md", "range": "10~12", "content": "New line 10\nNew line 11\n" }
295
+ 按以下参数调用函数工具 `file_range_edit`:
296
+ { "path": "README.md", "range": "10~12", "pad_id": "rewrite_intro", "pad_range": "~" }
297
+ ```
298
+
299
+ - 整文件大改(文件 → pad → 覆盖写回):
300
+
301
+ ```text
302
+ 按以下参数调用函数工具 `pad_load_file_range`:
303
+ { "pad_id": "rewrite_doc", "path": "docs/spec.md" }
304
+ ```
305
+
306
+ ```text
307
+ 按以下参数调用函数工具 `pad_edit` / `pad_insert` / `pad_delete_range` 精修 `rewrite_doc`。
308
+ ```
309
+
310
+ ```text
311
+ 按以下参数调用函数工具 `overwrite_entire_file`:
312
+ { "path": "docs/spec.md", "pad_id": "rewrite_doc", "known_old_total_lines": <read_file.total_lines>, "known_old_total_bytes": <read_file.size_bytes>, "content_format": "markdown" }
313
+ ```
314
+
315
+ - 末尾追加(可 create):
316
+
317
+ ```text
318
+ 按以下参数调用函数工具 `file_append`:
319
+ { "path": "notes/prompt.md", "content": "## Tools\n- Use file_range_edit for precise ranges; use file_block_replace for anchor-delimited blocks.\n" }
253
320
  ```
254
321
 
255
322
  - 双锚点块替换:
256
323
 
257
324
  ```text
258
- Call the function tool `prepare_file_block_replace` with:
325
+ 按以下参数调用函数工具 `file_block_replace`:
259
326
  { "path": "docs/spec.md", "start_anchor": "## Start", "end_anchor": "## End", "content": "NEW BLOCK LINE 1\nNEW BLOCK LINE 2\n" }
260
327
  ```
261
328
 
329
+ - 多 occurrence 批量替换:
330
+
331
+ ```text
332
+ 按以下参数调用函数工具 `prepare_occurrence_replace`:
333
+ { "path": "docs/spec.md", "find": "oldTerm", "content": "newTerm" }
334
+ ```
335
+
262
336
  ```text
263
- Call the function tool `apply_file_modification` with:
264
- { "hunk_id": "<hunk_id>" }
337
+ 确认候选无误后,按 prepare 输出的 plan_id 调用函数工具 `apply_occurrence_replace`:
338
+ { "plan_id": "<plan_id>" }
265
339
  ```
266
340
 
267
- ## 11. 与 `.minds/` 的关系(team_mgmt 版本)
341
+ ## 13. 与 `.minds/` 的关系(team_mgmt 版本)
268
342
 
269
- `.minds/` 属于团队配置与 rtws(运行时工作区)记忆的核心,通常应通过 `team_mgmt` toolset 的镜像工具操作(例如 `team_mgmt_prepare_file_insert_after` 等)。
270
- 本设计文档的“prepare-first + apply”心智模型保持一致,但路径与权限语义由 team_mgmt 工具包装层决定(详见 team_mgmt 文档/工具说明)。
343
+ `.minds/` 属于团队配置与 rtws(运行时工作区)记忆的核心,通常应通过 `team_mgmt` toolset 的镜像工具操作(例如 `team_mgmt_file_insert_after` 等)。
344
+ 本设计文档的 direct edit 心智模型保持一致,但路径与权限语义由 team_mgmt 工具包装层决定(详见 team_mgmt 文档/工具说明)。
271
345
 
272
346
  ---
273
347
 
@@ -275,12 +349,12 @@ Call the function tool `apply_file_modification` with:
275
349
 
276
350
  This is the design doc for `ws_mod` text editing as implemented.
277
351
 
278
- - Incremental edits are **prepare-first** (`prepare_*` returns YAML + unified diff + `hunk_id`) and **single-apply** (`apply_file_modification({hunk_id})` is the only apply entrypoint).
352
+ - Precise line-range edits use **direct range edit** (`file_range_edit`) by default; it writes immediately and returns YAML-only/redacted output unless `preview` or `show_diff` is requested.
353
+ - Single-block appends, anchor insertions, and anchor-delimited block replacements are direct tools: `file_append`, `file_insert_after` / `file_insert_before`, and `file_block_replace`.
279
354
  - Legacy direct-write edit tools are removed (no compat): `append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace`.
280
- - Function tool calls in one message run in parallel **prepare apply must be two messages**.
281
- - Applies are serialized per file in-process (queue by `createdAtMs`, then `hunkId`).
282
- - `hunk_id` is TTL-limited and in-memory; apply checks ownership and access.
283
- - Before apply, the prepared change is not persisted, so re-reading still returns the old file content; if you want the next edit based on that prepared result, apply the current hunk first, then prepare again.
284
- - `create_new_file` creates a new file (empty content allowed) and refuses to overwrite existing files (YAML-only output).
285
- - `overwrite_entire_file` is the exception full-file overwrite tool, guarded by `known_old_total_lines/known_old_total_bytes`, and it refuses diff/patch-like content by default unless `content_format='diff'|'patch'`.
355
+ - Function tool calls in one message run in parallel; same-file writes are serialized in-process by the direct file tools.
356
+ - `create_new_file` creates a new file (empty content allowed) and refuses to overwrite existing files; it accepts either direct `content` or `pad_id/pad_range` as source.
357
+ - `overwrite_entire_file` is the exception full-file overwrite tool, guarded by `known_old_total_lines/known_old_total_bytes`; it accepts either direct `content` or `pad_id/pad_range` as source, and refuses diff/patch-like content by default unless `content_format='diff'|'patch'`.
286
358
  - Some providers (e.g. Codex) may require “all fields present” in function calls; for those providers only, use sentinels like empty strings / 0 to express “unset/default”. For most providers, omit optional fields naturally.
359
+ - Scratch Pad is a staged `ws_mod` buffer system for large text editing. The current foundation includes `pad_write`, `pad_load_file_range`, `pad_edit`, `pad_insert`, `pad_delete_range`, `pad_copy`, `pad_move`, and `pad_delete`; `pad_load_file_range({pad_id,path})` loads whole files by default, and `create_new_file`, `overwrite_entire_file`, `file_range_edit`, `file_append`, `file_insert_*`, and `file_block_replace` can consume pad content directly. It keeps `add_reminder` / `update_reminder` / `delete_reminder` semantics unchanged, exposes lightweight task metadata (`intent`, `completion`, `source_note`, `delete_when_done`) plus the full line-numbered pad body as a prominent managed reminder in both UI and LLM context, marks pad body text as data rather than instructions, and includes pad metadata plus cleanup guidance in successful pad-sourced file write outputs. It intentionally avoids pad observation tools such as `pad_read` / `pad_preview` / `pad_diff`. Large generated content may still enter persistent tool-call history when first written, but subsequent file/pad operations should move text by handle instead of re-emitting it.
360
+ - Backlog: broaden pad-as-source/target support across file tools, then later evaluate whether pad/range editing tools can be consolidated after real usage patterns are clear.