dominds 1.4.2 → 1.5.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 (171) hide show
  1. package/README.md +24 -0
  2. package/README.zh.md +24 -0
  3. package/dist/apps/app-json.js +38 -3
  4. package/dist/apps/dialog-run-controls.js +4 -0
  5. package/dist/apps/enabled-apps.js +8 -1
  6. package/dist/apps/installed-file.js +207 -0
  7. package/dist/apps/run-app-json.js +6 -6
  8. package/dist/apps/runtime-port.js +91 -0
  9. package/dist/apps/runtime.js +316 -68
  10. package/dist/apps-host/client.js +153 -3
  11. package/dist/apps-host/host.js +339 -2
  12. package/dist/apps-host/ipc-types.js +215 -30
  13. package/dist/cli/install.js +21 -1
  14. package/dist/dialog-fork.js +608 -0
  15. package/dist/dialog.js +2 -2
  16. package/dist/docs/app-constitution.md +153 -2
  17. package/dist/docs/app-constitution.zh.md +153 -2
  18. package/dist/docs/dialog-persistence.md +31 -0
  19. package/dist/docs/dialog-persistence.zh.md +31 -0
  20. package/dist/docs/dialog-system.md +29 -0
  21. package/dist/docs/dialog-system.zh.md +29 -0
  22. package/dist/docs/kernel-app-architecture.md +286 -0
  23. package/dist/docs/kernel-app-architecture.zh.md +285 -0
  24. package/dist/llm/defaults.yaml +16 -0
  25. package/dist/llm/driver-entry.js +28 -0
  26. package/dist/llm/driver-v2/context-health.js +121 -0
  27. package/dist/llm/driver-v2/context.js +56 -0
  28. package/dist/llm/driver-v2/core.js +1545 -0
  29. package/dist/llm/driver-v2/index.js +26 -0
  30. package/dist/llm/driver-v2/orchestrator.js +158 -0
  31. package/dist/llm/driver-v2/policy.js +129 -0
  32. package/dist/llm/driver-v2/restore-dialog-hierarchy.js +73 -0
  33. package/dist/llm/driver-v2/round.js +366 -0
  34. package/dist/llm/driver-v2/runtime-utils.js +365 -0
  35. package/dist/llm/driver-v2/saying-events.js +20 -0
  36. package/dist/llm/driver-v2/subdialog-txn.js +42 -0
  37. package/dist/llm/driver-v2/supdialog-response.js +400 -0
  38. package/dist/llm/driver-v2/tellask-bridge.js +1148 -0
  39. package/dist/llm/driver-v2/types.js +10 -0
  40. package/dist/llm/driver-v2-ref-only/context-health.js +121 -0
  41. package/dist/llm/driver-v2-ref-only/context.js +17 -0
  42. package/dist/llm/driver-v2-ref-only/core.js +1710 -0
  43. package/dist/llm/driver-v2-ref-only/index.js +26 -0
  44. package/dist/llm/driver-v2-ref-only/orchestrator.js +158 -0
  45. package/dist/llm/driver-v2-ref-only/policy.js +129 -0
  46. package/dist/llm/driver-v2-ref-only/restore-dialog-hierarchy.js +73 -0
  47. package/dist/llm/driver-v2-ref-only/round.js +366 -0
  48. package/dist/llm/driver-v2-ref-only/runtime-utils.js +473 -0
  49. package/dist/llm/driver-v2-ref-only/saying-events.js +18 -0
  50. package/dist/llm/driver-v2-ref-only/subdialog-txn.js +42 -0
  51. package/dist/llm/driver-v2-ref-only/supdialog-response.js +453 -0
  52. package/dist/llm/driver-v2-ref-only/tellask-bridge.js +1178 -0
  53. package/dist/llm/driver-v2-ref-only/types.js +10 -0
  54. package/dist/llm/gen/anthropic.js +68 -15
  55. package/dist/llm/gen/codex.js +59 -10
  56. package/dist/llm/gen/openai-compatible.js +38 -9
  57. package/dist/llm/gen/openai.js +58 -11
  58. package/dist/llm/gen/tool-output-limit.js +50 -0
  59. package/dist/llm/kernel-driver/subdialog.js +8 -1
  60. package/dist/llm/kernel-driver/tellask-special.js +18 -3
  61. package/dist/minds/load.js +7 -0
  62. package/dist/persistence.js +190 -28
  63. package/dist/priming.js +20 -1
  64. package/dist/server/api-routes.js +82 -0
  65. package/dist/server/setup-routes.js +15 -0
  66. package/dist/static/assets/{_basePickBy-B2o4z1Hf.js → _basePickBy-C-nynT9f.js} +3 -3
  67. package/dist/static/assets/{_basePickBy-B2o4z1Hf.js.map → _basePickBy-C-nynT9f.js.map} +1 -1
  68. package/dist/static/assets/{_baseUniq-CLmcxjdl.js → _baseUniq-CiHd-eVT.js} +2 -2
  69. package/dist/static/assets/{_baseUniq-CLmcxjdl.js.map → _baseUniq-CiHd-eVT.js.map} +1 -1
  70. package/dist/static/assets/{arc-CymD_KN7.js → arc-_OJzDWy1.js} +2 -2
  71. package/dist/static/assets/{arc-CymD_KN7.js.map → arc-_OJzDWy1.js.map} +1 -1
  72. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js → architectureDiagram-VXUJARFQ-CDEG85ub.js} +7 -7
  73. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DJQfSJUH.js.map → architectureDiagram-VXUJARFQ-CDEG85ub.js.map} +1 -1
  74. package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js → blockDiagram-VD42YOAC-1LzKVc5t.js} +7 -7
  75. package/dist/static/assets/{blockDiagram-VD42YOAC-pHVz60D0.js.map → blockDiagram-VD42YOAC-1LzKVc5t.js.map} +1 -1
  76. package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js → c4Diagram-YG6GDRKO-BzYnVyvY.js} +3 -3
  77. package/dist/static/assets/{c4Diagram-YG6GDRKO-B0WnCfAT.js.map → c4Diagram-YG6GDRKO-BzYnVyvY.js.map} +1 -1
  78. package/dist/static/assets/{channel-CX9BlKil.js → channel-VAEDAk9T.js} +2 -2
  79. package/dist/static/assets/{channel-CX9BlKil.js.map → channel-VAEDAk9T.js.map} +1 -1
  80. package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js → chunk-4BX2VUAB-D0r2u3mX.js} +2 -2
  81. package/dist/static/assets/{chunk-4BX2VUAB-lXArRj3o.js.map → chunk-4BX2VUAB-D0r2u3mX.js.map} +1 -1
  82. package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js → chunk-55IACEB6-Dkl8Xw7i.js} +2 -2
  83. package/dist/static/assets/{chunk-55IACEB6-CdqwynH9.js.map → chunk-55IACEB6-Dkl8Xw7i.js.map} +1 -1
  84. package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js → chunk-B4BG7PRW-9sxsI8ns.js} +5 -5
  85. package/dist/static/assets/{chunk-B4BG7PRW-Y-uXcJst.js.map → chunk-B4BG7PRW-9sxsI8ns.js.map} +1 -1
  86. package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js → chunk-DI55MBZ5-AHaqkaLl.js} +4 -4
  87. package/dist/static/assets/{chunk-DI55MBZ5-C5xSbRST.js.map → chunk-DI55MBZ5-AHaqkaLl.js.map} +1 -1
  88. package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js → chunk-FMBD7UC4-NWDLDixD.js} +2 -2
  89. package/dist/static/assets/{chunk-FMBD7UC4-5uefwCjI.js.map → chunk-FMBD7UC4-NWDLDixD.js.map} +1 -1
  90. package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js → chunk-QN33PNHL-C2KeUqle.js} +2 -2
  91. package/dist/static/assets/{chunk-QN33PNHL-DzWVcvpI.js.map → chunk-QN33PNHL-C2KeUqle.js.map} +1 -1
  92. package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js → chunk-QZHKN3VN-B6Eoxo5L.js} +2 -2
  93. package/dist/static/assets/{chunk-QZHKN3VN-BrrvAZdP.js.map → chunk-QZHKN3VN-B6Eoxo5L.js.map} +1 -1
  94. package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js → chunk-TZMSLE5B-Bc-VyQon.js} +2 -2
  95. package/dist/static/assets/{chunk-TZMSLE5B-DyKOlPTY.js.map → chunk-TZMSLE5B-Bc-VyQon.js.map} +1 -1
  96. package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js → classDiagram-2ON5EDUG-DmPfsN1H.js} +6 -6
  97. package/dist/static/assets/{classDiagram-2ON5EDUG-FCrnlCWC.js.map → classDiagram-2ON5EDUG-DmPfsN1H.js.map} +1 -1
  98. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js → classDiagram-v2-WZHVMYZB-DmPfsN1H.js} +6 -6
  99. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-FCrnlCWC.js.map → classDiagram-v2-WZHVMYZB-DmPfsN1H.js.map} +1 -1
  100. package/dist/static/assets/{clone-BlI81KqZ.js → clone-B1R4pLTW.js} +2 -2
  101. package/dist/static/assets/{clone-BlI81KqZ.js.map → clone-B1R4pLTW.js.map} +1 -1
  102. package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js → cose-bilkent-S5V4N54A-CxY__sKv.js} +2 -2
  103. package/dist/static/assets/{cose-bilkent-S5V4N54A-yM7S2atz.js.map → cose-bilkent-S5V4N54A-CxY__sKv.js.map} +1 -1
  104. package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js → dagre-6UL2VRFP-CPkB5tQ0.js} +7 -7
  105. package/dist/static/assets/{dagre-6UL2VRFP-BcweuZHt.js.map → dagre-6UL2VRFP-CPkB5tQ0.js.map} +1 -1
  106. package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js → diagram-PSM6KHXK-C6kCVpCz.js} +8 -8
  107. package/dist/static/assets/{diagram-PSM6KHXK-D4-QwLW1.js.map → diagram-PSM6KHXK-C6kCVpCz.js.map} +1 -1
  108. package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js → diagram-QEK2KX5R-BWF6htf1.js} +7 -7
  109. package/dist/static/assets/{diagram-QEK2KX5R-BVbuejJn.js.map → diagram-QEK2KX5R-BWF6htf1.js.map} +1 -1
  110. package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js → diagram-S2PKOQOG-lKGJH6O9.js} +7 -7
  111. package/dist/static/assets/{diagram-S2PKOQOG-pB6N6Tq_.js.map → diagram-S2PKOQOG-lKGJH6O9.js.map} +1 -1
  112. package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js → erDiagram-Q2GNP2WA-DJ3YaFob.js} +5 -5
  113. package/dist/static/assets/{erDiagram-Q2GNP2WA-DLKmthuw.js.map → erDiagram-Q2GNP2WA-DJ3YaFob.js.map} +1 -1
  114. package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js → flowDiagram-NV44I4VS-h3eQwA3O.js} +6 -6
  115. package/dist/static/assets/{flowDiagram-NV44I4VS-BsBhWukh.js.map → flowDiagram-NV44I4VS-h3eQwA3O.js.map} +1 -1
  116. package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js → ganttDiagram-JELNMOA3-BCbsDOF_.js} +3 -3
  117. package/dist/static/assets/{ganttDiagram-JELNMOA3-Debz-J-C.js.map → ganttDiagram-JELNMOA3-BCbsDOF_.js.map} +1 -1
  118. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js} +8 -8
  119. package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-BnAPFBGR.js.map → gitGraphDiagram-V2S2FVAM-D0kX6h-T.js.map} +1 -1
  120. package/dist/static/assets/{graph-DbzWiBNK.js → graph-CZIEXp3A.js} +3 -3
  121. package/dist/static/assets/{graph-DbzWiBNK.js.map → graph-CZIEXp3A.js.map} +1 -1
  122. package/dist/static/assets/{index-B-8J28g7.js → index-vIzCTZQE.js} +156 -35
  123. package/dist/static/assets/index-vIzCTZQE.js.map +1 -0
  124. package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js → infoDiagram-HS3SLOUP-DUNbcXxv.js} +6 -6
  125. package/dist/static/assets/{infoDiagram-HS3SLOUP-CZ5hWoxV.js.map → infoDiagram-HS3SLOUP-DUNbcXxv.js.map} +1 -1
  126. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js} +5 -5
  127. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-CKN3oSxk.js.map → journeyDiagram-XKPGCS4Q-Cg_VhiqB.js.map} +1 -1
  128. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js → kanban-definition-3W4ZIXB7-DMVCZVFE.js} +3 -3
  129. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BQCMklfJ.js.map → kanban-definition-3W4ZIXB7-DMVCZVFE.js.map} +1 -1
  130. package/dist/static/assets/{layout-C5B58szc.js → layout-DoKTmwlM.js} +5 -5
  131. package/dist/static/assets/{layout-C5B58szc.js.map → layout-DoKTmwlM.js.map} +1 -1
  132. package/dist/static/assets/{linear-_32fut6G.js → linear-DFVlPfX6.js} +2 -2
  133. package/dist/static/assets/{linear-_32fut6G.js.map → linear-DFVlPfX6.js.map} +1 -1
  134. package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js → mindmap-definition-VGOIOE7T-l5K7agVV.js} +4 -4
  135. package/dist/static/assets/{mindmap-definition-VGOIOE7T-C_goMzjx.js.map → mindmap-definition-VGOIOE7T-l5K7agVV.js.map} +1 -1
  136. package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js → pieDiagram-ADFJNKIX-BfQzSE-A.js} +8 -8
  137. package/dist/static/assets/{pieDiagram-ADFJNKIX-BQ2n0cOB.js.map → pieDiagram-ADFJNKIX-BfQzSE-A.js.map} +1 -1
  138. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js → quadrantDiagram-AYHSOK5B-CJWvA5jc.js} +3 -3
  139. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-BLg7_neg.js.map → quadrantDiagram-AYHSOK5B-CJWvA5jc.js.map} +1 -1
  140. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js → requirementDiagram-UZGBJVZJ-CeBbmqBK.js} +4 -4
  141. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-DwkJt0zi.js.map → requirementDiagram-UZGBJVZJ-CeBbmqBK.js.map} +1 -1
  142. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js → sankeyDiagram-TZEHDZUN-JeUBTDxx.js} +2 -2
  143. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DmxmatUB.js.map → sankeyDiagram-TZEHDZUN-JeUBTDxx.js.map} +1 -1
  144. package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js} +4 -4
  145. package/dist/static/assets/{sequenceDiagram-WL72ISMW-KHU_eApU.js.map → sequenceDiagram-WL72ISMW-Bd_7Pgc5.js.map} +1 -1
  146. package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js → stateDiagram-FKZM4ZOC-D_WyM3K1.js} +9 -9
  147. package/dist/static/assets/{stateDiagram-FKZM4ZOC-B3DBCxAL.js.map → stateDiagram-FKZM4ZOC-D_WyM3K1.js.map} +1 -1
  148. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js} +5 -5
  149. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-C-uIk7gh.js.map → stateDiagram-v2-4FDKWEC3-Q_yh26yx.js.map} +1 -1
  150. package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js → timeline-definition-IT6M3QCI-Ca8mCFDg.js} +3 -3
  151. package/dist/static/assets/{timeline-definition-IT6M3QCI-SysEcQCC.js.map → timeline-definition-IT6M3QCI-Ca8mCFDg.js.map} +1 -1
  152. package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js → treemap-GDKQZRPO-CyBvKC8o.js} +5 -5
  153. package/dist/static/assets/{treemap-GDKQZRPO-d0AbKEc4.js.map → treemap-GDKQZRPO-CyBvKC8o.js.map} +1 -1
  154. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js → xychartDiagram-PRI3JC2R-DY0BLEdj.js} +3 -3
  155. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CmSQMxUh.js.map → xychartDiagram-PRI3JC2R-DY0BLEdj.js.map} +1 -1
  156. package/dist/static/index.html +1 -1
  157. package/dist/team.js +33 -4
  158. package/dist/tools/app-reminders.js +280 -0
  159. package/dist/tools/prompts/memory/en/errors.md +155 -0
  160. package/dist/tools/prompts/memory/en/index.md +47 -0
  161. package/dist/tools/prompts/memory/en/principles.md +79 -0
  162. package/dist/tools/prompts/memory/en/scenarios.md +174 -0
  163. package/dist/tools/prompts/memory/en/tools.md +154 -0
  164. package/dist/tools/prompts/memory/zh/errors.md +155 -0
  165. package/dist/tools/prompts/memory/zh/index.md +47 -0
  166. package/dist/tools/prompts/memory/zh/principles.md +79 -0
  167. package/dist/tools/prompts/memory/zh/scenarios.md +174 -0
  168. package/dist/tools/prompts/memory/zh/tools.md +154 -0
  169. package/dist/tools/ripgrep.js +197 -63
  170. package/package.json +2 -2
  171. package/dist/static/assets/index-B-8J28g7.js.map +0 -1
@@ -34,7 +34,7 @@ This document uses **A/B/C/D** to describe the evolution phases of this feature.
34
34
  Goal: make the kernel/app boundary and the minimal data flow runnable, so the install/resolve/boot path can be validated.
35
35
 
36
36
  - Key capabilities (at minimum):
37
- - App install handshake (`<app> --json`) can be consumed by the kernel/CLI.
37
+ - App install handshake (`<app> --dominds-app`) can be consumed by the kernel/CLI.
38
38
  - App manifest (`.minds/app.yaml`) schema/loader is available.
39
39
  - Basic local resolution strategy (`local`) works: discover local apps under `<rtws>/dominds-apps/<appId>/`.
40
40
 
@@ -168,7 +168,7 @@ Key semantics:
168
168
  - `<rtws>/.apps/resolution.yaml` can pin an `assignedPort` as a stable resolved config; **if present it must be non-zero** (anti-jitter).
169
169
  - `assignedPort` is not the runtime “bound port”; it is the resolver’s stable config output.
170
170
 
171
- ### Install JSON (`npx <pkg> --json`)
171
+ ### Install JSON (`npx <pkg> --dominds-app`)
172
172
 
173
173
  (Target: planned) Install JSON should avoid overlapping with the manifest (`.minds/app.yaml`).
174
174
 
@@ -179,6 +179,20 @@ Recommended principles:
179
179
  - Install JSON carries only the minimal fields required for locating caches and reading the manifest.
180
180
  - Capability inventory (teammates/tools/web/seed, etc.) must be **manifest-only**, to avoid drift from dual-writing.
181
181
 
182
+ User-facing installation and the low-level handshake must stay clearly separated:
183
+
184
+ - The **user-facing install entrypoint** should be `dominds install <spec>`, not `npx <pkg> --dominds-app`.
185
+ - `--dominds-app` is a **kernel/CLI-to-app handshake flag** used by Dominds to retrieve install JSON. It is not meant to be the ordinary human-facing UX.
186
+ - For published apps, the kernel/CLI may resolve install JSON through `npx -y <pkg> --dominds-app` during resolution.
187
+ - For local apps under development, the kernel/CLI may call the local package bin through `dominds install <path> --local`, still passing the same `--dominds-app` handshake flag underneath.
188
+ - `npm install` / `pnpm add` only answers “where is the package downloaded/cached”. They do **not** register an app into the current rtws by themselves. The operation that actually adds the app into the current workspace dependency graph is still `dominds install`.
189
+
190
+ Recommended user mental model:
191
+
192
+ - `npm` / `pnpm`: package managers responsible for publishing, downloading, and caching.
193
+ - `npx`: one-shot execution of an npm package entrypoint; in the app system it mainly serves as the kernel's resolution/handshake backend.
194
+ - `dominds install`: the product-level Dominds command that updates `.minds/app.yaml`, `.minds/app-lock.yaml`, `<rtws>/.apps/configuration.yaml`, and `<rtws>/.apps/resolution.yaml`, making the app actually part of the current rtws capability graph.
195
+
182
196
  (Current: implemented) existing anchors:
183
197
 
184
198
  - JSON schema: `dominds/main/apps/app-json.ts` (`DomindsAppInstallJsonV1`).
@@ -243,6 +257,143 @@ Key semantics:
243
257
  - The kernel must not implicitly write `env.md` into shell rc or environment.
244
258
  - If the kernel offers “write managed rc block” (e.g. setup flow), it must be explicit and user-confirmed.
245
259
 
260
+ ### Reference design: Web Dev App (replacing the old prototype-app narrative)
261
+
262
+ Instead of continuing to discuss app semantics around an accidental prototype, this document now uses a more durable reference design: **Web Dev App**.
263
+
264
+ Its goal is not to represent one specific product. Its goal is to provide a high-frequency, easy-to-validate app shape:
265
+
266
+ - focused on web development and browser regression work,
267
+ - packaging browser interaction capability as an explicit toolset,
268
+ - shipping a minimal but complete team with at least `web_tester` and `web_developer`.
269
+
270
+ Design stance:
271
+
272
+ - `Web Dev App` is an **integrator-style app**. The important part is the packaging of team, toolsets, environment guidance, and workflow posture, not a demo business frontend.
273
+ - It should reuse existing capabilities where possible instead of inventing a new browser automation protocol inside the app.
274
+ - The current upstream capability to learn from is the repo-root `playwright-interactive/` skill. That skill is better understood as a workflow/method asset, not as a ready-to-install Dominds MCP server.
275
+
276
+ So `Web Dev App` should make the `playwright-interactive` relationship explicit as two separate layers:
277
+
278
+ 1. **Product-semantic layer (in scope for this design)**
279
+ - define a stable toolset semantic such as `playwright_interactive`;
280
+ - define which teammates receive it, what problem it solves, and when to use it;
281
+ - ship the related `.minds/team.yaml`, member persona/knowledge, `.minds/env.md`, etc.
282
+ 2. **Execution-backend layer (replaceable implementation detail)**
283
+ - this may wrap the `playwright-interactive` skill into app-host tools;
284
+ - or later be replaced by an equivalent MCP server / local host module;
285
+ - as long as the team-facing toolset contract does not drift.
286
+
287
+ It must be explicit that **an app is not the same thing as a skill**:
288
+
289
+ - An **app** is a Dominds install/resolve/composition unit. It has an `id`, a manifest (`.minds/app.yaml`), team-facing assets (`.minds/team.yaml`, persona/knowledge/lessons), env docs (`.minds/env.md`), and participates in rtws-level lock/configuration/resolution.
290
+ - A **skill** is closer to a workflow asset, method asset, or low-level execution material. A skill can be reused, wrapped, or replaced by an app, but it usually does not own rtws installation, dependency graph membership, or `team.yaml` import semantics by itself.
291
+ - `playwright-interactive/` is currently closer to a skill: it provides browser-workflow capability that Web Dev can learn from or wrap. `Web Dev App` is the installable product unit that packages those capabilities into a stable team/toolset/env contract.
292
+
293
+ So the correct story is not “install a skill as an app”. The correct story is:
294
+
295
+ - the skill is absorbed as implementation material by an app,
296
+ - the app exposes a stable team-facing contract,
297
+ - the low-level skill / MCP / host-module backend can change later without changing the app identity or team-facing semantics.
298
+
299
+ Suggested user-facing installation flow:
300
+
301
+ ```bash
302
+ # Local app under development
303
+ dominds install ./dominds-apps/web-dev --local --enable
304
+
305
+ # Published npm app (target shape)
306
+ dominds install @longrun-ai/web-dev --enable
307
+ ```
308
+
309
+ After installation, the user should expect these files to change:
310
+
311
+ - `.minds/app.yaml`: root dependency declaration is updated.
312
+ - `.minds/app-lock.yaml`: app package version is frozen.
313
+ - `<rtws>/.apps/configuration.yaml`: explicit enable/disable intent is recorded.
314
+ - `<rtws>/.apps/resolution.yaml`: effective source, enabled state, and stable `assignedPort` are materialized.
315
+
316
+ Suggested minimal asset shape:
317
+
318
+ ```text
319
+ web-dev/
320
+ ├── package.json
321
+ ├── .minds/
322
+ │ ├── app.yaml
323
+ │ ├── team.yaml
324
+ │ ├── env.md
325
+ │ ├── app-lock.yaml
326
+ │ └── team/
327
+ │ ├── web_tester/
328
+ │ │ ├── persona.zh.md
329
+ │ │ ├── knowledge.zh.md
330
+ │ │ └── lessons.zh.md
331
+ │ └── web_developer/
332
+ │ ├── persona.zh.md
333
+ │ ├── knowledge.zh.md
334
+ │ └── lessons.zh.md
335
+ └── src/
336
+ └── app-host.ts
337
+ ```
338
+
339
+ Suggested team shape:
340
+
341
+ - `web_tester`
342
+ - primary responsibility: run browser interaction, perform regression walkthroughs, collect screenshot/console/network evidence;
343
+ - default toolsets: `playwright_interactive` plus read-only workspace tools such as `ws_read`;
344
+ - non-goal: does not directly edit product code or take over build/process management.
345
+ - `web_developer`
346
+ - primary responsibility: implement UI/interaction fixes, consume `web_tester` findings, and close the loop;
347
+ - default toolsets: code-edit/search tools such as `codex_style_tools` (or equivalent) plus optional access to read tester evidence;
348
+ - non-goal: should not blur browser acceptance into an implicit “I also tested it” posture; when acceptance is needed, it should explicitly tell/ask `web_tester`.
349
+
350
+ Suggested `team.yaml` fragment:
351
+
352
+ ```yaml
353
+ members:
354
+ web_tester:
355
+ name: Web Tester
356
+ icon: '🧪'
357
+ toolsets:
358
+ - ws_read
359
+ - playwright_interactive
360
+
361
+ web_developer:
362
+ name: Web Developer
363
+ icon: '🛠️'
364
+ toolsets:
365
+ - ws_read
366
+ - codex_style_tools
367
+ ```
368
+
369
+ Requirements for the `playwright_interactive` toolset design:
370
+
371
+ - It should be treated as a **stable team-facing capability name**, not as a hard-coded implementation detail tied forever to one backend.
372
+ - At minimum it should cover these task intents:
373
+ - open/reuse a browser session,
374
+ - navigate to a target URL,
375
+ - perform interaction and assertions,
376
+ - capture screenshots and key debugging evidence,
377
+ - preserve the “reusable session across multiple fix iterations” mental model.
378
+ - If the current phase does not yet ship a directly executable backend, the docs must label it as a **target contract (planned)** instead of pretending it is already built in.
379
+
380
+ Current prototype note (`dominds-apps/web-dev`, as of March 8, 2026):
381
+
382
+ - The app is already installable and contributes `web_tester` / `web_developer` teammates plus a live `playwright_interactive` toolset registration.
383
+ - `playwright_session_new/list/status/eval/attach/detach/close` and cross-dialog reminder sync are already implemented.
384
+ - `kind: "web"` sessions now create a real Playwright-backed browser/context/page runtime and report live page surfaces via session status/reminders.
385
+ - `kind: "electron"` is **not** at the same completion level yet: it still falls back to the older prototype runtime path and should be treated as unfinished.
386
+ - Reminder UX contract: tool output may summarize reminder-sync actions, but the reminder panel is the authoritative surface for attachment state.
387
+ - Runtime refresh contract: after enabling the app, a full Dominds instance restart should not be required just to discover the toolset; the next minds reload / tools-registry fetch should refresh enabled app tool proxies. This does **not** mean in-flight prompts are rewritten retroactively.
388
+ - Remaining gap list for the browser capability layer: screenshot / console / network evidence are not yet exposed as first-class tool outputs, and there is not yet a production-grade browser lifecycle manager.
389
+ - Restart boundary: if the kernel/apps-host process restarts, persisted session records remain but the in-memory browser runtime degrades and must be recreated.
390
+
391
+ Why this app shape matters:
392
+
393
+ - It makes `.minds/team.yaml` collaboration semantics concrete: development and testing are two long-lived teammates, not vague temporary roles.
394
+ - It validates whether “app provides team + toolset + env docs” is expressive enough for a real workflow.
395
+ - It gives future skill/MCP/local-host convergence a stable semantic anchor at the app layer.
396
+
246
397
  ## `<rtws>/.apps/override/<app-id>/`: override layer
247
398
 
248
399
  ### Override root
@@ -33,7 +33,7 @@
33
33
  目标:把 Kernel/App 的边界与最小数据流跑通,让“安装/解析/启动路径”可被验证。
34
34
 
35
35
  - 关键能力(至少):
36
- - App 的 install handshake(`<app> --json`)可被 Kernel/CLI 读取。
36
+ - App 的 install handshake(`<app> --dominds-app`)可被 Kernel/CLI 读取。
37
37
  - App manifest(`.minds/app.yaml`)schema/loader 可用。
38
38
  - 基本的本地解析策略(`local`)可工作:按 `<rtws>/dominds-apps/<appId>/` 发现本地 app。
39
39
 
@@ -167,7 +167,7 @@ rtws 是一次运行的工作区根目录(`process.cwd()`)。Kernel 在其
167
167
  - `<rtws>/.apps/resolution.yaml` 中的 `assignedPort` 用于“固化后的解析配置”,一旦存在则必须为**非 0**端口(用于防抖动)。
168
168
  - `assignedPort` 不等同于运行时“实际绑定端口(bound port)”;它是 resolver 产出的稳定配置。
169
169
 
170
- ### Install JSON(`npx <pkg> --json`)
170
+ ### Install JSON(`npx <pkg> --dominds-app`)
171
171
 
172
172
  (目标:拟实现)Install JSON 应避免与 manifest(`.minds/app.yaml`)内容重叠。
173
173
 
@@ -178,6 +178,20 @@ rtws 是一次运行的工作区根目录(`process.cwd()`)。Kernel 在其
178
178
  - Install JSON 只承载“定位与缓存”所需的最小字段。
179
179
  - App 的能力清单(teammates/tools/web/seed 等)**只以 manifest 为准**,避免双写导致漂移。
180
180
 
181
+ 用户路径与底层机制应明确区分:
182
+
183
+ - **用户安装入口** 应是 `dominds install <spec>`,而不是要求用户自己执行 `npx <pkg> --dominds-app`。
184
+ - `--dominds-app` 是 **Kernel/CLI 与 app 包之间的握手参数**,用于让 Dominds 读取 app install JSON;它不是面向终端用户的常规操作界面。
185
+ - 对已发布 app:Kernel/CLI 可以在解析阶段通过 `npx -y <pkg> --dominds-app` 获取 install JSON。
186
+ - 对本地开发中的 app:Kernel/CLI 可以通过 `dominds install <path> --local` 调用本地包的 bin,并传入 `--dominds-app` 完成同一握手。
187
+ - `npm install` / `pnpm add` 只解决“包被下载到哪里”;它们**不会**自动把 app 注册到当前 rtws。把 app 纳入当前 workspace 依赖图的动作仍然是 `dominds install`。
188
+
189
+ 建议的用户心智模型:
190
+
191
+ - `npm` / `pnpm`:包管理器,负责发布、下载、缓存。
192
+ - `npx`:一次性执行某个 npm package 的入口;在 app 体系里主要作为 Kernel 的解析/握手后端。
193
+ - `dominds install`:Dominds 的产品级安装命令,负责把 app 写入 `.minds/app.yaml`、更新 `.minds/app-lock.yaml`、刷新 `<rtws>/.apps/configuration.yaml` / `resolution.yaml`,并让该 app 真正进入当前 rtws 的能力图。
194
+
181
195
  (现状:已实现)install json schema 与 apps 配置/解析锚点仍可参考:
182
196
 
183
197
  - JSON schema:`dominds/main/apps/app-json.ts`(`DomindsAppInstallJsonV1`)。
@@ -241,6 +255,143 @@ rtws 是一次运行的工作区根目录(`process.cwd()`)。Kernel 在其
241
255
  - Kernel 不应自动把 `env.md` 写入 shell rc 或环境;它只提供可见性(文档/提示)。
242
256
  - 若 Kernel 提供“写入 rc managed block”的能力(例如 setup flow),也应基于明确的 UI/确认,而不是隐式执行。
243
257
 
258
+ ### 参考设计:Web Dev App(替代旧的原型 app 叙事)
259
+
260
+ 为了避免继续围绕一个过于偶然的原型 app 收敛语义,本文改用一个更直接、可长期演进的参考设计:**Web Dev App**。
261
+
262
+ 它的目标不是“代表某个具体产品”,而是提供一个高频、通用、容易验证的 app 形态:
263
+
264
+ - 面向 Web 开发与浏览器回归。
265
+ - 把浏览器交互能力包装成一个明确的 toolset。
266
+ - 自带一支最小但完整的团队:至少 `web_tester` 与 `web_developer`。
267
+
268
+ 设计口径:
269
+
270
+ - `Web Dev App` 是一个 **integrator-style app**:重点是封装团队、工具集、环境说明与工作方式,而不是炫耀某个业务前端。
271
+ - 它应优先复用已有能力,而不是在 app 内重复发明一套浏览器自动化协议。
272
+ - 当前可参考的上游能力是仓库根目录的 `playwright-interactive/` skill;该 skill 更像“工作流/方法学资产”,不是可直接作为 Dominds MCP server 安装的现成 server。
273
+
274
+ 因此,`Web Dev App` 对 `playwright-interactive` 的定位应明确分成两层:
275
+
276
+ 1. **产品语义层(本次设计范围)**:
277
+ - 定义一个稳定的 toolset 语义,例如 `playwright_interactive`。
278
+ - 规定哪些成员拿到这个 toolset、它解决什么问题、什么时候用。
279
+ - 配套 `.minds/team.yaml`、成员 persona/knowledge、`.minds/env.md` 等资产。
280
+ 2. **执行后端层(后续实现可替换)**:
281
+ - 可以是把 `playwright-interactive` skill 包装成 app-host tools;
282
+ - 也可以是未来替换成等价的 MCP server / 本地 host module;
283
+ - 只要对 team.yaml 暴露的 toolset 契约不漂移即可。
284
+
285
+ 这里必须明确 **app 与 skill 不是同一层概念**:
286
+
287
+ - **App** 是 Dominds 的安装/解析/组合单元:它有自己的 `id`、manifest(`.minds/app.yaml`)、团队资产(`.minds/team.yaml`、persona/knowledge/lessons)、环境说明(`.minds/env.md`),并可被 `dominds install` 纳入某个 rtws。
288
+ - **Skill** 更像工作流资产、方法学资产,或某个底层执行能力的封装材料。它可以被 app 复用、包装、替换,但通常不直接承担“被 workspace 安装、被 team.yaml 引用、被 resolution/lock 管理”的职责。
289
+ - `playwright-interactive/` 当前更接近 skill:它提供可借鉴或可包装的浏览器工作流能力,但 `Web Dev App` 才是把这些能力整合成“可安装产品单元”的实体。
290
+
291
+ 因此,正确表述不是“把一个 skill 直接当 app 安装”,而是:
292
+
293
+ - skill 作为实现材料被 app 吸纳;
294
+ - app 对外暴露稳定的 team/toolset/env 契约;
295
+ - 底层 skill / MCP / host module 可以替换,但 app 身份与 team-facing contract 应保持稳定。
296
+
297
+ 建议安装流程(面向用户):
298
+
299
+ ```bash
300
+ # 本地开发态 app
301
+ dominds install ./dominds-apps/web-dev --local --enable
302
+
303
+ # 已发布到 npm 的 app(目标形态)
304
+ dominds install @longrun-ai/web-dev --enable
305
+ ```
306
+
307
+ 安装完成后,用户应预期以下文件发生变化:
308
+
309
+ - `.minds/app.yaml`:增加根依赖声明。
310
+ - `.minds/app-lock.yaml`:冻结 app package 版本。
311
+ - `<rtws>/.apps/configuration.yaml`:记录用户显式 enable/disable 意图。
312
+ - `<rtws>/.apps/resolution.yaml`:记录实际来源、effective enabled 与稳定 `assignedPort`。
313
+
314
+ 建议的最小资产形态:
315
+
316
+ ```text
317
+ web-dev/
318
+ ├── package.json
319
+ ├── .minds/
320
+ │ ├── app.yaml
321
+ │ ├── team.yaml
322
+ │ ├── env.md
323
+ │ ├── app-lock.yaml
324
+ │ └── team/
325
+ │ ├── web_tester/
326
+ │ │ ├── persona.zh.md
327
+ │ │ ├── knowledge.zh.md
328
+ │ │ └── lessons.zh.md
329
+ │ └── web_developer/
330
+ │ ├── persona.zh.md
331
+ │ ├── knowledge.zh.md
332
+ │ └── lessons.zh.md
333
+ └── src/
334
+ └── app-host.ts
335
+ ```
336
+
337
+ 建议的团队形态:
338
+
339
+ - `web_tester`
340
+ - 主要职责:运行浏览器交互、回归走查、收集截图/console/network 证据。
341
+ - 默认工具集:`playwright_interactive` + 只读型 workspace 工具(如 `ws_read`)。
342
+ - 非目标:不直接修改业务代码;不接管构建/进程管理。
343
+ - `web_developer`
344
+ - 主要职责:实现页面/UI/交互修复,消费 `web_tester` 的缺陷报告并完成闭环。
345
+ - 默认工具集:代码修改/检索工具(如 `codex_style_tools` 或等价工具)+ 可选读取 `web_tester` 产出的证据。
346
+ - 非目标:不把浏览器验收职责模糊地“顺手做掉”;需要时应显式 tellask `web_tester` 做验收。
347
+
348
+ 建议的 `team.yaml` 片段:
349
+
350
+ ```yaml
351
+ members:
352
+ web_tester:
353
+ name: Web Tester
354
+ icon: '🧪'
355
+ toolsets:
356
+ - ws_read
357
+ - playwright_interactive
358
+
359
+ web_developer:
360
+ name: Web Developer
361
+ icon: '🛠️'
362
+ toolsets:
363
+ - ws_read
364
+ - codex_style_tools
365
+ ```
366
+
367
+ 关于 `playwright_interactive` toolset 的设计要求:
368
+
369
+ - 它应被视为 **app 暴露给 team 的稳定能力名**,而不是强绑定某个底层实现细节(skill / MCP / app-host)。
370
+ - 它应至少覆盖以下任务意图:
371
+ - 打开/复用浏览器会话。
372
+ - 导航到目标 URL。
373
+ - 执行交互与断言。
374
+ - 采集截图与关键调试证据。
375
+ - 在多轮修复之间保持“可复用会话”的心智模型。
376
+ - 如果当前阶段还没有可直接执行的后端实现,文档必须明确标注为“目标契约(拟实现)”,而不是宣称已经内建完成。
377
+
378
+ 当前 prototype 说明(`dominds-apps/web-dev`,截至 2026-03-08):
379
+
380
+ - 该 app 已可安装,并已贡献 `web_tester` / `web_developer` teammate 与可用的 `playwright_interactive` toolset 注册。
381
+ - `playwright_session_new/list/status/eval/attach/detach/close` 与跨对话 reminder sync 已落地。
382
+ - `kind: "web"` 会话现在会创建真实的 Playwright browser/context/page runtime,并通过 status/reminder 报告实时页面 surface。
383
+ - `kind: "electron"` 还没有达到同等完成度:当前仍回落到旧的 prototype runtime 路径,应视为未完成能力。
384
+ - reminder 体验契约:tool 输出可以摘要提示 reminder-sync 动作,但 attachment state 的权威可见面仍是 reminder 面板本身。
385
+ - runtime 刷新契约:app 启用后,不应再要求为了“看见 toolset”而整实例重启;下一次 minds reload / tools-registry fetch 应刷新 enabled app tool proxies。但这 **不表示** 已经发出的 in-flight prompt 会被追写更新。
386
+ - 浏览器能力层的剩余缺口:截图 / console / network 证据尚未作为一等 tool output 暴露,也还没有生产级浏览器生命周期管理器。
387
+ - 重启边界:若 kernel/apps-host 进程重启,已持久化的 session record 仍在,但内存态浏览器 runtime 会退化,需要后续 tool call 重新建立。
388
+
389
+ 这类 app 的价值在于:
390
+
391
+ - 它让 `.minds/team.yaml` 的跨成员协作语义更具体:开发与测试天然是两个长期 agent,而不是临时角色描述。
392
+ - 它验证“app 提供团队 + toolset + env 文档”的组合是否足够表达一个真实工作流。
393
+ - 它为后续把 skill/MCP/本地 host module 统一到同一个 app 语义层提供了稳定锚点。
394
+
244
395
  ## `<rtws>/.apps/override/<app-id>/`:覆盖层
245
396
 
246
397
  ### 覆盖层目录(override root)
@@ -300,6 +300,37 @@ Simple text file containing the current course number:
300
300
  }
301
301
  ```
302
302
 
303
+ ### Root-generation anchors and reconciliation records
304
+
305
+ To support root dialog fork, persistence now records which root-generation viewpoint a piece of dialog state belongs to.
306
+
307
+ **Root-generation anchor**:
308
+
309
+ - `rootCourse`
310
+ - `rootGenseq`
311
+
312
+ **Purpose**:
313
+
314
+ - Any state snapshot that must stay aligned across the entire root dialog tree must be anchored to the root generation rather than each subdialog's local course/genseq
315
+ - When forking at `(course, genseq)`, the retained state is the latest consistent snapshot at or before `(rootCourse=course, rootGenseq=genseq-1)`
316
+
317
+ **New / strengthened persisted records**:
318
+
319
+ - `subdialog_created_record`
320
+ - persisted in the root transcript
321
+ - marks when a subdialog already exists on the root timeline, so fork can decide whether to include it
322
+ - `reminders_reconciled_record`
323
+ - `questions4human_reconciled_record`
324
+ - `pending_subdialogs_reconciled_record`
325
+ - `subdialog_registry_reconciled_record`
326
+ - `subdialog_responses_reconciled_record`
327
+
328
+ **Required behavior**:
329
+
330
+ - These reconciliation records are state snapshots, not LLM transcript content; message reconstruction must skip them
331
+ - Any subdialog transcript record that participates in root-fork cutoff trimming must carry `rootCourse/rootGenseq`
332
+ - When writing a forked root, persistence appends a baseline reconciliation set into `course-1` so reminders / Q4H / pending subdialogs / registry / responses are restored to the pre-cutoff state
333
+
303
334
  ---
304
335
 
305
336
  ## Memory Persistence
@@ -297,6 +297,37 @@ status: 'active' # 当前对话状态
297
297
  }
298
298
  ```
299
299
 
300
+ ### Root generation 锚点与状态对账记录
301
+
302
+ 为支持 root dialog fork,持久化层现在显式记录“某条数据对应的是哪一个 root generation 视角”。
303
+
304
+ **Root generation 锚点**:
305
+
306
+ - `rootCourse`
307
+ - `rootGenseq`
308
+
309
+ **用途**:
310
+
311
+ - 所有需要跨整棵 root tree 对齐的状态快照,都必须绑定到 root generation,而不是各自子对话的本地 course/genseq
312
+ - root fork 在切点 `(course, genseq)` 时,实际保留的是**不晚于** `(rootCourse=course, rootGenseq=genseq-1)` 的最后一个一致快照
313
+
314
+ **新增/强化的持久化记录**:
315
+
316
+ - `subdialog_created_record`
317
+ - 持久化在 root transcript 中
318
+ - 记录某个子对话何时在 root 时间线上已“存在”,供 fork 时判断是否应纳入新树
319
+ - `reminders_reconciled_record`
320
+ - `questions4human_reconciled_record`
321
+ - `pending_subdialogs_reconciled_record`
322
+ - `subdialog_registry_reconciled_record`
323
+ - `subdialog_responses_reconciled_record`
324
+
325
+ **规范要求**:
326
+
327
+ - 这些对账记录是状态快照,不属于 LLM transcript 内容;重建消息上下文时应跳过
328
+ - 子对话 transcript 中凡是需要参与 root fork 边界裁剪的记录,都必须带 `rootCourse/rootGenseq`
329
+ - fork 写入新 root 时,会在 `course-1` 追加一组 baseline 对账记录,用来把 reminders / Q4H / pending subdialogs / registry / responses 恢复到切点前状态
330
+
300
331
  ---
301
332
 
302
333
  ## 记忆持久化
@@ -979,6 +979,35 @@ Frontend twin must stay in sync: `dominds/webapp/src/shared/utils/inter-dialog-f
979
979
 
980
980
  **Registry**: Registered subdialogs (TYPE B Tellasks) are tracked in the root dialog's registry and persist across restarts.
981
981
 
982
+ ### Root dialog fork
983
+
984
+ An entire root dialog tree can be forked at the start of a chosen root generation into a brand-new root dialog. This is used to preserve prior context while re-running the later mainline/sideline path from a historical branch point.
985
+
986
+ **Entry points**:
987
+
988
+ - UI shows `Fork dialog` only on generation bubbles of a root dialog (`selfId === rootId`)
989
+ - Backend API: `POST /api/dialogs/:rootId/fork`
990
+ - Request body: `{ course, genseq, status? }`
991
+
992
+ **Semantics (required)**:
993
+
994
+ - The selected generation bubble is **not** copied into the forked root; the fork point means "branch immediately before this generation starts"
995
+ - The copy scope is the **entire root dialog tree**, not just one dialog
996
+ - A subdialog is included only if the root had already persisted it as created before the cutoff
997
+ - Subdialog transcript retention is bounded by the root-generation anchor, not by the subdialog's local `genseq`
998
+
999
+ **Post-fork actions** (returned by backend to UI):
1000
+
1001
+ - `draft_user_text`: if the target generation is a user message, prefill that text into the new dialog input and wait for user confirmation
1002
+ - `restore_pending`: if there were pending Q4H or pending subdialogs before the cutoff, restore those blocking states in the new root
1003
+ - `auto_continue`: if there is no pending blocker before the cutoff, initialize the new root as `interrupted(system_stop: fork_dialog_continue)` and have UI immediately send `resume_dialog`
1004
+
1005
+ **Consistency requirements**:
1006
+
1007
+ - Fork must preserve the same Taskdoc reference
1008
+ - The forked root and all forked subdialogs are persisted under `running/` with a new rootId
1009
+ - Frontend must not expose this entry for sideline dialogs; current implementation supports root dialogs only
1010
+
982
1011
  ### Lifecycle Management
983
1012
 
984
1013
  **Active State**: Dialogs remain active while agents are working on tasks.
@@ -949,6 +949,35 @@ interface RegistryMethods {
949
949
 
950
950
  **注册表**:已注册的子对话(TYPE B Tellask)在根对话的注册表中跟踪,并在重启后持久化;若子对话被宣布卡死,其条目会被裁剪,不再参与后续同 slug 复用。
951
951
 
952
+ ### Root dialog fork(根对话分叉)
953
+
954
+ 运行中的一个完整 root dialog tree 可以在某个 root generation 起点处被 fork 成新的 root dialog。该能力用于“保留此前上下文,但从某个历史分叉点重新走后续主线/支线”。
955
+
956
+ **入口**:
957
+
958
+ - UI 仅对 root dialog(`selfId === rootId`)的 generation bubble 显示 `Fork 对话`
959
+ - 后端 API:`POST /api/dialogs/:rootId/fork`
960
+ - 请求体:`{ course, genseq, status? }`
961
+
962
+ **语义(强制)**:
963
+
964
+ - 选中的 generation bubble **不会**被复制到 fork 后的新 root;fork 切点语义是“从该 generation 开始前分叉”
965
+ - 复制范围不是单个对话,而是**整棵 root dialog tree**
966
+ - 子对话是否纳入 fork,取决于它是否已经在切点之前被根对话显式记录为已创建
967
+ - 子对话 transcript 的保留边界由 root generation anchor 决定,而不是子对话自身的本地 `genseq`
968
+
969
+ **fork 后动作**(由后端返回给 UI):
970
+
971
+ - `draft_user_text`:若目标 generation 是一条用户输入,则把该文本回填到新对话输入框中,等待用户决定是否发送
972
+ - `restore_pending`:若切点之前存在待处理 Q4H 或待处理子对话,则恢复这些阻塞态,让新 root 继续处于阻塞状态
973
+ - `auto_continue`:若切点之前没有待处理阻塞,则新 root 以 `interrupted(system_stop: fork_dialog_continue)` 初始化,UI 随后立即发送 `resume_dialog`
974
+
975
+ **一致性要求**:
976
+
977
+ - fork 必须保留同一 Taskdoc 引用
978
+ - fork 后的 root/subdialog 都落到 `running/`,并拥有新的 rootId
979
+ - 前端不得对 sideline dialog 暴露该入口;当前实现仅支持 fork root dialog
980
+
952
981
  ### 子对话课程头(强制)
953
982
 
954
983
  每次子对话 course 开始时,运行时必须在 assignment prompt 前插入角色头: