better-dsh 0.2.2-a → 0.2.2-c

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 (86) hide show
  1. package/docs/50_test-reports/2026-09-06-write/345/267/245/345/205/267sandbox/345/215/207/347/272/247/351/200/217/344/274/240bug/345/244/215/345/217/221/345/217/212/346/214/202/350/265/267-/344/272/213/344/273/266/346/212/245/345/221/212.md +43 -0
  2. package/docs/50_test-reports/v0.2.4-ios-focus-zoom-suppression/345/256/236/346/265/213/346/212/245/345/221/212.md +158 -0
  3. package/docs/60_exploration-and-research/01-cordis-runtime/bun-compile-cordis-runtime-bootstrap-research.md +536 -0
  4. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-customization-and-override-mechanics.md +418 -0
  5. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-research.md +350 -0
  6. package/docs/60_exploration-and-research/01-cordis-runtime/dsh-cordis-hotplug-mcp-patch-research.md +265 -0
  7. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-profile-package-map.md +186 -0
  8. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-ui-slot-system-research.md +310 -0
  9. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-backend-data-inventory.md +633 -0
  10. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-strip-boundary-research.md +300 -0
  11. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-wire-appendix.md +3729 -0
  12. package/docs/60_exploration-and-research/02-dsh-webui/web-frontend-composability-research.md +191 -0
  13. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/capture-live-turn.json +1 -0
  14. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/observed-endpoints.json +224 -0
  15. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/remote-inventory.json +110954 -0
  16. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/served-index-sample.html +47 -0
  17. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/session-events.json +9411 -0
  18. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/ws-frame-examples.json +20 -0
  19. package/docs/60_exploration-and-research/03-mobile-ios/dsh-mobile-spa-ios-input-experience-research.md +160 -0
  20. package/docs/60_exploration-and-research/03-mobile-ios/ios-chat-app-bridge-research.md +324 -0
  21. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-jsonl-mapping.md +1532 -0
  22. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode-failed.json +46 -0
  23. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode1.json +1124 -0
  24. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode2.json +1240 -0
  25. package/docs/60_exploration-and-research/05-dashr-dev/plugin-development.md +148 -0
  26. package/docs/60_exploration-and-research/05-dashr-dev/upstream-alignment.md +102 -0
  27. package/docs/60_exploration-and-research/README.md +87 -0
  28. package/docs/60_exploration-and-research/bun-compile-cordis-runtime-bootstrap-research.md +348 -0
  29. package/docs/60_exploration-and-research/dsh-mobile-spa-ios-input-experience-research.md +160 -0
  30. package/lib/index.d.ts +9 -1
  31. package/lib/index.js +258 -6
  32. package/package.json +1 -1
  33. 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 +0 -110
  34. package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +0 -14
  35. package/docs/adr/0002-masking-is-presentation-only.md +0 -15
  36. package/docs/plans/A2A-messaging-channel-test-archive.md +0 -256
  37. package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +0 -137
  38. package/docs/plans/dashr-blueprint-review.md +0 -201
  39. package/docs/plans/dashr-blueprint.md +0 -561
  40. package/docs/plans/dashr-compaction-window-and-archive.md +0 -307
  41. package/docs/plans/dashr-profile-layer-feasibility.md +0 -367
  42. package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +0 -171
  43. package/docs/plans/dashr-security-sandbox-analysis.md +0 -187
  44. package/docs/plans/dashr-surface-invariant-and-omp-imports.md +0 -97
  45. package/docs/plans/ipython-kernel-interactive-interface-test-report.md +0 -152
  46. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +0 -146
  47. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +0 -50
  48. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +0 -79
  49. package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +0 -138
  50. package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +0 -161
  51. package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +0 -109
  52. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +0 -50
  53. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +0 -113
  54. package/docs/plans/recallable-compaction.md +0 -147
  55. package/docs/plans/spike-tag-repro.mjs +0 -102
  56. package/docs/plans/upstream-analysis.md +0 -128
  57. package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -142
  58. package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -193
  59. package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -96
  60. package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -127
  61. package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -150
  62. package/docs/v0.1.8d_artifacts/README.md +0 -138
  63. package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  64. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  65. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  66. package/docs/v0.1.8d_artifacts/functions.json +0 -592
  67. package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  68. package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  69. package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  70. package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  71. package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  72. package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -224
  73. package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -168
  74. package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -123
  75. package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  76. package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  77. package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  78. package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  79. package/docs/v0.2.0b_artifacts/hashline-probe.md +0 -5
  80. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  81. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  82. package/docs/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  83. package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  84. package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -110
  85. package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -86
  86. package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -66
@@ -1,113 +0,0 @@
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.
@@ -1,147 +0,0 @@
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)
@@ -1,102 +0,0 @@
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)
@@ -1,128 +0,0 @@
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`
@@ -1,142 +0,0 @@
1
- # DASHR v0.1.8 改进版复测报告(第一人称实测)
2
-
3
- > 复测方式:仍以 DASHR 运行时自身为被测对象(本会话,dsh Web GUI)。运行时已按上版报告调整并重启,本次对**上版全部问题逐条复测**,并重跑测试套件。
4
- > 复测日期:2026-08-24(同日晚,更新 commit `7ec46ac`)
5
-
6
- ---
7
-
8
- ## 0. 结论摘要
9
-
10
- | 结论 | 结果 |
11
- |---|---|
12
- | 上版 **P0(snapshot 失效)** | ✅ **已修复** |
13
- | 上版 **P1(docstring 回归)** | ✅ **已修复** |
14
- | 上版 P2/P3(命名漂移、masking 张力、fgm→pgmi) | ✅ **全部修复/重新设计** |
15
- | 测试套件 | ✅ **156/156 全绿**(上版 155/163) |
16
- | 遗留问题 | 🟡 README 中后段 + 根 README 仍残留旧架构文档;`compact` 引擎本部署仍未挂载 |
17
-
18
- **一句话结论**:改进版把上版报告里的**功能性问题全部清零**——内核环境自管(Python 3.11 + dill)让 snapshot 复活,delegation 工具从「桥接包装」改为「直接暴露」消除了 masking 与 dual-exposure 的张力;但**文档层还有两处 README 残留旧架构描述**需要清理。
19
-
20
- ---
21
-
22
- ## 1. 本次变更(commit `7ec46ac`)
23
-
24
- ```
25
- dashr: runtime-owned kernel environment + native delegation exposure
26
- ```
27
-
28
- 1. **内核环境自管**(新增 `src/kernel-env.ts`,210 行):运行时自己 provision 一个托管 CPython 3.11 venv(`ipykernel` + `dill`),落在**包内 `.venv-kernel`**(不再 `/tmp` 悬空 symlink)。显式解释器被校验:缺 `dill` = 响亮告警(禁用快照),缺 `ipykernel` = 硬错误。
29
- 2. **原生 delegation 直接暴露**:masking 从 8 名收敛到**仅 2 名**(`send_message` + `report`);`subagent`/`subagent_fork`/`list_agents`/`interrupt_agent`/`workflow`/`ralph` 直接暴露为 `tool.*` 成员;**`rlm`/`agent_list`/`rlm_workflow`/`rlm_ralph` 桥接全部删除**。
30
- 3. **Rebrand**:`@fgm-builds/dashr` → `@pgmi-builds/dashr`;RLM 术语在 CONTEXT/ADR 去强调。
31
-
32
- ---
33
-
34
- ## 2. 上版问题逐条复测
35
-
36
- | 上版问题 | 严重度 | 本次实测证据 | 状态 |
37
- |---|---|---|---|
38
- | snapshot 失效(dill 缺 + Python 3.14) | 🔴 P0 | 实测内核 `Python 3.11.15` + `dill 0.4.1` + `ipykernel 7.3.0`;`.venv-kernel` 指向 uv 托管 3.11;快照测试全绿 | ✅ 修复 |
39
- | docstring 回归 | 🟠 P1 | 实测 `helper.__doc__ == 'First summary line.\n Details follow.'`;`runtime.spec.ts` 绿 | ✅ 修复 |
40
- | `agent_message` vs `send_message` | 🟡 P2 | 实测 `tool.agent_message` → `unknown binding`;`tool.send_message` 为双向桥接;CONTEXT/ADR 已改 | ✅ 修复 |
41
- | flat-global vs `tool.*` | 🟡 P2 | CONTEXT.md「Binding」已改「`tool.*` member」 | ✅ 修复 |
42
- | `fgm` vs `pgmi` | 🟡 P2 | `package.json` name / `cordis.patch.yml` 均 `@pgmi-builds/dashr` | ✅ 修复 |
43
- | masking 7 vs 8 | 🟡 P2 | 重新设计为 2 名,ADR-0002 已同步 | ✅ 修复 |
44
- | masking 对直接面无效(结构性张力) | 🟡 P3 | 决策落地:delegation 直接暴露、`rlm` 删除,张力消除 | ✅ 修复 |
45
- | 桥接错误风格不一致 | 🟡 P3 | `rlm_workflow` 等已删,仅剩 `send_message`(结构化 error 值) | ✅ 消除 |
46
-
47
- ---
48
-
49
- ## 3. 新功能面实测(第一人称逐项)
50
-
51
- ### ✅ 3.1 内核环境自管 —— 通过
52
-
53
- ```
54
- kernel python: 3.11.15
55
- dill: 0.4.1
56
- ipykernel: 7.3.0
57
- ```
58
-
59
- `.venv-kernel/bin/python` 现指向 `/home/u1/.local/share/uv/python/cpython-3.11-linux-x86_64-gnu/bin/python3.11`(真实存在,非悬空)。
60
-
61
- ### ✅ 3.2 原生 delegation 直接暴露 —— 通过
62
-
63
- `tool.subagent` / `tool.subagent_fork` / `tool.list_agents` / `tool.interrupt_agent` / `tool.workflow` / `tool.ralph` 现在**全部直接绑定**(call-through 返回的是真实工具的参数校验错误,而非 `unknown binding`):
64
-
65
- ```
66
- tool.subagent -> REJECTED (invalid arguments: missing required property "description")
67
- tool.list_agents -> bound+callable(返回子代理列表)
68
- tool.workflow -> REJECTED (missing required property "script")
69
- tool.ralph -> REJECTED (missing required property "objective")
70
- ```
71
-
72
- ### ✅ 3.3 桥接收敛(仅 send_message + refine + compact)—— 通过
73
-
74
- ```
75
- tool.send_message -> bound+callable (双向桥接)
76
- tool.refine -> bound+callable
77
- tool.compact -> bound+callable
78
- tool.rlm -> REJECTED (unknown binding "tool.rlm")
79
- tool.agent_list -> REJECTED (unknown binding)
80
- tool.rlm_workflow -> REJECTED (unknown binding)
81
- tool.rlm_ralph -> REJECTED (unknown binding)
82
- tool.agent_message -> REJECTED (unknown binding)
83
- ```
84
-
85
- `rlm` 家族彻底移除,递归改走 `tool.subagent` / `tool.subagent_fork` 直连。
86
-
87
- ### ✅ 3.4 递归 + A2A 全链路(新形态)—— 通过
88
-
89
- ```
90
- tool.subagent spawn → {'kind':'continuable','subagentId':'3e8f3609-...'} (8*9)
91
- child 完成上报
92
- tool.send_message(receiver='child') 下行追问 9*9 → 上报 "81"
93
- tool.send_message(receiver='parent') from root → 结构化 UNAUTHORIZED(guard 仍在)
94
- ```
95
-
96
- ### ✅ 3.5 无回归项 —— 通过
97
-
98
- `tool.*` 绑定、跨 cell 持久化、`ToolCallError(.toolName)`、`asyncio.gather`、顶层 `return` → SyntaxError 均与上版一致,无回归。
99
-
100
- ### ✅ 3.6 测试套件 —— 全绿
101
-
102
- ```
103
- Test Files 18 passed (18)
104
- Tests 156 passed (156)
105
- ```
106
-
107
- 上版失败的 `snapshot-revive` / `snapshot-restore` / `lifecycle` / `session-keys` / `runtime`(docstring) 全部转绿;新增 `bindings.spec.ts`(7)、`parallel.spec.ts`(2)。
108
-
109
- ---
110
-
111
- ## 4. 遗留问题(新发现)
112
-
113
- ### 🟡 4.1 包内 `dashr/README.md` 中后段仍描述旧架构
114
-
115
- header 段已更新(`dsh-rlm-mode`→`dashr`、`RLMRuntime`→`ReplRuntime`、`ipython`→`eval`、kernel 自管),但**中后段未同步**,仍残留:
116
-
117
- - 「**`ipython`** — the only tool the model may call directly」(应为 `eval`)
118
- - 「FLAT top-level callables — `await name({...})`」(应为 `tool.*` member)
119
- - 「bridge callables `rlm`, `send_message`, `agent_list`, `rlm_workflow`, `rlm_ralph`」(已删)
120
- - 「Delegation and messaging (rlm, send_message, agent_list, rlm_workflow, rlm_ralph)」整段 `rlm()` API 文档(已删)
121
- - install 段仍指 `dsh-rlm-mode` + `rlm-mode` preset(preset 已删)
122
- - `dashr-kernel` group `isolate: { rlmRuntime: true }`(旧 realm 架构,现为 host-plane `dashr-repl`)
123
-
124
- ### 🟡 4.2 根 `README.md` 完全未 rebrand
125
-
126
- 根 `README.md` 仍是「# Dashr: RLM Plugin for `dsh`」+ `dsh-rlm-mode` npm badge + 完整 RLM 定位 + `rlm()` API 示例——本次 commit **未触碰根 README**。
127
-
128
- ### 🟡 4.3 `compact` 引擎本部署未挂载
129
-
130
- `tool.compact` 返回 `{'context_tokens': 137635, 'error': 'compact() is unavailable: no ctx.compaction engine is mounted in this composition'}`——桥接存在,但本 composition 无宿主压缩引擎(与上版一致,非本 commit 引入)。
131
-
132
- ### ⚪ 4.4 观察项:会话续接时工具目录未随插件升级刷新
133
-
134
- 本会话(`session-5037d6a6`)跨过了插件更新 + 运行时重启,但**本会话的 system prompt(Tool Catalog)仍是旧版**——仍在声明 `rlm`/`agent_list`/`rlm_workflow`/`rlm_ralph` 可用,而实测运行时已 `unknown binding`。新开会话应得到正确目录,但「持久会话热升级插件后目录不刷新」值得留意。
135
-
136
- ---
137
-
138
- ## 5. 建议
139
-
140
- 1. **清理 README 残留**:把 `dashr/README.md` 中后段(ipython/flat/rlm 家族/install/preset/isolate realm)+ 根 `README.md`(RLM 定位、`dsh-rlm-mode` badge、`rlm()` API)对齐 v0.1.8 实际形态(`eval`、`tool.*`、直接 delegation、`@pgmi-builds/dashr`)。
141
- 2. **验证 compact 部署**:在目标部署形态下挂载宿主压缩引擎,复验 `compact` 与 Global Context Recency Window。
142
- 3. **会话续接目录刷新**(可选):考虑在插件升级/重启后让持久会话的 Tool Catalog 失效或重算,避免模型看到过期工具面。