dominds 1.9.2 → 1.9.3

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 (120) hide show
  1. package/dist/docs/memory-system.zh.md +1 -0
  2. package/dist/docs/txt-editing-tools.md +2 -0
  3. package/dist/docs/txt-editing-tools.zh.md +1 -0
  4. package/dist/llm/kernel-driver/tellask-special.js +1 -3
  5. package/dist/runtime/driver-messages.js +4 -4
  6. package/dist/runtime/inter-dialog-format.d.ts +10 -0
  7. package/dist/runtime/inter-dialog-format.js +21 -0
  8. package/dist/tools/os.js +129 -31
  9. package/dist/tools/prompts/os/en/tools.md +7 -0
  10. package/dist/tools/prompts/os/zh/tools.md +7 -0
  11. package/dist/tools/prompts/team_mgmt/en/index.md +1 -0
  12. package/dist/tools/prompts/team_mgmt/en/principles.md +1 -0
  13. package/dist/tools/prompts/team_mgmt/en/scenarios.md +2 -0
  14. package/dist/tools/prompts/team_mgmt/zh/index.md +1 -0
  15. package/dist/tools/prompts/team_mgmt/zh/principles.md +1 -0
  16. package/dist/tools/prompts/team_mgmt/zh/scenarios.md +2 -0
  17. package/dist/tools/prompts/ws_mod/en/index.md +1 -0
  18. package/dist/tools/prompts/ws_mod/en/principles.md +1 -0
  19. package/dist/tools/prompts/ws_mod/zh/index.md +1 -0
  20. package/dist/tools/prompts/ws_mod/zh/principles.md +1 -0
  21. package/dist/tools/prompts/ws_mod.en.md +4 -0
  22. package/dist/tools/prompts/ws_mod.zh.md +4 -0
  23. package/dist/tools/team_mgmt.js +2 -2
  24. package/dist/tools/txt.js +21 -11
  25. package/package.json +3 -3
  26. package/webapp/dist/assets/{_basePickBy-9Z1lbVTN.js → _basePickBy-BfH-AyMu.js} +3 -3
  27. package/webapp/dist/assets/{_basePickBy-9Z1lbVTN.js.map → _basePickBy-BfH-AyMu.js.map} +1 -1
  28. package/webapp/dist/assets/{_baseUniq-C3pRnD57.js → _baseUniq-BNsMcBuE.js} +2 -2
  29. package/webapp/dist/assets/{_baseUniq-C3pRnD57.js.map → _baseUniq-BNsMcBuE.js.map} +1 -1
  30. package/webapp/dist/assets/{arc-BvNng3O_.js → arc-Bs3CcPvC.js} +2 -2
  31. package/webapp/dist/assets/{arc-BvNng3O_.js.map → arc-Bs3CcPvC.js.map} +1 -1
  32. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BF8vwQ4e.js → architectureDiagram-2XIMDMQ5-C-KYTHQZ.js} +7 -7
  33. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-BF8vwQ4e.js.map → architectureDiagram-2XIMDMQ5-C-KYTHQZ.js.map} +1 -1
  34. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C7kfjZhf.js → blockDiagram-WCTKOSBZ-D9B_SH9m.js} +7 -7
  35. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-C7kfjZhf.js.map → blockDiagram-WCTKOSBZ-D9B_SH9m.js.map} +1 -1
  36. package/webapp/dist/assets/{c4Diagram-IC4MRINW-CaJ6bX75.js → c4Diagram-IC4MRINW-BDMmvUDN.js} +3 -3
  37. package/webapp/dist/assets/{c4Diagram-IC4MRINW-CaJ6bX75.js.map → c4Diagram-IC4MRINW-BDMmvUDN.js.map} +1 -1
  38. package/webapp/dist/assets/{channel-DDuIUO0R.js → channel-DkOACQ-Q.js} +2 -2
  39. package/webapp/dist/assets/{channel-DDuIUO0R.js.map → channel-DkOACQ-Q.js.map} +1 -1
  40. package/webapp/dist/assets/{chunk-4BX2VUAB-BQPkQh6v.js → chunk-4BX2VUAB-C2YYQQdn.js} +2 -2
  41. package/webapp/dist/assets/{chunk-4BX2VUAB-BQPkQh6v.js.map → chunk-4BX2VUAB-C2YYQQdn.js.map} +1 -1
  42. package/webapp/dist/assets/{chunk-55IACEB6-C2eZTkZ1.js → chunk-55IACEB6-BLL_vvlL.js} +2 -2
  43. package/webapp/dist/assets/{chunk-55IACEB6-C2eZTkZ1.js.map → chunk-55IACEB6-BLL_vvlL.js.map} +1 -1
  44. package/webapp/dist/assets/{chunk-FMBD7UC4-aXp5zApD.js → chunk-FMBD7UC4-DbvS-iIS.js} +2 -2
  45. package/webapp/dist/assets/{chunk-FMBD7UC4-aXp5zApD.js.map → chunk-FMBD7UC4-DbvS-iIS.js.map} +1 -1
  46. package/webapp/dist/assets/{chunk-JSJVCQXG-DXyaccrz.js → chunk-JSJVCQXG-BYsOBtUv.js} +2 -2
  47. package/webapp/dist/assets/{chunk-JSJVCQXG-DXyaccrz.js.map → chunk-JSJVCQXG-BYsOBtUv.js.map} +1 -1
  48. package/webapp/dist/assets/{chunk-KX2RTZJC-C-u000c0.js → chunk-KX2RTZJC-qqotPQTC.js} +2 -2
  49. package/webapp/dist/assets/{chunk-KX2RTZJC-C-u000c0.js.map → chunk-KX2RTZJC-qqotPQTC.js.map} +1 -1
  50. package/webapp/dist/assets/{chunk-NQ4KR5QH-BoYRoo4A.js → chunk-NQ4KR5QH-DtayaIyM.js} +4 -4
  51. package/webapp/dist/assets/{chunk-NQ4KR5QH-BoYRoo4A.js.map → chunk-NQ4KR5QH-DtayaIyM.js.map} +1 -1
  52. package/webapp/dist/assets/{chunk-QZHKN3VN-BAc_2ceG.js → chunk-QZHKN3VN-ByCgInOy.js} +2 -2
  53. package/webapp/dist/assets/{chunk-QZHKN3VN-BAc_2ceG.js.map → chunk-QZHKN3VN-ByCgInOy.js.map} +1 -1
  54. package/webapp/dist/assets/{chunk-WL4C6EOR-D6ws69Jx.js → chunk-WL4C6EOR-n6R_kv7j.js} +6 -6
  55. package/webapp/dist/assets/{chunk-WL4C6EOR-D6ws69Jx.js.map → chunk-WL4C6EOR-n6R_kv7j.js.map} +1 -1
  56. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BIRrKhqs.js → classDiagram-VBA2DB6C-Cr6hx981.js} +7 -7
  57. package/webapp/dist/assets/{classDiagram-VBA2DB6C-BIRrKhqs.js.map → classDiagram-VBA2DB6C-Cr6hx981.js.map} +1 -1
  58. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BIRrKhqs.js → classDiagram-v2-RAHNMMFH-Cr6hx981.js} +7 -7
  59. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BIRrKhqs.js.map → classDiagram-v2-RAHNMMFH-Cr6hx981.js.map} +1 -1
  60. package/webapp/dist/assets/{clone-DweFyVW6.js → clone-CVYUyjRt.js} +2 -2
  61. package/webapp/dist/assets/{clone-DweFyVW6.js.map → clone-CVYUyjRt.js.map} +1 -1
  62. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-vgovmGKM.js → cose-bilkent-S5V4N54A-CbVvMD8B.js} +2 -2
  63. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-vgovmGKM.js.map → cose-bilkent-S5V4N54A-CbVvMD8B.js.map} +1 -1
  64. package/webapp/dist/assets/{dagre-KLK3FWXG-B-Ax3qBf.js → dagre-KLK3FWXG-BuefmyeA.js} +7 -7
  65. package/webapp/dist/assets/{dagre-KLK3FWXG-B-Ax3qBf.js.map → dagre-KLK3FWXG-BuefmyeA.js.map} +1 -1
  66. package/webapp/dist/assets/{diagram-E7M64L7V-B1sUlvtn.js → diagram-E7M64L7V-DbxkA6bq.js} +8 -8
  67. package/webapp/dist/assets/{diagram-E7M64L7V-B1sUlvtn.js.map → diagram-E7M64L7V-DbxkA6bq.js.map} +1 -1
  68. package/webapp/dist/assets/{diagram-IFDJBPK2-3IlyK_xp.js → diagram-IFDJBPK2-6eTYxZlY.js} +7 -7
  69. package/webapp/dist/assets/{diagram-IFDJBPK2-3IlyK_xp.js.map → diagram-IFDJBPK2-6eTYxZlY.js.map} +1 -1
  70. package/webapp/dist/assets/{diagram-P4PSJMXO-C3x0JkgF.js → diagram-P4PSJMXO-BaxnuVrQ.js} +7 -7
  71. package/webapp/dist/assets/{diagram-P4PSJMXO-C3x0JkgF.js.map → diagram-P4PSJMXO-BaxnuVrQ.js.map} +1 -1
  72. package/webapp/dist/assets/{erDiagram-INFDFZHY-mEp6kC6i.js → erDiagram-INFDFZHY-CdM7JIpN.js} +5 -5
  73. package/webapp/dist/assets/{erDiagram-INFDFZHY-mEp6kC6i.js.map → erDiagram-INFDFZHY-CdM7JIpN.js.map} +1 -1
  74. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-AsG_wdLN.js → flowDiagram-PKNHOUZH-DWXwTxvt.js} +7 -7
  75. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-AsG_wdLN.js.map → flowDiagram-PKNHOUZH-DWXwTxvt.js.map} +1 -1
  76. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-zv3UhEAO.js → ganttDiagram-A5KZAMGK-icFBfjxa.js} +3 -3
  77. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-zv3UhEAO.js.map → ganttDiagram-A5KZAMGK-icFBfjxa.js.map} +1 -1
  78. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-C1yyISy7.js → gitGraphDiagram-K3NZZRJ6-DvG6Al7K.js} +8 -8
  79. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-C1yyISy7.js.map → gitGraphDiagram-K3NZZRJ6-DvG6Al7K.js.map} +1 -1
  80. package/webapp/dist/assets/{graph-CkQycYq_.js → graph-DttgpnyF.js} +3 -3
  81. package/webapp/dist/assets/{graph-CkQycYq_.js.map → graph-DttgpnyF.js.map} +1 -1
  82. package/webapp/dist/assets/{index-CCGi5dDE.js → index-glyVn6qA.js} +123 -41
  83. package/webapp/dist/assets/{index-CCGi5dDE.js.map → index-glyVn6qA.js.map} +1 -1
  84. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-Dw1wAgpl.js → infoDiagram-LFFYTUFH-Be7NVGsk.js} +6 -6
  85. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-Dw1wAgpl.js.map → infoDiagram-LFFYTUFH-Be7NVGsk.js.map} +1 -1
  86. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-DY9fHLYz.js → ishikawaDiagram-PHBUUO56-aBgICO2W.js} +2 -2
  87. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-DY9fHLYz.js.map → ishikawaDiagram-PHBUUO56-aBgICO2W.js.map} +1 -1
  88. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-CSGjRykr.js → journeyDiagram-4ABVD52K-6ZhQR2pT.js} +5 -5
  89. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-CSGjRykr.js.map → journeyDiagram-4ABVD52K-6ZhQR2pT.js.map} +1 -1
  90. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-DDCQetMc.js → kanban-definition-K7BYSVSG-BD5WcwkZ.js} +3 -3
  91. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-DDCQetMc.js.map → kanban-definition-K7BYSVSG-BD5WcwkZ.js.map} +1 -1
  92. package/webapp/dist/assets/{layout-DpuTr6cl.js → layout-BicT-AKX.js} +5 -5
  93. package/webapp/dist/assets/{layout-DpuTr6cl.js.map → layout-BicT-AKX.js.map} +1 -1
  94. package/webapp/dist/assets/{linear-BQv5LuhW.js → linear-mfPB9dWF.js} +2 -2
  95. package/webapp/dist/assets/{linear-BQv5LuhW.js.map → linear-mfPB9dWF.js.map} +1 -1
  96. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-C5ajM9Hr.js → mindmap-definition-YRQLILUH-kLbwaG3m.js} +4 -4
  97. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-C5ajM9Hr.js.map → mindmap-definition-YRQLILUH-kLbwaG3m.js.map} +1 -1
  98. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Daqms3DT.js → pieDiagram-SKSYHLDU-C2kjOvDJ.js} +8 -8
  99. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-Daqms3DT.js.map → pieDiagram-SKSYHLDU-C2kjOvDJ.js.map} +1 -1
  100. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BMNWp18J.js → quadrantDiagram-337W2JSQ-EBFouDoS.js} +3 -3
  101. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-BMNWp18J.js.map → quadrantDiagram-337W2JSQ-EBFouDoS.js.map} +1 -1
  102. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-C1Mc4MX-.js → requirementDiagram-Z7DCOOCP-q8a4FaYa.js} +4 -4
  103. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-C1Mc4MX-.js.map → requirementDiagram-Z7DCOOCP-q8a4FaYa.js.map} +1 -1
  104. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-DTHGhOsp.js → sankeyDiagram-WA2Y5GQK-BQB-fWeY.js} +2 -2
  105. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-DTHGhOsp.js.map → sankeyDiagram-WA2Y5GQK-BQB-fWeY.js.map} +1 -1
  106. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-C6cA5ncc.js → sequenceDiagram-2WXFIKYE-VQq6HFC4.js} +4 -4
  107. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-C6cA5ncc.js.map → sequenceDiagram-2WXFIKYE-VQq6HFC4.js.map} +1 -1
  108. package/webapp/dist/assets/{stateDiagram-RAJIS63D-DRDqVPKY.js → stateDiagram-RAJIS63D-CYdwXt96.js} +9 -9
  109. package/webapp/dist/assets/{stateDiagram-RAJIS63D-DRDqVPKY.js.map → stateDiagram-RAJIS63D-CYdwXt96.js.map} +1 -1
  110. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B-pby7Ke.js → stateDiagram-v2-FVOUBMTO-BtL9yVRW.js} +5 -5
  111. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-B-pby7Ke.js.map → stateDiagram-v2-FVOUBMTO-BtL9yVRW.js.map} +1 -1
  112. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C-m1bG_Z.js → timeline-definition-YZTLITO2-Mir0gPkJ.js} +3 -3
  113. package/webapp/dist/assets/{timeline-definition-YZTLITO2-C-m1bG_Z.js.map → timeline-definition-YZTLITO2-Mir0gPkJ.js.map} +1 -1
  114. package/webapp/dist/assets/{treemap-KZPCXAKY-BWvLuAyU.js → treemap-KZPCXAKY-BZkUTsQ5.js} +5 -5
  115. package/webapp/dist/assets/{treemap-KZPCXAKY-BWvLuAyU.js.map → treemap-KZPCXAKY-BZkUTsQ5.js.map} +1 -1
  116. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-C8gZYuUq.js → vennDiagram-LZ73GAT5-01He2Gl0.js} +2 -2
  117. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-C8gZYuUq.js.map → vennDiagram-LZ73GAT5-01He2Gl0.js.map} +1 -1
  118. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-Bb3azvDM.js → xychartDiagram-JWTSCODW-D1Igvf_e.js} +3 -3
  119. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-Bb3azvDM.js.map → xychartDiagram-JWTSCODW-D1Igvf_e.js.map} +1 -1
  120. package/webapp/dist/index.html +1 -1
@@ -149,6 +149,7 @@ TL;DR:
149
149
  有一类提醒项来自运行时环境(例如后台进程状态、MCP 租用/到期等)。它们更像信号灯:
150
150
 
151
151
  - 你应该阅读并据此调整行为
152
+ - 默认应“静默吸收”这类状态信号;除非它实际改变当前判断/计划/风险,否则不要在回复里专门确认、复述或总结它
152
153
  - 但它们的生命周期通常由系统管理(自动更新/自动清理),不要把它们当成个人工作日志
153
154
  - 在消息语义上,这类提醒应视为**系统提示**:通常落在 `role=user` 侧,并带显眼头标(如 `【系统提示】`),避免与个人工作提醒混淆
154
155
 
@@ -114,6 +114,7 @@ Chinese version: [中文版](./txt-editing-tools.zh.md)
114
114
 
115
115
  - 每个 plan hunk 带 TTL(输出 `expires_at_ms`)。
116
116
  - hunk 存储于进程内内存;进程重启后丢失。
117
+ - prepare 结果在 apply 前不会落盘;此时再次读取文件仍只能看到旧内容。若想基于该结果继续下一笔修改,必须先 apply 当前 hunk,再重新 prepare。
117
118
  - `apply_file_modification` 会检查:
118
119
  - hunk 是否存在且未过期
119
120
  - hunk 是否由当前成员规划(`WRONG_OWNER` 拒绝)
@@ -278,6 +279,7 @@ This is the design doc for `ws_mod` text editing as implemented.
278
279
  - Function tool calls in one message run in parallel → **prepare → apply must be two messages**.
279
280
  - Applies are serialized per file in-process (queue by `createdAtMs`, then `hunkId`).
280
281
  - `hunk_id` is TTL-limited and in-memory; apply checks ownership and access.
282
+ - 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.
281
283
  - `create_new_file` creates a new file (empty content allowed) and refuses to overwrite existing files (YAML-only output).
282
284
  - `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'`.
283
285
  - 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.
@@ -114,6 +114,7 @@ updated: 2026-01-24
114
114
 
115
115
  - 每个 plan hunk 带 TTL(输出 `expires_at_ms`)。
116
116
  - hunk 存储于进程内内存;进程重启后丢失。
117
+ - prepare 结果在 apply 前不会落盘;此时再次读取文件仍只能看到旧内容。若想基于该结果继续下一笔修改,必须先 apply 当前 hunk,再重新 prepare。
117
118
  - `apply_file_modification` 会检查:
118
119
  - hunk 是否存在且未过期
119
120
  - hunk 是否由当前成员规划(`WRONG_OWNER` 拒绝)
@@ -386,15 +386,13 @@ async function finishRegisteredTellaskReplacement(args) {
386
386
  const { ownerDialog, subdialog, pendingRecord, responseBody } = args;
387
387
  const language = (0, work_language_1.getWorkLanguage)();
388
388
  const requesterId = ownerDialog.agentId;
389
- const response = (0, inter_dialog_format_1.formatTellaskResponseContent)({
390
- callName: pendingRecord.callName,
389
+ const response = (0, inter_dialog_format_1.formatTellaskReplacementNoticeContent)({
391
390
  responderId: subdialog.agentId,
392
391
  requesterId,
393
392
  mentionList: pendingRecord.mentionList,
394
393
  sessionSlug: pendingRecord.sessionSlug,
395
394
  tellaskContent: pendingRecord.tellaskContent,
396
395
  responseBody,
397
- status: 'failed',
398
396
  language,
399
397
  });
400
398
  const carryoverOriginCourse = pendingRecord.callingCourse;
@@ -78,12 +78,12 @@ function formatRegisteredTellaskCallerUpdateNotice(language) {
78
78
  if (language === 'zh') {
79
79
  return [
80
80
  prefix,
81
- '刚才那轮诉请先不用继续等待了;对方接下来会按你更新后的要求继续处理,请以后续要求为准。',
81
+ '刚才那轮诉请不用再等了;对方接下来会按你刚更新的要求继续处理,后续请以最新要求为准。',
82
82
  ].join('\n');
83
83
  }
84
84
  return [
85
85
  prefix,
86
- 'You no longer need to wait on that earlier request. The teammate will continue from your updated request, so follow the later request from here.',
86
+ 'You no longer need to wait on that earlier request. The teammate will continue under your updated request, so treat the latest request as the one now in effect.',
87
87
  ].join('\n');
88
88
  }
89
89
  function formatRegisteredTellaskCalleeUpdateNotice(language) {
@@ -188,7 +188,7 @@ function formatReminderItemGuide(language, index, content, options) {
188
188
  return [
189
189
  `提醒项 #${index}(工具状态)`,
190
190
  '',
191
- '我把这条当作工具维护的状态参考,不把它自动当成我现在必须立刻执行的指令。',
191
+ '我把这条当作工具维护的状态参考。默认不在对外回复里专门确认、复述或总结它;只有它实际改变当前判断、计划或风险时,我才提炼真正相关的部分。',
192
192
  '',
193
193
  `这条提醒项由工具 ${managementTool} 管理;如果我要调整它,就用 ${managementTool}(不要用 update_reminder)。`,
194
194
  '',
@@ -232,7 +232,7 @@ function formatReminderItemGuide(language, index, content, options) {
232
232
  const updateExampleSafe = updateExample ?? `${managementTool}({ ... })`;
233
233
  return `REMINDER ITEM #${index} (TOOL STATE)
234
234
 
235
- I treat this as a tool-maintained state reference, not as an automatic must-do command.
235
+ I treat this as a tool-maintained state reference. By default I should not explicitly acknowledge, restate, or summarize it in my outward reply; I should only extract the parts that materially change my current judgment, plan, or risk.
236
236
 
237
237
  This reminder is managed by tool ${managementTool}; if I need to change it, I should use ${managementTool} instead of update_reminder.
238
238
 
@@ -48,6 +48,15 @@ export type TellaskResponseFormatInput = {
48
48
  status?: 'completed' | 'failed';
49
49
  language?: LanguageCode;
50
50
  };
51
+ export type TellaskReplacementNoticeFormatInput = {
52
+ responderId: string;
53
+ requesterId: string;
54
+ mentionList?: string[];
55
+ sessionSlug?: string;
56
+ tellaskContent: string;
57
+ responseBody: string;
58
+ language?: LanguageCode;
59
+ };
51
60
  export type TellaskCarryoverResultFormatInput = {
52
61
  originCourse: number;
53
62
  callName: 'tellask' | 'tellaskSessionless' | 'freshBootsReasoning';
@@ -70,4 +79,5 @@ export declare function formatAssignmentFromSupdialog(input: SubdialogAssignment
70
79
  export declare function formatUpdatedAssignmentFromSupdialog(input: SubdialogAssignmentFormatInput): string;
71
80
  export declare function formatSupdialogCallPrompt(input: SupdialogCallPromptInput): string;
72
81
  export declare function formatTellaskResponseContent(input: TellaskResponseFormatInput): string;
82
+ export declare function formatTellaskReplacementNoticeContent(input: TellaskReplacementNoticeFormatInput): string;
73
83
  export declare function formatTellaskCarryoverResultContent(input: TellaskCarryoverResultFormatInput): string;
@@ -18,6 +18,7 @@ exports.formatAssignmentFromSupdialog = formatAssignmentFromSupdialog;
18
18
  exports.formatUpdatedAssignmentFromSupdialog = formatUpdatedAssignmentFromSupdialog;
19
19
  exports.formatSupdialogCallPrompt = formatSupdialogCallPrompt;
20
20
  exports.formatTellaskResponseContent = formatTellaskResponseContent;
21
+ exports.formatTellaskReplacementNoticeContent = formatTellaskReplacementNoticeContent;
21
22
  exports.formatTellaskCarryoverResultContent = formatTellaskCarryoverResultContent;
22
23
  const driver_messages_1 = require("./driver-messages");
23
24
  const markdown_format_1 = require("./markdown-format");
@@ -219,6 +220,26 @@ function formatTellaskResponseContent(input) {
219
220
  : `regarding the original tellask: ${mentionLine} • ${sessionSlug}`;
220
221
  return `${markerPrefix}${hello}\n\n${(0, markdown_format_1.markdownQuote)(input.responseBody)}\n\n${tail}\n\n${(0, markdown_format_1.markdownQuote)(tellaskContent)}\n`;
221
222
  }
223
+ function formatTellaskReplacementNoticeContent(input) {
224
+ const language = input.language ?? 'en';
225
+ const tellaskContent = requireNonEmpty(input.tellaskContent, 'tellaskContent');
226
+ const responseBody = requireNonEmpty(input.responseBody, 'responseBody');
227
+ const mentionIds = (input.mentionList ?? [])
228
+ .map((item) => stripMentionPrefix(item))
229
+ .filter((item) => item !== '');
230
+ const mentionLine = mentionIds.length === 0
231
+ ? `@${requireNonEmpty(input.requesterId, 'requesterId')}`
232
+ : mentionIds.map((mentionId) => `@${mentionId}`).join(' ');
233
+ const sessionSlug = input.sessionSlug?.trim() ?? '';
234
+ const tail = language === 'zh'
235
+ ? sessionSlug === ''
236
+ ? `对应原始诉请: ${mentionLine}`
237
+ : `对应原始诉请: ${mentionLine} • ${sessionSlug}`
238
+ : sessionSlug === ''
239
+ ? `applies to the original tellask: ${mentionLine}`
240
+ : `applies to the original tellask: ${mentionLine} • ${sessionSlug}`;
241
+ return `${responseBody}\n\n${tail}\n\n${(0, markdown_format_1.markdownQuote)(tellaskContent)}\n`;
242
+ }
222
243
  function formatTellaskCarryoverResultContent(input) {
223
244
  const language = input.language ?? 'en';
224
245
  const tellaskContent = requireNonEmpty(input.tellaskContent, 'tellaskContent');
package/dist/tools/os.js CHANGED
@@ -132,6 +132,55 @@ class HeadTailByteBuffer {
132
132
  }
133
133
  // Global registry for daemon processes
134
134
  const daemonProcesses = new Map();
135
+ let trackedDaemonShutdownSigtermSent = false;
136
+ let trackedDaemonShutdownSigkillSent = false;
137
+ function resolveBestEffortDaemonSignalTarget(daemon) {
138
+ if (process.platform !== 'win32' && daemon.processGroupId !== undefined) {
139
+ return -daemon.processGroupId;
140
+ }
141
+ return daemon.pid;
142
+ }
143
+ function signalTrackedDaemonsForProcessShutdown(signal) {
144
+ const alreadySent = signal === 'SIGTERM' ? trackedDaemonShutdownSigtermSent : trackedDaemonShutdownSigkillSent;
145
+ if (alreadySent)
146
+ return;
147
+ if (signal === 'SIGTERM') {
148
+ trackedDaemonShutdownSigtermSent = true;
149
+ }
150
+ else {
151
+ trackedDaemonShutdownSigkillSent = true;
152
+ }
153
+ for (const daemon of daemonProcesses.values()) {
154
+ const signalTarget = resolveBestEffortDaemonSignalTarget(daemon);
155
+ try {
156
+ process.kill(signalTarget, signal);
157
+ }
158
+ catch (error) {
159
+ console.error('[os] failed to signal tracked daemon during process shutdown', {
160
+ pid: daemon.pid,
161
+ processGroupId: daemon.processGroupId ?? null,
162
+ signal,
163
+ error: error instanceof Error ? error.message : String(error),
164
+ });
165
+ }
166
+ }
167
+ if (signal === 'SIGKILL') {
168
+ daemonProcesses.clear();
169
+ }
170
+ }
171
+ process.once('beforeExit', () => {
172
+ signalTrackedDaemonsForProcessShutdown('SIGTERM');
173
+ });
174
+ process.once('exit', () => {
175
+ signalTrackedDaemonsForProcessShutdown('SIGTERM');
176
+ signalTrackedDaemonsForProcessShutdown('SIGKILL');
177
+ });
178
+ process.once('SIGINT', () => {
179
+ signalTrackedDaemonsForProcessShutdown('SIGTERM');
180
+ });
181
+ process.once('SIGTERM', () => {
182
+ signalTrackedDaemonsForProcessShutdown('SIGTERM');
183
+ });
135
184
  function getOsToolMessages(language) {
136
185
  if (language === 'zh') {
137
186
  return {
@@ -249,7 +298,17 @@ function parseStopDaemonArgs(args) {
249
298
  if (typeof pid !== 'number') {
250
299
  throw new Error('stop_daemon.pid must be a number');
251
300
  }
252
- return { pid };
301
+ const entirePg = args.entire_pg;
302
+ if (entirePg !== undefined && typeof entirePg !== 'boolean') {
303
+ throw new Error('stop_daemon.entire_pg must be a boolean if provided');
304
+ }
305
+ if (process.platform === 'win32' && entirePg === true) {
306
+ throw new Error('stop_daemon.entire_pg=true is unsupported on Windows');
307
+ }
308
+ return {
309
+ pid,
310
+ entirePg: entirePg ?? process.platform !== 'win32',
311
+ };
253
312
  }
254
313
  function parseGetDaemonOutputArgs(args) {
255
314
  const pid = args.pid;
@@ -356,6 +415,10 @@ const stopDaemonSchema = {
356
415
  type: 'number',
357
416
  description: 'Process ID of the daemon to stop',
358
417
  },
418
+ entire_pg: {
419
+ type: 'boolean',
420
+ description: 'Whether to signal the entire process group instead of only the tracked PID (default: true on Unix-like systems; false on Windows)',
421
+ },
359
422
  },
360
423
  required: ['pid'],
361
424
  additionalProperties: false,
@@ -377,44 +440,70 @@ const getDaemonOutputSchema = {
377
440
  additionalProperties: false,
378
441
  };
379
442
  // Format daemon status for reminder display
380
- function formatDaemonStatus(daemon) {
443
+ function formatDaemonStatus(daemon, language) {
381
444
  const uptime = Math.floor((Date.now() - daemon.startTime.getTime()) / 1000);
382
- const status = daemon.isRunning
383
- ? 'running'
384
- : `exited (code: ${daemon.exitCode}, signal: ${daemon.exitSignal})`;
445
+ const status = language === 'zh'
446
+ ? daemon.isRunning
447
+ ? '运行中'
448
+ : `已退出(code: ${daemon.exitCode}, signal: ${daemon.exitSignal})`
449
+ : daemon.isRunning
450
+ ? 'running'
451
+ : `exited (code: ${daemon.exitCode}, signal: ${daemon.exitSignal})`;
385
452
  const stdoutInfo = daemon.stdoutBuffer.getScrollInfo();
386
453
  const stderrInfo = daemon.stderrBuffer.getScrollInfo();
387
454
  let scrollNotice = '';
388
455
  if (stdoutInfo.hasScrolledContent || stderrInfo.hasScrolledContent) {
389
456
  const scrolledLines = stdoutInfo.linesScrolledOut + stderrInfo.linesScrolledOut;
390
- scrollNotice = `\n⚠️ ${scrolledLines} lines have scrolled out of view`;
457
+ scrollNotice =
458
+ language === 'zh'
459
+ ? `\n注意:已有 ${scrolledLines} 行滚出当前保留缓冲区`
460
+ : `\nNote: ${scrolledLines} lines have scrolled out of the retained buffer`;
391
461
  }
392
462
  const stdoutContent = daemon.stdoutBuffer.isEmpty()
393
- ? '(no output)'
463
+ ? language === 'zh'
464
+ ? '(无输出)'
465
+ : '(no output)'
394
466
  : daemon.stdoutBuffer.getContent();
395
467
  const stderrContent = daemon.stderrBuffer.isEmpty()
396
- ? '(no errors)'
468
+ ? language === 'zh'
469
+ ? '(无 stderr 输出)'
470
+ : '(no stderr output)'
397
471
  : daemon.stderrBuffer.getContent();
398
472
  const fenceConsole = '```console';
399
473
  const fenceEnd = '```';
400
- return `🔄 Daemon Process ${daemon.pid}
401
- Command: ${daemon.command}
474
+ return language === 'zh'
475
+ ? `后台进程 PID: ${daemon.pid}
476
+ 命令: ${daemon.command}
402
477
  Shell: ${daemon.shell}
403
- Status: ${status}
404
- Uptime: ${uptime}s
405
- Started: ${(0, time_1.formatUnifiedTimestamp)(daemon.startTime)}${scrollNotice}
478
+ 生命周期状态: ${status}
479
+ 已运行: ${uptime}s
480
+ 启动时间: ${(0, time_1.formatUnifiedTimestamp)(daemon.startTime)}${scrollNotice}
406
481
 
407
- 📤 Latest stdout:
482
+ stdout 缓冲区快照:
408
483
  ${fenceConsole}
409
484
  ${stdoutContent}
410
485
  ${fenceEnd}
411
486
 
412
- 📤 Latest stderr:
487
+ stderr 缓冲区快照:
413
488
  ${fenceConsole}
414
489
  ${stderrContent}
490
+ ${fenceEnd}`
491
+ : `Daemon PID: ${daemon.pid}
492
+ Command: ${daemon.command}
493
+ Shell: ${daemon.shell}
494
+ Lifecycle status: ${status}
495
+ Uptime: ${uptime}s
496
+ Started at: ${(0, time_1.formatUnifiedTimestamp)(daemon.startTime)}${scrollNotice}
497
+
498
+ Stdout buffer snapshot:
499
+ ${fenceConsole}
500
+ ${stdoutContent}
415
501
  ${fenceEnd}
416
502
 
417
- 💡 Use stop_daemon({"pid": ${daemon.pid}}) to terminate this process`;
503
+ Stderr buffer snapshot:
504
+ ${fenceConsole}
505
+ ${stderrContent}
506
+ ${fenceEnd}`;
418
507
  }
419
508
  // ReminderOwner implementation for shell command tool
420
509
  exports.shellCmdReminderOwner = {
@@ -432,7 +521,7 @@ exports.shellCmdReminderOwner = {
432
521
  // Check if process has exited
433
522
  if (!daemon.isRunning) {
434
523
  // Process has exited, provide final status and drop reminder
435
- const finalStatus = formatDaemonStatus(daemon);
524
+ const finalStatus = formatDaemonStatus(daemon, (0, work_language_1.getWorkLanguage)());
436
525
  daemonProcesses.delete(pid);
437
526
  return {
438
527
  treatment: 'update',
@@ -457,7 +546,7 @@ exports.shellCmdReminderOwner = {
457
546
  daemon.exitSignal = 'UNKNOWN';
458
547
  }
459
548
  // Update the reminder with current daemon status
460
- const updatedContent = formatDaemonStatus(daemon);
549
+ const updatedContent = formatDaemonStatus(daemon, (0, work_language_1.getWorkLanguage)());
461
550
  return {
462
551
  treatment: 'update',
463
552
  updatedContent,
@@ -477,11 +566,11 @@ exports.shellCmdReminderOwner = {
477
566
  role: 'user',
478
567
  content: language === 'zh'
479
568
  ? `${prefix} 后台进程状态提醒 #${index + 1}
480
- 你正在查看系统维护的后台进程状态,不要把它当成你自己写的工作便签。该提醒会随进程生命周期自动更新或删除。
569
+ 这是系统维护的后台进程状态快照。默认静默吸收即可,不要把它当成你自己写的工作便签,也不要在对外回复里专门确认或复述;只有它实际影响当前判断或后续动作时,才提炼相关事实。该提醒会随进程生命周期自动更新或删除。
481
570
  ---
482
571
  ${reminder.content}`
483
572
  : `${prefix} Background process status reminder #${index + 1}
484
- You are looking at system-maintained background process state. Do not treat it as a self-authored work note. This reminder will update or disappear automatically with the process lifecycle.
573
+ This is a system-maintained background process snapshot. Consume it silently by default: do not treat it as a self-authored work note, and do not explicitly acknowledge or restate it in your outward reply unless it materially affects your current judgment or next action. This reminder will update or disappear automatically with the process lifecycle.
485
574
  ---
486
575
  ${reminder.content}`,
487
576
  };
@@ -507,20 +596,20 @@ This daemon process has finished its lifecycle and is no longer running. This re
507
596
  : uptime < 3600
508
597
  ? `${Math.floor(uptime / 60)}m ${uptime % 60}s`
509
598
  : `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m`;
510
- const statusInfo = formatDaemonStatus(daemon);
599
+ const statusInfo = formatDaemonStatus(daemon, language);
511
600
  return {
512
601
  type: 'environment_msg',
513
602
  role: 'user',
514
603
  content: language === 'zh'
515
- ? `🔄 ${prefix} 运行中后台进程监控 #${index + 1} - PID ${pid}(已运行 ${uptimeStr})
516
- 你当前有一个仍在运行的后台进程。请按需要检查它的健康状态、资源占用和输出情况;这条提醒由系统自动维护,会随进程状态变化自动更新或删除。
604
+ ? `🔄 ${prefix} 运行中后台进程状态 #${index + 1} - PID ${pid}(已运行 ${uptimeStr})
605
+ 这是系统维护的状态快照,不是新的用户诉求,也不是默认需要单独汇报的事项。只有它实际改变当前判断、计划、风险,或确实需要调用守护进程相关工具时,才使用下面的信息;否则保持静默吸收即可。
517
606
 
518
- **当前状态:**
607
+ **状态快照:**
519
608
  ${statusInfo}`
520
- : `🔄 ${prefix} Active daemon monitor #${index + 1} - PID ${pid} (uptime: ${uptimeStr})
521
- You currently have a background process that is still running. Check its health, resource usage, and output as needed. This reminder is system-maintained and will update or disappear automatically as the process state changes.
609
+ : `🔄 ${prefix} Active daemon state #${index + 1} - PID ${pid} (uptime: ${uptimeStr})
610
+ This is a system-maintained snapshot, not a new user request and not something that normally deserves a standalone mention. Use the information below only when it materially changes your current judgment, plan, risk, or a daemon-management action; otherwise consume it silently.
522
611
 
523
- **Current status:**
612
+ **State snapshot:**
524
613
  ${statusInfo}`,
525
614
  };
526
615
  },
@@ -546,6 +635,7 @@ exports.shellCmdTool = {
546
635
  return new Promise((resolve) => {
547
636
  const childProcess = (0, child_process_1.spawn)(spawnSpec.command, spawnSpec.args, {
548
637
  stdio: ['pipe', 'pipe', 'pipe'],
638
+ detached: process.platform !== 'win32',
549
639
  });
550
640
  const pid = childProcess.pid;
551
641
  const startTime = new Date();
@@ -564,6 +654,7 @@ exports.shellCmdTool = {
564
654
  command,
565
655
  shell: spawnSpec.shellLabel,
566
656
  process: childProcess,
657
+ processGroupId: process.platform === 'win32' ? undefined : pid,
567
658
  startTime,
568
659
  stdoutBuffer,
569
660
  stderrBuffer,
@@ -1308,19 +1399,26 @@ exports.stopDaemonTool = {
1308
1399
  async call(dlg, caller, args) {
1309
1400
  const language = (0, work_language_1.getWorkLanguage)();
1310
1401
  const t = getOsToolMessages(language);
1311
- const { pid } = parseStopDaemonArgs(args);
1402
+ const { pid, entirePg } = parseStopDaemonArgs(args);
1312
1403
  const daemon = daemonProcesses.get(pid);
1313
1404
  if (!daemon) {
1314
1405
  return t.noDaemonFound(pid);
1315
1406
  }
1316
1407
  try {
1317
- // Kill the process
1318
- process.kill(pid, 'SIGTERM');
1408
+ let signalTarget = pid;
1409
+ if (entirePg) {
1410
+ if (daemon.processGroupId === undefined) {
1411
+ throw new Error('daemon has no isolated process group; rerun it after this update, or retry with entire_pg=false');
1412
+ }
1413
+ signalTarget = -daemon.processGroupId;
1414
+ }
1415
+ // Kill the tracked process or its entire process group.
1416
+ process.kill(signalTarget, 'SIGTERM');
1319
1417
  // Wait a bit for graceful shutdown
1320
1418
  await new Promise((resolve) => setTimeout(resolve, 1000));
1321
1419
  // Force kill if still running
1322
1420
  try {
1323
- process.kill(pid, 'SIGKILL');
1421
+ process.kill(signalTarget, 'SIGKILL');
1324
1422
  }
1325
1423
  catch (e) {
1326
1424
  // Process already terminated
@@ -48,6 +48,7 @@ Stop daemon process.
48
48
  **Parameters:**
49
49
 
50
50
  - `pid` (required): Daemon process ID (number)
51
+ - `entire_pg` (optional): Whether to signal the entire process group (default: `true` on Unix-like systems, `false` on Windows; Windows does not support explicitly passing `true`)
51
52
 
52
53
  **Returns:**
53
54
 
@@ -151,6 +152,12 @@ shell_cmd({
151
152
  stop_daemon({
152
153
  pid: 12345,
153
154
  });
155
+
156
+ // On Unix-like systems, you can explicitly terminate the whole process group
157
+ stop_daemon({
158
+ pid: 12345,
159
+ entire_pg: true,
160
+ });
154
161
  ```
155
162
 
156
163
  ### Get Daemon Process Output
@@ -48,6 +48,7 @@ executed_at: <执行时间戳>
48
48
  **参数:**
49
49
 
50
50
  - `pid`(必需):守护进程 PID(数字)
51
+ - `entire_pg`(可选):是否对整个进程组发终止信号(默认:Linux/macOS 为 `true`,Windows 为 `false`;Windows 不支持显式传 `true`)
51
52
 
52
53
  **返回:**
53
54
 
@@ -151,6 +152,12 @@ shell_cmd({
151
152
  stop_daemon({
152
153
  pid: 12345,
153
154
  });
155
+
156
+ // Unix-like 平台可显式要求终止整个进程组
157
+ stop_daemon({
158
+ pid: 12345,
159
+ entire_pg: true,
160
+ });
154
161
  ```
155
162
 
156
163
  ### 获取守护进程输出
@@ -27,6 +27,7 @@
27
27
  team_mgmt is Dominds' toolset for managing `.minds/` (team configuration and rtws memory), using **prepare-first + single apply** architecture:
28
28
 
29
29
  - **Incremental edits (preferred)**: Use `team_mgmt_prepare_*` to generate reviewable YAML + diff + `hunk_id`, then write via `team_mgmt_apply_file_modification`
30
+ - **Hard ordering rule for the LLM**: `team_mgmt_prepare_*` only creates an in-memory preview and does not write the file; before `apply`, re-reading still returns the old content. If you want further edits based on the prepared result, you must call `team_mgmt_apply_file_modification` first, then read/prepare the next change
30
31
  - **Only operates in `.minds/`**: This toolset only operates within the `.minds/` subtree and should not touch other rtws files
31
32
  - **Shell guardrail**: toolset `os` includes `shell_cmd` / `stop_daemon` / `get_daemon_output`; any member with these shell tools must be listed in top-level `shell_specialists`
32
33
  - **Member assets recommended**: strongly recommend `persona/knowledge/lessons` files for every `members.<id>` to define ownership, boundaries, and reusable lessons
@@ -27,6 +27,7 @@
27
27
 
28
28
  - **Incremental edits (preferred)**: Use `team_mgmt_prepare_*` to generate reviewable YAML + diff + `hunk_id`, then write via `team_mgmt_apply_file_modification({ "hunk_id": "<hunk_id>" })`
29
29
  - **Parallelism constraint**: Multiple function tool calls in one generation step may run in parallel; **prepare → apply must be two steps**
30
+ - **LLM persistence semantics**: `team_mgmt_prepare_*` only stores a pending in-memory preview and does not modify the file before apply; a `team_mgmt_read_file` before apply still returns the old content. If you only want to revise that pending preview, overwrite the same hunk with `existing_hunk_id`; if you want the next edit based on this change, apply the current hunk first, then read/prepare again
30
31
  - **Minimum shell privilege**: toolset `os` includes `shell_cmd` / `stop_daemon` / `get_daemon_output`; grant it only to a small specialist set and list those member ids in top-level `shell_specialists`
31
32
  - **Exception (create)**: `team_mgmt_create_new_file` only creates a new file (empty content allowed). It does not do incremental edits and does not use prepare/apply; it refuses to overwrite existing files
32
33
  - **Exception (overwrite)**: `team_mgmt_overwrite_entire_file` writes immediately (no prepare/apply). It requires `known_old_total_lines/known_old_total_bytes` guardrails; use `team_mgmt_read_file` to read `total_lines/size_bytes` from the YAML header
@@ -52,6 +52,8 @@ Call the function tool `team_mgmt_apply_file_modification` with:
52
52
  { "hunk_id": "<hunk_id>" }
53
53
  ```
54
54
 
55
+ Important: before this apply, the prepared diff is not persisted yet; re-reading the file still returns the old content. If you want the next edit based on this change, apply the current hunk first, then prepare the next one.
56
+
55
57
  ### 4. Create New Mind File
56
58
 
57
59
  ```text
@@ -27,6 +27,7 @@
27
27
  team_mgmt 是 Dominds 用于管理 `.minds/`(团队配置与 rtws 记忆)的工具集,采用 **prepare-first + single apply** 架构:
28
28
 
29
29
  - **增量编辑(推荐)**:用 `team_mgmt_prepare_*` 先生成可复核的 YAML + diff + `hunk_id`,再用 `team_mgmt_apply_file_modification` 显式写入
30
+ - **LLM 顺序硬约束**:`team_mgmt_prepare_*` 只生成内存中的预览,不会写盘;在 `apply` 之前再次读取文件仍只能读到旧内容。若要基于本次改动继续修改,必须先 `team_mgmt_apply_file_modification`,再重新 read/prepare 新改动
30
31
  - **只操作 `.minds/`**:该 toolset 只允许操作 `.minds/` 子树,不会也不应触碰 rtws 其他文件
31
32
  - **shell 权限约束**:`os` toolset 包含 `shell_cmd` / `stop_daemon` / `get_daemon_output`;任何拿到这些工具的成员都必须出现在顶层 `shell_specialists`
32
33
  - **成员资产推荐**:强烈建议为每个 `members.<id>` 配置 `persona/knowledge/lessons` 资产文件,显式定义角色职责、边界和经验复用
@@ -27,6 +27,7 @@
27
27
 
28
28
  - **增量编辑(推荐)**:用 `team_mgmt_prepare_*` 先生成可复核的 YAML + diff + `hunk_id`,再用 `team_mgmt_apply_file_modification({ "hunk_id": "<hunk_id>" })` 显式写入
29
29
  - **并行约束**:同一轮生成中的多个工具调用可能并行执行;**prepare → apply 必须分两轮**
30
+ - **LLM 落盘语义**:`team_mgmt_prepare_*` 只保存待应用的内存预览,apply 前不会改动文件;此时再次 `team_mgmt_read_file` 看到的仍是旧内容。若只是修订同一个未落盘预览,可用同一 prepare 工具加 `existing_hunk_id` 覆写;若想继续下一笔修改,必须先 apply 当前 hunk,再重新 read/prepare
30
31
  - **shell 最小授权**:`os` toolset 包含 `shell_cmd` / `stop_daemon` / `get_daemon_output`;只授予少数专员成员,并在顶层 `shell_specialists` 显式列出这些成员 id
31
32
  - **例外(创建)**:`team_mgmt_create_new_file` 只负责创建新文件(允许空内容),不做增量编辑、不走 prepare/apply;若文件已存在会拒绝(避免误用覆盖写入语义)
32
33
  - **例外(整文件覆盖)**:`team_mgmt_overwrite_entire_file` 会直接写盘(不走 prepare/apply),必须提供 `known_old_total_lines/known_old_total_bytes` 作为对账护栏;建议先用 `team_mgmt_read_file` 从 YAML header 读取 `total_lines/size_bytes` 再填写
@@ -52,6 +52,8 @@ Call the function tool `team_mgmt_apply_file_modification` with:
52
52
  { "hunk_id": "<hunk_id>" }
53
53
  ```
54
54
 
55
+ 注意:这一步之前,prepare 结果还没有落盘;如果此时再次读取文件,读到的仍是旧内容。若要基于这次改动继续修改,先 apply 当前 hunk,再准备下一笔改动。
56
+
55
57
  ### 4. 创建新的 mind 文件
56
58
 
57
59
  ```text
@@ -28,6 +28,7 @@ ws_mod is Dominds' text editing toolset, using **prepare-first + single apply**
28
28
 
29
29
  - **prepare-first**: All incremental edits are planned first (output reviewable diff + evidence + hunk_id)
30
30
  - **single apply**: All planned edits are persisted only through `apply_file_modification`
31
+ - **Hard ordering rule for the LLM**: Before apply, a prepared hunk exists only in memory; re-reading still returns the old file content. If you want further edits based on that prepared result, apply the current hunk first, then prepare again
31
32
  - **Legacy tools removed**: `append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace` are completely removed
32
33
 
33
34
  ## Quick Navigation
@@ -35,6 +35,7 @@ Therefore unified to:
35
35
 
36
36
  - **prepare-first**: All incremental edits are planned first (output reviewable diff + evidence + hunk_id)
37
37
  - **single apply**: All planned edits are persisted only through `apply_file_modification({ "hunk_id": "<hunk_id>" })`
38
+ - **LLM persistence semantics**: before apply, a prepared hunk exists only in memory and does not modify the file; a `read_file` at that point still returns the old content. If you only want to revise the same pending preview, overwrite it with the same prepare tool plus `existing_hunk_id`; if you want the next edit based on this change, apply the current hunk first, then read/prepare again
38
39
  - **Legacy tools removed**: `append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace` are completely removed (no aliases, no compat layer)
39
40
 
40
41
  ## 2. Goals & Non-Goals
@@ -28,6 +28,7 @@ ws_mod 是 Dominds 的文本编辑工具集,采用 **prepare-first + single ap
28
28
 
29
29
  - **prepare-first**:所有增量编辑先规划(输出可审阅 diff + evidence + hunk_id)
30
30
  - **single apply**:所有计划类编辑仅通过 `apply_file_modification` 落盘
31
+ - **LLM 顺序硬约束**:prepare 结果在 apply 前只存在于内存里;此时再次读取文件仍只能读到旧内容。若要基于该结果继续修改,必须先 apply 当前 hunk,再重新 prepare
31
32
  - **移除旧工具**:`append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace` 已彻底删除
32
33
 
33
34
  ## 快速导航
@@ -35,6 +35,7 @@
35
35
 
36
36
  - **prepare-first**:所有增量编辑先规划(输出可审阅 diff + evidence + hunk_id)
37
37
  - **single apply**:所有计划类编辑仅通过 `apply_file_modification({ "hunk_id": "<hunk_id>" })` 落盘
38
+ - **LLM 落盘语义**:prepare 结果在 apply 前只保存在内存中,不会改动文件;此时再次 `read_file` 看到的仍是旧内容。若只是修订同一个未落盘预览,可用同一 prepare 工具加 `existing_hunk_id` 覆写;若想继续下一笔修改,必须先 apply 当前 hunk,再重新 read/prepare
38
39
  - **移除旧工具**:`append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace` 已彻底删除(无 alias、无兼容层)
39
40
 
40
41
  ## 2. 目标与非目标
@@ -5,6 +5,7 @@ You have read/write access to the rtws (runtime workspace), but **all incrementa
5
5
  ## Principles
6
6
 
7
7
  - Incremental edits: use `prepare_*` to generate an applyable hunk, then write via `apply_file_modification`.
8
+ - Hard ordering rule for the LLM: `prepare_*` only creates an in-memory preview and does not write the file; before `apply_file_modification`, re-reading still returns the old content. If you want further edits based on the prepared result, you must apply the current hunk first, then read/prepare the next change.
8
9
  - Legacy tools are removed (no compatibility layer): `append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace`.
9
10
  - Constraint: paths under `*.tsk/` are encapsulated Taskdocs; file tools cannot access them.
10
11
  - Parallelism constraint: multiple function tool calls in one generation step may run in parallel; **prepare → apply must be two steps**.
@@ -35,6 +36,7 @@ You have read/write access to the rtws (runtime workspace), but **all incrementa
35
36
  - `prepare_*` generates `hunk_id` (TTL = 1 hour); apply can only use an unexpired hunk.
36
37
  - Expired/unused hunks have no side effects; they are cleaned up automatically.
37
38
  - Some prepare tools accept `existing_hunk_id` to overwrite the same prepared hunk; **custom new ids are not supported**.
39
+ - If you only want to revise the same not-yet-persisted preview, overwrite that hunk with the same prepare tool plus `existing_hunk_id`; if you want the next edit based on this change, apply the current hunk first, then prepare again.
38
40
 
39
41
  ## Apply semantics (context_match)
40
42
 
@@ -58,6 +60,8 @@ Call the function tool `apply_file_modification` with:
58
60
  { "hunk_id": "<hunk_id>" }
59
61
  ```
60
62
 
63
+ Before this step, the prepared diff is not persisted yet; a `read_file` at that point still returns the old content.
64
+
61
65
  ## Examples
62
66
 
63
67
  - Append to EOF:
@@ -5,6 +5,7 @@
5
5
  ## 总原则
6
6
 
7
7
  - 增量编辑:通过 `prepare_*` 生成可 apply 的 hunk;然后用 `apply_file_modification` 写入。
8
+ - LLM 顺序硬约束:`prepare_*` 只生成内存中的预览,不会写盘;在 `apply_file_modification` 之前再次读取文件仍只能读到旧内容。若要基于本次改动继续修改,必须先 apply 当前 hunk,再重新 read/prepare 新改动。
8
9
  - 旧工具已移除(无兼容层):`append_file` / `insert_after` / `insert_before` / `replace_block` / `apply_block_replace`。
9
10
  - 约束:`*.tsk/` 下的路径属于封装差遣牒,文件工具不可访问。
10
11
  - 并行约束:同一轮对话中的多个工具调用可能并行执行;**prepare → apply 必须分两轮**(除非未来有顺序编排器)。
@@ -36,6 +37,7 @@
36
37
  - `prepare_*` 会生成 `hunk_id`(TTL=1 小时);apply 只能用仍然存在的 hunk。
37
38
  - 过期/未使用的 hunk **不会产生任何副作用**,会在运行时自动清理;只需关注"最后一次准备的那个 `hunk_id`"。
38
39
  - 部分 prepare 工具支持 `existing_hunk_id` 作为"覆写同一 prepare"的方式;**不支持自定义新 id**。
40
+ - 若只是修订同一个未落盘预览,可用同一 prepare 工具配合 `existing_hunk_id` 覆写;若想基于这次改动继续做下一笔修改,必须先 apply 当前 hunk,再重新 prepare。
39
41
 
40
42
  ## apply 语义(context_match)
41
43
 
@@ -59,6 +61,8 @@
59
61
  { "hunk_id": "<hunk_id>" }
60
62
  ```
61
63
 
64
+ 在这一步之前,prepare 结果还没有落盘;如果此时再次 `read_file`,读到的仍是旧内容。
65
+
62
66
  ## 示例
63
67
 
64
68
  - 末尾追加: