better-dsh 0.0.0 → 0.2.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 (142) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +294 -4
  3. package/control-prompt.md +37 -0
  4. package/cordis.patch.yml +53 -0
  5. package/docs/00_adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
  6. package/docs/00_adr/0002-masking-is-presentation-only.md +15 -0
  7. package/docs/10_plans/A2A-messaging-channel-test-archive.md +256 -0
  8. package/docs/10_plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
  9. package/docs/10_plans/dashr-blueprint-review.md +201 -0
  10. package/docs/10_plans/dashr-blueprint.md +561 -0
  11. package/docs/10_plans/dashr-compaction-window-and-archive.md +307 -0
  12. package/docs/10_plans/dashr-profile-layer-feasibility.md +367 -0
  13. package/docs/10_plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
  14. package/docs/10_plans/dashr-security-sandbox-analysis.md +187 -0
  15. package/docs/10_plans/dashr-surface-invariant-and-omp-imports.md +97 -0
  16. package/docs/10_plans/ipython-kernel-interactive-interface-test-report.md +152 -0
  17. package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
  18. package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
  19. package/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
  20. package/docs/10_plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
  21. package/docs/10_plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
  22. package/docs/10_plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
  23. package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
  24. package/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
  25. package/docs/10_plans/recallable-compaction.md +147 -0
  26. package/docs/10_plans/spike-tag-repro.mjs +102 -0
  27. package/docs/10_plans/upstream-analysis.md +128 -0
  28. package/docs/50_test-reports/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
  29. package/docs/50_test-reports/kernel-provisioning.md +44 -0
  30. package/docs/50_test-reports/repl-kernel-provisioning-test-report.md +87 -0
  31. package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-local-test-report.md +81 -0
  32. package/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-report.md +93 -0
  33. package/docs/50_test-reports/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
  34. package/docs/50_test-reports/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
  35. package/docs/50_test-reports/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
  36. package/docs/50_test-reports/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
  37. package/docs/50_test-reports/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
  38. package/docs/50_test-reports/v0.1.8d_artifacts/README.md +138 -0
  39. package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
  40. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
  41. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
  42. package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +592 -0
  43. package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
  44. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
  45. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
  46. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
  47. package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
  48. package/docs/50_test-reports/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
  49. package/docs/50_test-reports/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
  50. package/docs/50_test-reports/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
  51. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
  52. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
  53. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
  54. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
  55. package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +5 -0
  56. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
  57. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
  58. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
  59. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
  60. package/docs/50_test-reports/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
  61. package/docs/50_test-reports/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
  62. package/docs/50_test-reports/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
  63. package/docs/50_test-reports/v0.2.1d-/345/256/236/346/265/213/346/212/245/345/221/212.md +67 -0
  64. package/docs/50_test-reports/v0.2.1e-P1-/345/256/236/346/265/213/346/212/245/345/221/212.md +136 -0
  65. package/docs/50_test-reports/v0.2.1ef-dev-audit-report.md +73 -0
  66. package/docs/50_test-reports/v0.2.1f-plugin-shipped-ui-patches/345/256/236/346/265/213/346/212/245/345/221/212.md +102 -0
  67. package/docs/60_exploration-and-research/cordis-research.md +350 -0
  68. package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +186 -0
  69. package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +310 -0
  70. package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +300 -0
  71. package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +324 -0
  72. package/docs/60_exploration-and-research/web-frontend-composability-research.md +191 -0
  73. package/docs/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
  74. package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
  75. package/docs/adr/0002-masking-is-presentation-only.md +15 -0
  76. package/docs/distro-blueprint.md +81 -0
  77. package/docs/dsh-webUI-with-rlm-mode.png +0 -0
  78. package/docs/plans/A2A-messaging-channel-test-archive.md +256 -0
  79. package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
  80. package/docs/plans/dashr-blueprint-review.md +201 -0
  81. package/docs/plans/dashr-blueprint.md +561 -0
  82. package/docs/plans/dashr-compaction-window-and-archive.md +307 -0
  83. package/docs/plans/dashr-profile-layer-feasibility.md +367 -0
  84. package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
  85. package/docs/plans/dashr-security-sandbox-analysis.md +187 -0
  86. package/docs/plans/dashr-surface-invariant-and-omp-imports.md +97 -0
  87. package/docs/plans/ipython-kernel-interactive-interface-test-report.md +152 -0
  88. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
  89. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
  90. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
  91. package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
  92. package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
  93. package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
  94. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
  95. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
  96. package/docs/plans/recallable-compaction.md +147 -0
  97. package/docs/plans/spike-tag-repro.mjs +102 -0
  98. package/docs/plans/upstream-analysis.md +128 -0
  99. package/docs/repositioning-and-rebranding.md +102 -0
  100. package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
  101. package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
  102. package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
  103. package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
  104. package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
  105. package/docs/v0.1.8d_artifacts/README.md +138 -0
  106. package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +74 -0
  107. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +3890 -0
  108. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +544 -0
  109. package/docs/v0.1.8d_artifacts/functions.json +592 -0
  110. package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +30 -0
  111. package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +1236 -0
  112. package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +592 -0
  113. package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +516 -0
  114. package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +54 -0
  115. package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
  116. package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
  117. package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
  118. package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +7 -0
  119. package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +6 -0
  120. package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +8 -0
  121. package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +4 -0
  122. package/docs/v0.2.0b_artifacts/hashline-probe.md +5 -0
  123. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +7 -0
  124. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +7 -0
  125. package/docs/v0.2.0b_artifacts/slowprobe/build.rs +4 -0
  126. package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +13 -0
  127. package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
  128. package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
  129. package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
  130. package/lib/client/index.js +473 -0
  131. package/lib/index.d.ts +736 -0
  132. package/lib/index.js +11518 -0
  133. package/lib/kernel-env-hxaihi9C.js +195 -0
  134. package/lib/kernel-env.d.ts +80 -0
  135. package/lib/kernel-env.js +3 -0
  136. package/lib/py-sdk-BCaOGYz7.d.ts +125 -0
  137. package/lib/py-sdk-CbgYiX8O.js +691 -0
  138. package/lib/py-sdk.d.ts +2 -0
  139. package/lib/py-sdk.js +3 -0
  140. package/package.json +325 -4
  141. package/scripts/kernel-provision.mjs +35 -0
  142. package/index.js +0 -3
@@ -0,0 +1,113 @@
1
+ # Self Survey of `dsh` (DeepSeek Harness Agent) and Prime Agent - Actionable Surface to LLM in Agent runtime
2
+
3
+
4
+ - Actionables: tools, toolset(s), skills, bash, executable code scripts (e.g. python ...)
5
+ - Surface to LLM: the text/prompts exposed to LLM during agent runtime
6
+
7
+
8
+
9
+
10
+ ## Prime Agent(第一人称:Prime Agent 运行时自述)
11
+
12
+ ### 地基 — 我"调用工具"的 wire 形态(function calling)
13
+
14
+ - 和 dsh 是同一个 function-calling JSON:`Function: { name, arguments }` —— 只有两个 element,`name` 平级、无 `tools.` 之类前缀命名空间。
15
+ - **但我的平级工具枚举清单里只有一个名字:`ipython`。** 所以 wire 层固定是:`name` 只有 `"ipython"` 一种取值;`arguments` 只有一个必填键 `code`(字符串)。没有别的字段。
16
+
17
+ - 我发出的真实 wire 原文(从我自己这个 session 的日志里抄的,一字未改):
18
+
19
+ ```json
20
+ {"type": "toolCall", "id": "call_00_wf7zeFy6KRIXEaeC5zZS3896",
21
+ "name": "ipython",
22
+ "arguments": {"code": "%%bash\nls -la /home/u1/workspaces/dashr/dev/kernel-refactoring/"}}
23
+ ```
24
+
25
+ - 客户端拿 `name: "ipython"` 定位唯一执行器,把 `arguments.code` 整段交给**常驻 IPython kernel** 执行,把我 print / 显示出来的 stdout 文本塞回 toolResult(原文照抄,stderr 与 kernel 状态另列):
26
+
27
+ ```json
28
+ {"role": "toolResult", "toolCallId": "call_00_wf7zeFy6KRIXEaeC5zZS3896",
29
+ "toolName": "ipython",
30
+ "content": [{"type": "text", "text": "<cell 的 stdout>"}],
31
+ "details": {"durationMs": 472, "status": "ok", "stdout": "...", "stderr": "", "kernelRestarted": false},
32
+ "isError": false}
33
+ ```
34
+
35
+ - **`await` 不在 wire 层,在 `code` 层**——`await` 是 Python 语法,发生在我写进 `arguments.code` 的那段程序里面。完整的语法链就四步:
36
+
37
+ 1. 我要做一个动作 → 想好一段 **Python 程序**(一句话也是一个程序);
38
+ 2. 把它写进 `arguments.code`(可以是 `await 技能函数(...)`、`%%bash` cell、`rlm(...)`、或任意 Python);
39
+ 3. 发出唯一形态的 JSON:`Function: { name: "ipython", arguments: { code: "<那个程序>" } }`;
40
+ 4. kernel 跑完,stdout 原样作为 toolResult 回到我的上下文,我再决定下一轮。
41
+
42
+ - wire 示例(全部是同一个工具名,差别只在 `code` 里):
43
+
44
+ ```json
45
+ // 例子1:调用联网技能 —— await 发生在 code 里
46
+ Function: { name: "ipython", arguments: {"code": "await websearch('prime agent')"} }
47
+
48
+ // 例子2:shell —— %%bash 必须是 code 的第一行
49
+ Function: { name: "ipython", arguments: {"code": "%%bash\nls -la"} }
50
+
51
+ // 例子3:子代理 admission —— 返回的是句柄,不是答案
52
+ Function: { name: "ipython", arguments: {"code": "h = await rlm('sub-task', name='worker')"} }
53
+ ```
54
+
55
+ ### Actionables — 全部经 `ipython` 的 `code` 触达(没有第二层工具枚举)
56
+
57
+ wire 层是平的、只有一个名字;dsh 那 29 个平级工具对应到我这边的全部"动作清单",都是我写进 `code` 里的 Python 对象:
58
+
59
+ - **内核全局预导入的 9 个 python skill 模块**,调用形态统一是 `await <模块>.<函数>(...)`,返回值可绑定变量、可组合:
60
+ `agent_message`(send / list_agents)、`agent_observe`、`attach_image`、`compact`、`edit`、`goal`、`refine`(run)、`rlm_heartbeat`、`websearch`
61
+ - **内核全局 `rlm`**:`await rlm('sub-task')`(非阻塞 admission,返回 rlm_child_id/name/session_dir/model,永不返回答案)、`rlm.list_subagents()`、`rlm.delete_subagent()`、`rlm.find_models()`、`rlm.get_harness_state()`、`rlm.harness.*`(memory / prompt_note / skill / subagent-spec 四类 CRUD,默认 session 本地,`global_=True` 才跨会话)
62
+ - **`%%bash` cell**(必须是 `code` 的第一行)——shell、项目命令、CLI 全走这里;**没有独立的 bash 工具名**
63
+ - **任意 Python**:stdlib 读/写/搜索文件、编排进程、`uv pip install` 装包、`%cd` / `os.environ` 管内核状态
64
+ - **每个 skill 的 shell CLI**:`<skill> ...`(在 %%bash 里跑)
65
+ - **markdown skills**(项目 `.agents/skills` 向上收集 + 用户级 + 捆绑 dist):不是 callable 绑定,用 ipython 读它们的 SKILL.md 学 API
66
+ - **没有的东西**:read / write / glob / grep / todo_write / subagent / send_message……这些名字在我的 wire 枚举里**不存在**;对应能力 = code 里的 Python 或 skill 函数。这条不是靠运行时报错兜底,是 schema 面根本不暴露。
67
+
68
+ ### Surface to LLM — 我暴露给模型的文本
69
+
70
+ - 系统提示正文(每次请求动态组装,顺序固定):code-first 人设开篇 → IPYTHON_CONTROL_PROMPT(长驻 notebook、%%bash 纪律、状态持久、await 调用、"do not invent non-native wrappers" 等反模式明令)→ RLM-native call contract → delegation doctrine(子代理 admission/消息/观察拓扑)→ continual harness 状态菜单(prompt/memory/skill/subagent 计数)→ 项目 AGENTS.md 链(Project Context)→ 会话变量:cwd、conversation log 路径、recursive agent depth、预装 Python 包清单
71
+ - 工具 schema:只有 `ipython` 一个(`name` + `parameters:{code: string}`,description 写在 schema 里,正文不重复列工具目录)
72
+ - skills catalog:`<available_skills>` XML 块拼在正文里(当前 session 26 条:name / type / python_import / description / location,措辞是 kernel 形态)
73
+ - SKILL.md 本体:不注入;我用 ipython 读文件学 API
74
+ - 对话历史 + 压缩(compact skill;单条 cell 输出截断上限默认 2000 行 / 50KB)
75
+ - kernel 事件通知:`<ipython_kernel_reset>` 标记、interrupted cell 的 wait/kill 选择提示
76
+
77
+
78
+ ### 组合性 — 预绑定的名字是「Python 类型化的内置工具」,可当一等对象组合(本 session 已实测)
79
+
80
+ - 术语(建议 Dash prompt 也采用):**Python 类型化的内置工具(typed Python built-in tools)**。它们不是 wire 层的 function call,而是 kernel 全局命名空间里的 typed Python 对象:
81
+ - `edit` = 可调用模块,成员 `run(path, old_str, new_str) -> str` 是 async 函数,抛 `FileNotFoundError` / `ValueError`
82
+ - `rlm` = 可调用模块(`rlm(...)` 即 spawn),成员 run / find_models / list_subagents / delete_subagent / harness / get_harness_state
83
+ - 实现层:`edit` 是进程内 async Python 函数(`Path.read_text/write_text` 直接 syscall),零 shell 零 subprocess
84
+ - 实测组合模式(全部真实执行):
85
+
86
+ | 组合模式 | 写法 | 结果 |
87
+ |---|---|---|
88
+ | 条件 | `if "x" in Path(p).read_text(): await edit(...)` | ✅ |
89
+ | 异常 | `except ValueError` / `except FileNotFoundError` | ✅ 类型化异常 |
90
+ | 重试 | for + try/except,失败换更宽 old_str | ✅ |
91
+ | 批量 / 并行 | for 收集返回值 / `asyncio.gather(*[edit(...)])` | ✅ |
92
+ | 对象化 | 存 dict、当参数传、自写 `safe_edit()` wrapper(加重试/降级策略) | ✅ |
93
+
94
+ - 对照:平级 function call(DSH/Hermes)里组合只能发生在模型脑内、跨多轮往返、非确定;这里组合发生在确定性 Python 代码里,一个 cell 一轮往返。
95
+ - **反面证据(诚实记录)**:本 session 的 system prompt 关于组合只有一句 "composed into program logic just like any other call",无例子、未说明是 typed 对象 → 本 session 模型未自发组合过一次(写文件全用裸 Python)。结论:**不写清楚,模型就不会。**(此为 prompt 缺口,补丁见下节)
96
+
97
+ ### 状态管理 — cell 化之后的「可回查状态机」(本 session 已实测)
98
+
99
+ 三种后台句柄,全部跨 cell 存活于 kernel 命名空间、可回查、可控制:
100
+
101
+ | 句柄 | 创建 | 回查状态 | 控制 |
102
+ |---|---|---|---|
103
+ | asyncio Task | `t = asyncio.create_task(coro())` | `t.done()` / `t.result()` | `t.cancel()` |
104
+ | 子进程(Hermes job/PID 等价物) | `p = subprocess.Popen(...)` | `p.poll()` / `p.pid` | `p.kill()` / `p.wait()` |
105
+ | rlm 子代理 | `h = await rlm('sub-task')` | `rlm.list_subagents()` → `status` 字段 | `rlm.delete_subagent(h)` |
106
+
107
+ - `await` 是"等"的语法;`asyncio.create_task` / Popen 是"不等"的句柄 —— 本 session 的 prompt 只教了 await,没教 async 句柄,这是第二个 prompt 缺口。
108
+ - rlm 实测闭环:admission 立即返回 `RLMSpawnHandle(rlm_child_id, session_dir, model)` → `list_subagents()` 查 `status='completed'` → `delete_subagent` 回收 → 子代理回复经 agent_message **事件驱动送达**(实测:delete 之后消息仍到达,投递队列与句柄注册表解耦)。
109
+ - 长命令(`%%bash` curl 等):包进 create_task/Popen,句柄落 kernel 命名空间,下一 cell 回查;kernel 死则句柄丢(进程还活,句柄没了)。
110
+
111
+ ### 建议 prompt 补丁(Prime upstream `IPYTHON_CONTROL_PROMPT` 与 Dash preset 共用)
112
+
113
+ > Pre-imported skill modules and the global `rlm` are typed Python objects, not wire-level tools: each exposes documented async functions and raises typed exceptions (e.g. `edit` raises `FileNotFoundError`/`ValueError`). Treat them as first-class values: compose them with conditionals, `try/except` on their typed errors, loops, `asyncio.gather` for parallelism, custom wrapper functions for retry/degradation policies, or storage in data structures. For background work, keep pollable handles in the kernel namespace: `asyncio.create_task` → `done()/result()/cancel()`; `subprocess.Popen` → `pid/poll()/kill()`; `rlm()` admission → `rlm.list_subagents()/delete_subagent()`, with results arriving asynchronously via `agent_message`. Prefer composing multiple tool calls inside one cell over issuing them one call per cell.
@@ -0,0 +1,147 @@
1
+ # Recallable Compaction(可回溯压缩)— 设计备忘
2
+
3
+ > 状态:设计备忘(**未实现**)· 2026-08-20 · 用户方向 + API 面 spike 验证通过
4
+ > 归属:`dashr/dev/`(gitignored 本地 scratch,不进公开仓库)
5
+ > 上游文档:`dev/dashr-compaction-window-and-archive.md`(Feature 2 压缩损失补偿的总纲;本文档是其「回溯通道」的落地设计,并回收其 §3 开放问题中已解决项)
6
+
7
+ ## 0. 背景:Context as variable 的四方向与本 gap
8
+
9
+ dashr 参考 Prime Agent 的三个核心特点(RLM 模式 / IPython REPL tool calling / Context as variable)中,前两个已完全实现;第三个目前只实现一半。完全体的四个方向:
10
+
11
+ | 方向 | 状态 |
12
+ |---|---|
13
+ | 1. 事件流过滤 | ✅ 已实现(`recencyWindowTokens`,Feature 1,v0.1.1+) |
14
+ | 2. 运行时变量存取 | ✅ 已实现(kernel 变量自由存取) |
15
+ | 3. **上下文压缩与回溯** | ❌ **未实现 ← 本文档** |
16
+ | 4. 广义上下文组件化 | ✅ 已实现(Continual Harness / `refine()`) |
17
+
18
+ 方向 3 的缺口:压缩后旧上下文被摘要 shadow,运行时模型无法直接读取原文(原文虽在 session 持久化文件中,但模型经资源工具查询繁琐且难定位)。Feature 2 原设计(强制归档 + 摘要尾部标记)解决「可恢复」,本文档补上「模型可寻址的回溯通道」与全部 API 面验证。
19
+
20
+ ## 1. Spike 结论(2026-08-20,Dash agent 实证 + 本机复验)
21
+
22
+ > 委托方式:Dash HTTP API(session `session-a2a61011`,`cwd=/home/u1/workspaces/dashr`,rlm-mode preset)。证据脚本 `dev/spike-tag-repro.mjs` 已随文档保存,本机复跑 exit 0、输出吻合。
23
+
24
+ | # | 事实 | 对设计的影响 |
25
+ |---|---|---|
26
+ | 1 | surface 是 **append-only + 深冻结** 的不可变投影;唯一写入口 `Session.append`;**不存在原地 patch 节点文本的 API** | 不能 mutate,只能 replace |
27
+ | 2 | 「改写单个节点」的官方正解 = 再 append 一个 `replace`,`start === end === 目标 seq`,新节点 shadow 旧节点 —— 这正是上游 compaction 改写历史所用的同一机制 | 挂 tag 的通道 ✓ |
28
+ | 3 | 新摘要节点 seq = **`result.summarySeq + 1`**(contractual adjacency;`commitCompactionBody` 源码确认:`compaction/summary` 事件后紧邻 `user/message` 替换节点,`= endSeq - 1`) | 摘要节点可精确定位 ✓ |
29
+ | 4 | 被 shadow 的原文**事后仍可读**:`session.events[shadowedSeqs]` 完整保留(append-only log 不删除,shadow 只是从 surface 投影隐去) | **归档不必在压缩前捕获** —— 顺序约束消失 |
30
+ | 5 | `user/message` 重写无限制(`assertToolResultRewrite` 只约束 `tool/result`) | 摘要文本可自由追加 tag 块 |
31
+ | 6 | 替换节点保留原 `source`(含 `compactionId`)时,下游 checkpoint 识别(`isCompactCheckpointSource`)不破 | tag 挂载无损 ✓ |
32
+
33
+ **关键修正**:原方案「归档先于压缩」(压缩前取到将被 shadow 的区间 → 归档 → 才允许压缩)不再需要。事实 #3+#4 意味着顺序可以是**先压缩、后归档、再挂 tag**——每一步只依赖已提交的事实,**tag 永不悬挂,无需任何补偿逻辑**。
34
+
35
+ ## 2. 设计:三步流程
36
+
37
+ 在 `compactIfNeeded`(与 `compactNow` 共用)的 `compactRegion` 返回之后:
38
+
39
+ 1. **读原文**(事后,从 append-only log):`result.shadowedSeqs` → `session.deriveEventMessage(session.events[seq])` → 分类 → 序列化。
40
+ 2. **写归档存储**:介质二选一(§2.2,待用户拍板)。
41
+ 3. **挂 tag**:单节点 `replace`(`start === end === result.summarySeq + 1`),把 tag 文本块追加到摘要内容尾部。
42
+
43
+ 归档失败时降级为现状行为(照常压缩、仅无 tag),**不阻塞压缩**(沿用旧 doc 原则)。
44
+
45
+ ### 2.1 分类(沿用旧 doc §2.2,纯机械非语义)
46
+
47
+ | bucket | 来源 | 说明 |
48
+ |---|---|---|
49
+ | `user_requests` | user 消息 | 用户指令原文 |
50
+ | `assistant_responses` | assistant 消息 | 正文 verbatim;thinking 块剥除与否见开放项 |
51
+ | `tool_results` | toolResult 消息 | 含 cell stdout |
52
+ | `file_ops` | 机械提取 | read/modified 列表 |
53
+
54
+ ### 2.2 归档介质(开放决策,二选一)
55
+
56
+ **方案 K — kernel 变量 + dill snapshot**(旧 doc 原方案):
57
+ - 复用 State Storage,实现量最小。
58
+ - 代价:(a) trunk 与用户工作变量抢同一个 `capBytes` 预算,超限时**整个 snapshot 被 skip**(连用户变量一起丢);(b) dill 跨 Python 版本脆弱;(c) 原文常驻 kernel 进程 RAM,随压缩次数线性涨。
59
+
60
+ **方案 F — 独立 trunk 文件 + kernel 索引 + `recall()` 读文件**(推荐):
61
+ - trunk 本体 = 纯文本 JSON(带 role/seq),落 `kernel-snapshots/<sessionId>/trunks/<compactionId>.json`;kernel 里只放索引 dict(tag → 路径);`recall(tag)` helper 直接读文件。
62
+ - 好处:独立预算天然成立(不吃 snapshot cap);写入即时持久(无 snapshot 的 1500ms debounce 窗口);恢复 = 回填索引或重扫目录;绕开 dill 版本问题。
63
+ - 代价:recall 读文件比读内存慢几毫秒,对 LLM 无感。
64
+ - State Storage 职责因此更清晰:snapshot 管用户工作变量,trunk store 管压缩原文。
65
+
66
+ ### 2.3 tag 与 recall 协议
67
+
68
+ - tag id:`ctx-<compactionId>`(或自增计数)。
69
+ - tag 文本块(挂摘要尾部,格式示例):
70
+
71
+ ```
72
+ [原文回溯: ctx-12]
73
+ 本轮压缩的原始上下文已归档,需要细节时用 recall('ctx-12') 读取。
74
+ ```
75
+
76
+ - `recall(tag)` helper(py-sdk 注入):保留命名空间藏 trunk 数据(**不暴露裸全局**,防模型 cell 误覆盖/`del`);只读访问;超长输出截断提示;缺失报明确错误。
77
+ - Control Prompt 增加约定段:摘要条目带 `ctx-N` 标签时,需要全文就 `recall('ctx-N')`。
78
+ - token 经济学:摘要照常在上下文(tag 一行文本 ≈ 0 成本);模型只在需要时付出一次读取成本;归档不查询则不进上下文。
79
+
80
+ ### 2.4 预算与淘汰(开放数字)
81
+
82
+ 归档随压缩次数线性增长,必须设上限,否则省下的上下文 token 从 RAM/磁盘侧门还回去。候选:最近 N 档 / 总 token 预算 / LRU。淘汰是安全的——session log 里原文永远在(§2.5)。
83
+
84
+ ### 2.5 自愈(compactionId 稳定性)
85
+
86
+ tag 携带 `compactionId + shadowedSeqs`;revive 时发现归档缺失,可从 session log 重放重建。本质:**session log 就是原文的持久层,归档只是模型可寻址的快路径缓存**。
87
+
88
+ ### 2.6 两条触发路径(共用挂点)
89
+
90
+ - auto pressure:`RecencyAwareCompactionEngine.compactIfNeeded`
91
+ - manual:`/compact` → `compactNow`
92
+ - 挂点都在 `compactRegion` 返回后,路径无关。
93
+
94
+ ## 3. 代码骨架(compactRegion 返回后)
95
+
96
+ ```ts
97
+ const result = await this.compactRegion(range.start, range.end, agent, signal)
98
+ if (result === null) return null
99
+
100
+ const session = agent.session
101
+ const summaryNodeSeq = result.summarySeq + 1 // contractual adjacency
102
+
103
+ // 1) 事后读原文(append-only log 完整保留)
104
+ const original = result.shadowedSeqs
105
+ .map(seq => session.deriveEventMessage(session.events[seq]))
106
+ .filter((m): m is Message => m !== null)
107
+ // 2) 归档(介质见 §2.2,失败则跳过第 3 步、不阻塞压缩)
108
+ const tagId = `ctx-${result.compactionId}`
109
+ // await archiveRecall(tagId, classify(original)) // 分类见 §2.1
110
+ // 3) 单节点 replace 挂 tag
111
+ const summaryMsg = session.deriveEventMessage(session.events[summaryNodeSeq])!
112
+ session.append('user/message', createUserMessage({
113
+ content: [...summaryMsg.content, { type: 'text', text: `\n[原文回溯: ${tagId}] 全文可通过 recall('${tagId}') 读取。` }],
114
+ source: summaryMsg.source, // 保留 compactionId,checkpoint 识别不破
115
+ }), {
116
+ surfaceOp: { op: 'replace', start: summaryNodeSeq, end: summaryNodeSeq },
117
+ sourceEventSeqs: [summaryNodeSeq],
118
+ })
119
+ ```
120
+
121
+ ## 4. 与旧 doc §3 开放问题对照
122
+
123
+ | # | 问题 | 状态 |
124
+ |---|---|---|
125
+ | 1 | 实现路径 A/B/C | 已裁定方案 B(子类化),Feature 1 已落地 v0.1.1+ |
126
+ | 3 | 摘要后编辑口 | **已解决**(本文档 §1):落盘前无插入口,落盘后单节点 replace 等效;且原文可事后读取,归档无需压缩前捕获 |
127
+ | 8 | compactionId 稳定性 | **已解决**(§2.5 自愈:log 重放重建) |
128
+ | 4 | 归档增长上限 | 仍开放(§2.4 候选方案) |
129
+ | 5 | thinking 块剥不剥 | 仍开放(剥=省空间丢推理过程;留=完整但体积翻倍) |
130
+ | 6 | 标记措辞与 token 预算 | 仍开放(§2.3 给出了候选格式) |
131
+ | 7 | 与 pruner 的交互 | 仍开放,但假设已变:recency 路径在 compactRegion 前调 `pruneSession`;若 prune 也是 surface-replace 机制,则 log 原文应仍在(append-only),需实现时验证 |
132
+ | 9 | recency 低于 system prompt 体积 | Feature 1 已带 no-op 守卫,软警告低优先 |
133
+
134
+ ## 5. 验证计划(实现时执行)
135
+
136
+ - **单测**:分类落桶(每条消息恰落一桶)、tag 格式、单节点 replace(`dev/spike-tag-repro.mjs` 已是该场景的可运行骨架)。
137
+ - **e2e**:灌满上下文 → 触发压缩(auto + manual 各一次)→ 断言:(1) 归档存储含被压缩区间原文;(2) 摘要尾部含 tag;(3) 模型执行 `recall(tag)` 能复述原文某细节。
138
+ - **pruner 交互**(开放项 #7):`pruneSession` 之后 log 里的原文事件是否完整。
139
+ - **回归**:未配归档时行为与现状一致(默认全关);测试只增不减(现有 140/140 不动)。
140
+
141
+ ## 6. 参考
142
+
143
+ - `dev/dashr-compaction-window-and-archive.md`(Feature 2 总纲 + Feature 1 已实现记录)
144
+ - `dev/spike-tag-repro.mjs`(API 面复现脚本,`node dev/spike-tag-repro.mjs` 可复跑,exit 0)
145
+ - `dashr/src/compaction/recency-engine.ts`(挂点)、`dashr/src/py-sdk.ts`(recall helper 注入点)
146
+ - 上游源码:`@deepseek-ai/dsh-session`(append/surface)、`@deepseek-ai/dsh-compaction-basic/lib/index.js` `commitCompactionBody`(替换节点 append 顺序)、`@deepseek-ai/dsh-compaction`(CompactionResult)
147
+ - 委托 spike 报告:`/tmp/a2a/dashr-tag-spike.md`(Dash agent 产出,2026-08-20;关键结论已全部吸收进本文档 §1)
@@ -0,0 +1,102 @@
1
+
2
+ // Minimal reproduction: verify that a session surface node's text can be
3
+ // "rewritten" (summary + recall tag) via the append-only replace surfaceOp,
4
+ // and that the new compaction summary node's seq is determinable.
5
+ // Read-only spike — no dashr repo files touched.
6
+
7
+ import { Session } from '/home/u1/workspaces/dashr/dashr/node_modules/@deepseek-ai/dsh-session/lib/index.js'
8
+ import { createUserMessage, createAssistantMessage } from '/home/u1/workspaces/dashr/dashr/node_modules/@deepseek-ai/dsh-llm/lib/index.js'
9
+
10
+ const s = Session.create('spike-tag-demo')
11
+
12
+ const userMsg = (text) => createUserMessage({
13
+ content: [{ type: 'text', text }],
14
+ source: { kind: 'user' },
15
+ })
16
+
17
+ const asstMsg = (text, step) => createAssistantMessage({
18
+ content: [{ type: 'text', text }],
19
+ source: { provider: 'p', model: 'm' },
20
+ })
21
+
22
+ const summarize = (m) => m.map(x => `${x.role}: ${x.content.map(b => b.text ?? '<non-text>').join('')}`).join('\n ')
23
+
24
+ console.log('=== stage 0: four surface appends ===')
25
+ s.append('user/message', userMsg('user-0: hello'), { surfaceOp: 'append' })
26
+ s.append('assistant/message', { turn: 1, step: 1, message: asstMsg('asst-1: world', 1) }, { surfaceOp: 'append' })
27
+ s.append('user/message', userMsg('user-2: question'), { surfaceOp: 'append' })
28
+ s.append('assistant/message', { turn: 1, step: 2, message: asstMsg('asst-3: answer', 2) }, { surfaceOp: 'append' })
29
+ console.log('surface.nodes =', JSON.stringify(s.surface.nodes))
30
+ console.log('deriveMessages:\n ' + summarize(s.deriveMessages()))
31
+
32
+ console.log('\n=== stage 1: simulate compactRegion writing a summary over nodes [1,2] ===')
33
+ // Mirror commitCompactionBody exactly: log-only compaction/summary, then the
34
+ // surface replacement user/message immediately after (summarySeq + 1).
35
+ const summaryEvent = s.append('compaction/summary', {
36
+ compactionId: 'c-1',
37
+ summary: [{ type: 'text', text: 'CONDENSED: user-2 and asst-3 happened.' }],
38
+ shadowedRange: { start: 1, end: 2 },
39
+ shadowedSeqs: [1, 2],
40
+ shadowedTokenCount: 1234,
41
+ provider: 'p', model: 'm',
42
+ })
43
+ const replacement = s.append('user/message',
44
+ createUserMessage({
45
+ content: [
46
+ { type: 'text', text: 'This is an automatically generated checkpoint...\n\n<compacted-summary>' },
47
+ { type: 'text', text: 'CONDENSED: user-2 and asst-3 happened.' },
48
+ { type: 'text', text: '</compacted-summary>' },
49
+ ],
50
+ source: { kind: 'plugin', plugin: 'compact', compactionId: 'c-1' },
51
+ }),
52
+ {
53
+ surfaceOp: { op: 'replace', start: 1, end: 2 },
54
+ sourceEventSeqs: [summaryEvent.seq, 1, 2],
55
+ },
56
+ )
57
+ console.log('summaryEvent.seq (compaction/summary) =', summaryEvent.seq)
58
+ console.log('replacement.seq (surface summary node) =', replacement.seq, ' === summarySeq+1 ?', replacement.seq === summaryEvent.seq + 1)
59
+ console.log('surface.nodes =', JSON.stringify(s.surface.nodes))
60
+ console.log('deriveMessages:\n ' + summarize(s.deriveMessages()))
61
+
62
+ console.log('\n=== stage 2: PATCH the summary node text (append recall tag) ===')
63
+ // The summary surface node seq is determinable as summarySeq + 1 (== replacement.seq).
64
+ const summaryNodeSeq = replacement.seq
65
+ const tagged = s.append('user/message',
66
+ createUserMessage({
67
+ content: [
68
+ { type: 'text', text: 'This is an automatically generated checkpoint...\n\n<compacted-summary>' },
69
+ { type: 'text', text: 'CONDENSED: user-2 and asst-3 happened.' },
70
+ { type: 'text', text: '</compacted-summary>' },
71
+ { type: 'text', text: '\n[原文回溯: ctx-12] 全文可通过 recall(\'ctx-12\') 读取。' },
72
+ ],
73
+ source: { kind: 'plugin', plugin: 'compact', compactionId: 'c-1' },
74
+ }),
75
+ {
76
+ surfaceOp: { op: 'replace', start: summaryNodeSeq, end: summaryNodeSeq },
77
+ sourceEventSeqs: [summaryNodeSeq],
78
+ },
79
+ )
80
+ console.log('patched node seq =', tagged.seq)
81
+ console.log('surface.nodes =', JSON.stringify(s.surface.nodes))
82
+ console.log('deriveMessages:\n ' + summarize(s.deriveMessages()))
83
+
84
+ console.log('\n=== stage 3: shadowed originals remain recoverable from the append-only log ===')
85
+ console.log('shadowedSeqs [1,2] still in session.events:')
86
+ for (const seq of [1, 2]) {
87
+ const e = s.events[seq]
88
+ const m = s.deriveEventMessage(e)
89
+ console.log(` seq ${seq}: type=${e.type} role=${m?.role} text="${m?.content.map(b => b.text ?? '').join('')}"`)
90
+ }
91
+
92
+ console.log('\n=== stage 4: confirm in-place mutation is rejected (deep-frozen) ===')
93
+ const frozenMsg = s.deriveMessages().find(m => m.content.some(b => b.text?.includes('[原文回溯')))
94
+ let mutateOk = false
95
+ try {
96
+ frozenMsg.content.push({ type: 'text', text: 'sneaky' })
97
+ mutateOk = true
98
+ } catch (err) {
99
+ console.log('mutation threw:', err.constructor.name, '-', err.message)
100
+ }
101
+ console.log('in-place push succeeded?', mutateOk)
102
+ console.log('total events:', s.events.length, '| seq (next):', s.seq)
@@ -0,0 +1,128 @@
1
+ # DASHR 上游源码分析(dsh × prime-agent)
2
+
3
+ > 日期:2026-08-16 · 工具:Graphify (graphify-http-mcp :4749, AST 模式)
4
+ > 用途:DASHR 自研运行时选型底图。两部分来源 + 结合方式蓝图见后续文档。
5
+
6
+ ## 0. 前置事实
7
+
8
+ | 项 | deepseek-harness (dsh) | prime-agent (PI) |
9
+ |---|---|---|
10
+ | Clone | `dashr/deepseek-harness` @ `47f9438` (2026-08-13, npm-public PR #2519) | `dashr/prime-agent` @ `97b994c` (2026-08-14, daemon spawn ledger #1387) |
11
+ | 语言主体 | TypeScript (ESM), Node ≥22.19 / ≥24 | TS host + Python runtime(模型面 Python,调度面 TS) |
12
+ | 规模 | ~85MB 源码, 2319 ts + 19 py | ~30MB, 925 ts + 23 py(+runtime) |
13
+ | pnpm workspaces | `packages/<group>/<pkg>` 两级, 50 组 ~230 包 | `packages/{agent,ai,coding-agent,tui}` 4 包 + `prime-agent-runtime/` (py) |
14
+ | 许可 | MIT(预发布期承诺) | MIT |
15
+
16
+ ## 1. Graphify 图谱(AST,无 LLM 语义增强)
17
+
18
+ | 指标 | dsh | prime-agent |
19
+ |---|---|---|
20
+ | nodes | 54,318 | 13,676 |
21
+ | edges | 72,496 | 29,765 |
22
+ | communities | 4,110 | 775 |
23
+ | code 节点 | 33,026 | 10,784 |
24
+ | graph.json | 44.9 MB | 15.4 MB |
25
+
26
+ 产物:各库 `graphify-out/{graph.json, GRAPH_REPORT.md, manifest.json}`。
27
+ graph.html 因 >5000 节点未生成(GRAPHIFY_VIZ_NODE_LIMIT),交互视图需切子图或提限。
28
+ 增量更新:`update_graph(project_path)`;Graphify 缓存于 `graphify-out/cache/`。
29
+
30
+ `.graphifyignore` 已写入两库(排除 node_modules/.git/dist/test fixtures/snapshots)。
31
+
32
+ ## 2. deepseek-harness 结构
33
+
34
+ ### 2.1 布局(依据 AGENTS.md + 实测目录)
35
+
36
+ ```
37
+ vendor/ vendored Cordis 内核(manifest+sync procedure)
38
+ packages/ @deepseek-ai/dsh-<name>,50 组 ~230 包
39
+ core/ agent, agent-loop, session, system-prompt, tools, scope
40
+ llm/ llm, llm-deepseek, llm-pi-ai, llm-retry, token-meter
41
+ subagent/ subagent + acp/claude-code/codex/dsh-sdk/fork-in-process/... 11 包
42
+ 其他能力组: fs, shell, subprocess, terminal, lsp, skill, web, mcp, acp,
43
+ compaction, context, workflow, todo, plan, preset, guard,
44
+ self-modification, hooks, session, identity, settings,
45
+ credentials, interaction, boot, sdk, typert, api, sandbox, ...
46
+ apps/ cli + web
47
+ python/ Python SDK + bundled runtime
48
+ native/ node-addon-landlock-run(Landlock 沙箱 addon)
49
+ .agents/ notes/(设计笔记,一手取证源)
50
+ docs/ architecture, cordis-api, postmortem, subsystems
51
+ ```
52
+
53
+ ### 2.2 图谱枢纽(god_nodes, by degree)
54
+
55
+ - `Context` (790) — Cordis 上下文,全库交汇点
56
+ - `InvariantInstaller` (216), `Service` (138) — 插件注册骨架
57
+ - `createSnapshotStore()` (97), `SnapshotStore` (79), `bindSnapshotSelector()` (88) — 会话快照存储链
58
+ - `launchWebScaffold()` / `WebScaffold` / `watchConsole()` — web 测试脚手架
59
+ - tsconfig `paths` (139) + package `scripts` (124) — workspace 胶水节点多,体现 monorepo 复杂度
60
+
61
+ ### 2.3 关键机制(docs/cordis-api 图谱查询 + AGENTS.md)
62
+
63
+ - 插件注册原语:`ctx.plugin()` / `ctx.inject()` / `Registry`(docs/cordis-api/registry.md)
64
+ - Registrations are effects:所有贡献走 `ctx.effect()` / `ctx.on()`,`register()` 返回 disposer(时空可组合性的实现基础;即 Cordis 论文「可逆效应」机制,论文仓库 `github.com/cordiverse/paper`,解读见 deepseek-dsh.md §1.4)
65
+ - 能力三层拆分:Service Definition(接口)/ provider(实现)/ Consumer(消费者)→ 换实现不动消费者
66
+ - per-session preset:`preset/` 包,agent.cordis.yml 组装,会话锁 `agent-preset-locked`
67
+
68
+ ## 3. prime-agent 结构
69
+
70
+ ### 3.1 布局
71
+
72
+ ```
73
+ packages/
74
+ agent/ 5 文件:agent-loop.ts, agent.ts, proxy.ts, types.ts(薄)
75
+ ai/ provider 层:api-registry, bedrock, stream, oauth,
76
+ models.generated, openrouter-reasoning, mcp
77
+ coding-agent/ 主体:src/core/{kernel, tools, session-manager, ...}
78
+ skills/(Python 技能:rlm, refine, compact, goal, edit,
79
+ websearch, agent-message, rlm-heartbeat, ...)
80
+ tui/ 终端 UI
81
+ prime-agent-runtime/ Python 侧 RLM runtime
82
+ src/rlm/{__init__, harness, skill, mcp_base}.py
83
+ test/ subagent_registry, mcp_base, agent_message_skill, harness
84
+ ```
85
+
86
+ ### 3.2 图谱枢纽(god_nodes)
87
+
88
+ - `AgentSession` (430) — 核心会话对象
89
+ - `InteractiveMode` (388), `TUI` (139), `Component` (134) — 交互层重
90
+ - `AgentDaemon` (184), `DaemonSupervisor` (134), `DaemonAgentConnection` (122) — daemon 体系(最新 commit 正是 supervisor-owned rlm spawn ledger)
91
+ - `SettingsManager` (172), `SessionManager` (108)
92
+
93
+ ### 3.3 关键链路(query_graph 取证)
94
+
95
+ **子 agent spawn(rlm())**:
96
+ `rlm/__init__.py` → `run()` → `host_request()`(comm 通道发 TS host)→ `_spawn_handle_from_payload()` → `RLMSpawnHandle`;Python 侧 `HarnessState/HarnessScope/HarnessEntry/RefinementEvent`(harness.py, community 70/90)构成 Continual Harness 状态。TS 侧 `fork-server.ts SpawnParams`(community 157)承接。
97
+
98
+ **IPython kernel(Context as Variable)**:
99
+ - `core/tools/ipython.ts`:`IpythonKernelProvisioner` → `.startKernel()` / `.ensure()`
100
+ - `core/kernel/index.ts` `KernelManager`:`.doStart()`, `.enqueueExecute()`, `.runIopubPump()`, `.handleExecutionMessage()`, `.shutdown()`
101
+ - 状态持久化:`state-snapshot.ts` `.snapshotState()` / `.restoreState()` / `RestoreResult`(community 217)→ 变量级 checkpoint
102
+ - fork:`fork-server.ts` `forkKernel()`(community 157,与 SpawnParams 同社区 → fork 复用 kernel 状态)
103
+
104
+ ## 4. 结合面初步观察(待蓝图输入)
105
+
106
+ | 维度 | 取 dsh | 取 prime-agent |
107
+ |---|---|---|
108
+ | 内核/装配 | Cordis 插件体系, preset, 能力三层 | — |
109
+ | 模型面 | — | 持久 IPython kernel + state-snapshot |
110
+ | 子 agent | subagent 11 包矩阵 | `rlm()` 函数式 + fork-server |
111
+ | 记忆 | — | Continual Harness (ρ,G,K,M) |
112
+ | 沙箱 | bwrap+Landlock (native addon) | — |
113
+ | LLM 接入 | llm-deepseek/pi-ai/retry/token-meter | ai/ 包多 provider |
114
+
115
+ 风险点:两库语言运行时不同(dsh 纯 TS vs PA 模型面 Python);结合方式决定桥接层(PA 式 comm channel 或 dsh 式 in-process SDK)。
116
+
117
+ ## 5. 图谱查询备忘
118
+
119
+ MCP endpoint `http://127.0.0.1:4749/mcp`(Streamable HTTP, 需 `Accept: application/json, text/event-stream`)。
120
+ `graph_path` 参数 = `graphify-out/` 目录(含尾 graph.json 解析)。常用:
121
+ `graph_stats / god_nodes / query_graph / get_neighbors / shortest_path / graph_affected(影响面) / graph_tree / surprising_connections`。
122
+
123
+ 增量:代码改动后 `update_graph`;LLM 语义增强需 API key(可选 gemini)。
124
+
125
+ ## 6. 相关档案
126
+
127
+ - 调研/实测:`agent-harness/21_CLI-Agent/03_deepseek-dsh/deepseek-dsh.md`
128
+ - `agent-harness/21_CLI-Agent/04_prime-agent/prime-agent-{research,deployment-experiment,rlm-analysis,paradigm-discussion,continual-harness}.md`
@@ -0,0 +1,102 @@
1
+ # DASHR: Repositioning & Rebranding
2
+
3
+ Status: proposal / agreed direction (2026-08-24)
4
+ Audience: maintainers, contributors, future packaging & marketing work.
5
+
6
+ ---
7
+
8
+ ## 1. Pronunciation
9
+
10
+ **DASHR** is read as **"Dasher"** — plain English natural reading. Anyone seeing the word
11
+ should be able to pronounce it without a guide (which is the point of the vowelized
12
+ spelling, see §3).
13
+
14
+ ## 2. Name origin (literal reading)
15
+
16
+ - **DASH** = upstream `DSH` (DeepSeek Harness) with a vowel inserted, so the acronym
17
+ becomes a naturally pronounceable word.
18
+ - **DASHR** = **"better form of dash"** — literally *dasher* with one vowel (`e`)
19
+ removed. The name itself encodes "a leaner-but-more dash".
20
+
21
+ ## 3. Repositioning
22
+
23
+ ### Before (current repo reality)
24
+
25
+ DASHR was positioned as a **plugin**: the RLM mode for `dsh` (npm `dsh-rlm-mode`).
26
+ One capability, installed into an existing dsh setup.
27
+
28
+ ### Now
29
+
30
+ DASHR is repositioned as **"Better Dash"** — a complete, ready-to-run App built on the
31
+ upstream DeepSeek Agent runtime ("Everything is plugin" / Cordis framework).
32
+
33
+ The phrase "Better Dash" is deliberately down-to-earth. We do not want to appear
34
+ grandiose: everything is built on open-source work. What the phrase conveys:
35
+
36
+ - **完整体** — a whole product, not a component.
37
+ - **开箱即用** — one install, works immediately.
38
+ - **接地气** — honest about being open-source-derived; no inflated claims.
39
+
40
+ ### Product shape (the "Linux distro" model)
41
+
42
+ | Layer | Analogy | DASHR reality |
43
+ |---|---|---|
44
+ | Kernel / core | Linux kernel | Upstream official DeepSeek Agent runtime (`dsh`), tracked at latest official release |
45
+ | Distro | Ubuntu / RHEL | DASHR: curated plugin composition + compatibility guarantee |
46
+ | Default enabled flagship | — | RLM mode (the former standalone plugin) |
47
+ | Enterprise services | Canonical custom engagements | Fast custom-agent builds on top of the distro |
48
+
49
+ Commercial positioning:
50
+
51
+ - We do **not** sell the agent core. We sell a **composition of plugins** (a recipe),
52
+ the compatibility matrix behind it, and support.
53
+ - The core stays anchored to the official latest release; we dynamically smoke-test
54
+ every bundled plugin against new core versions.
55
+ - Distribution form: semi-precompiled binary — shaped like a complete App, one-click
56
+ install.
57
+ - Full compatibility with the DASH community ecosystem: after installing the DASHR
58
+ App, users can still use the official plugin marketplace seamlessly.
59
+
60
+ ## 4. Self-owned vs community plugins
61
+
62
+ - **(a) Own plugins**: e.g. improvements where the current PTC code mode falls short
63
+ (RLM mode is the flagship).
64
+ - **(b) Curated community plugins**: selected useful plugins from the ecosystem
65
+ (source: `awesome-dsh-plugin`), each held to the compatibility matrix.
66
+ - **(c) Packaged whole**: the App bundles (a)+(b) into one agent runtime with
67
+ one-click install.
68
+
69
+ ## 5. Known risks (ranked)
70
+
71
+ 1. **The compatibility matrix is the moat.** Upstream is at `0.1.0-rc` (no semver
72
+ guarantees); every rc requires plugin × core smoke tests. The product promise
73
+ does not exist until this CI matrix exists. Build it first.
74
+ 2. **Semi-precompiled binary ships three runtimes.** Node ≥22 + Python 3.11 kernel
75
+ (uv venv) + plugin deps. Realistic v1 form: structured directory + launcher +
76
+ installer (Electron-style), not a true single-file binary.
77
+ 3. **Naming / trademark boundary.** DASHR's name derives from DSH and currently
78
+ carries DeepSeek branding/badges. As a distro we must state clearly in docs that
79
+ this is an **unofficial distribution**, mirroring how Canonical/Debian and
80
+ Fedora/RHEL handle the relationship.
81
+ 4. **"Seamless official marketplace" is conditional.** Our `cordis.patch.yml` bundle
82
+ patch must stay minimal and be pushed upstream wherever possible; any behavior
83
+ divergence breaks the seamlessness promise.
84
+
85
+ ## 6. Repository implications
86
+
87
+ - Three-layer layout going forward: `core/` (the npm plugin, stays independently
88
+ publishable — free acquisition funnel, keeps us honest against vendor lock),
89
+ `distro/` (lockfile + compatibility matrix + packaging), `app/` (launcher /
90
+ installer).
91
+ - `install.sh` evolves from single-plugin installer to distro installer.
92
+ - README narrative shifts from "RLM plugin for dsh" to "a DASH distribution —
93
+ RLM mode enabled by default".
94
+ - The standalone plugin remains published and usable on plain dsh.
95
+
96
+ ## 7. Sequence
97
+
98
+ 1. Build the minimal viable compatibility matrix (target: upstream rc stream).
99
+ 2. Distill the plugin composition (own + curated) into a lockfile.
100
+ 3. Package as directory+launcher App; one-click install.
101
+ 4. Rebrand surfaces (README, docs, badges) to the "Better Dash" positioning with
102
+ the unofficial-distribution disclaimer.