better-dsh 0.2.4-c → 0.2.5-a
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.
- package/cordis.patch.yml +11 -0
- package/docs/50_test-reports/2026-09-28-ctx-scheme/351/225/277/344/274/232/350/257/235utility/345/256/236/346/265/213/346/212/245/345/221/212.md +155 -0
- package/docs/50_test-reports/2026-10-01-v0.2.4d-web-password-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +105 -0
- package/docs/50_test-reports/2026-10-02-ctx-navigation/345/256/236/346/265/213/346/212/245/345/221/212.md +137 -0
- package/docs/50_test-reports/2026-10-02-v0.2.0-rc.2/345/257/271/351/275/220/350/275/256/345/256/236/346/265/213/346/212/245/345/221/212.md +38 -0
- package/docs/specs/ctx/spec.md +78 -6
- package/docs/specs/model-picker-ios-blur/spec.md +168 -0
- package/docs/superpowers/plans/2026-10-02-ctx-navigation.md +319 -0
- package/docs/superpowers/specs/2026-10-02-ctx-navigation-design.md +209 -0
- package/lib/fs-aware/sandbox-plugin.js +2 -2
- package/lib/url-schemes/index.js +194 -37
- package/lib/web-password.d.ts +156 -0
- package/lib/web-password.js +562 -0
- package/lib/{wrap-Dr8XtIak.js → wrap-Bzdimp4p.js} +1 -1
- package/package.json +18 -3
package/cordis.patch.yml
CHANGED
|
@@ -55,6 +55,17 @@
|
|
|
55
55
|
- id: dashr-remote
|
|
56
56
|
name: 'better-dsh/remote'
|
|
57
57
|
|
|
58
|
+
# Browser session gate: the native flow's door is a per-boot `?token=` URL,
|
|
59
|
+
# and exchanging it mints a durable signed cookie from a key that lives in
|
|
60
|
+
# this home's credential store. This row claims exact `/` (unclaimed
|
|
61
|
+
# upstream — dispatch is exact → longest prefix → fallback) and asks for a
|
|
62
|
+
# password instead, minting the SAME native cookie for the same 30 days.
|
|
63
|
+
# `/index.html` and every `/api` request keep being verified by the native
|
|
64
|
+
# checker, so no upstream code is touched; `?token=` simply stops being a
|
|
65
|
+
# door. The password is the row's own credential record, seeded to `admin`.
|
|
66
|
+
- id: dashr-web-password
|
|
67
|
+
name: 'better-dsh/web-password'
|
|
68
|
+
|
|
58
69
|
# Native compaction at the host plane: the base bundle ships the engine, the
|
|
59
70
|
# `/compact` command, and the tool-result pruner as host rows; dsh-web-app
|
|
60
71
|
# disables them to move compaction behind per-session presets. DASHR is
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# ctx:// scheme 长会话 utility 实测报告(2026-09-28)
|
|
2
|
+
|
|
3
|
+
- **对象**:better-dsh `ctx://` URL scheme(recallable-context 面)
|
|
4
|
+
- **被测构建**:better-dsh **0.2.4-c**(`35535d2`,现役发布版;装于 prod `~/.dsh/profiles/web`)
|
|
5
|
+
- **测试载体**:**第一人称、真实长会话**——本报告就是在该会话里写的。样本参数:15 条真实 user prompt、405 条 agent message、343 次 tool call、**1 次 compaction(shadow 825 items / 386,226 tokens)**、76 条注入消息。非合成夹具,正是该 scheme 的目标场景(超长会话)。
|
|
6
|
+
- **方法**:逐面活体探测(roster / snapshot / episode / raw window / 集合 / 元素 / 错误路径 / 跨 compaction grep),每条结论均有本会话内的真实调用为证。
|
|
7
|
+
|
|
8
|
+
## 一、逐面结果
|
|
9
|
+
|
|
10
|
+
| Surface | 探测 | 结果 |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `ctx://`(roster) | 裸读 | ✅ 10 行自描述面,含每个 sub-path 的语法与 `:raw:N-M` 提示;无需 live agent |
|
|
13
|
+
| `ctx://session`(快照) | 裸读 | ✅ totals(343 tool calls / 15 prompts / 1 compaction)+ segments(compacted 16–2336 vs live 2337–2379)+ **内联 compactions 清单**(label 2348、shadowed 825 items / 386k tokens、8 段 ×100 字预览)+ hints。长会话里这是"我丢了什么"的一张卡,一次读全拿到 |
|
|
14
|
+
| `ctx://session/compactions[2348]` | episode 摘要 | ✅ 8 段全文 verbatim(prepared 面),与本会话真实 checkpoint 内容一致 |
|
|
15
|
+
| `compactions[2348]:600-604` | **shadowed 原始跨度行窗口** | ✅ 精确回到被 compact 掉的历史,带 seq 标签(`[0000212] TOOL bash` 等) |
|
|
16
|
+
| `ctx://session/user_prompts[0]` / `[17]` | 元素面 + seq 二象性 | ✅ 0-based 序数与事件 seq 寻址等价(`[17]`≡`[0]`),返回完整原始 prompt(含中文长文无损) |
|
|
17
|
+
| `user_prompts[17]:1-2` | 元素面行窗口 | ✅ `:N-M` 在元素面上照常生效 |
|
|
18
|
+
| `ctx://session/tool_calls[342]` | 元素面 | ✅ name + arguments + result 三段式(result 空缺见 F2) |
|
|
19
|
+
| `ctx://session/injections` | 索引面 | ✅ **本会话 76+ 条注入的完整台账**:seq、source kind、~100 字预览。subagent-settled / agent-message / agent-instructions / compact-checkpoint 全在——长会话里这就是"我离开期间发生了什么"的账本 |
|
|
20
|
+
| `grep path: ctx://session/transcript` | **跨 compaction 全文搜索** | ✅ 把含 shadowed 跨度的全量 transcript 物化到 `/dev/shm` 检索,命中 6 处 `gate-removal`(含 compact 前的旧事件),**行号 = transcript 规范坐标**,可与 `:N-M` 窗口直接组合。长会话第一杀器 |
|
|
21
|
+
| `compactions[2348]/original` | 已废路径 | ✅ `CTX_BAD_PATH`,错误文本直接给出替代写法("superseded by the :raw / :raw:N-M selectors") |
|
|
22
|
+
|
|
23
|
+
## 二、utility 结论(长会话视角)
|
|
24
|
+
|
|
25
|
+
**该 scheme 在其设计目标场景(超长会话 + compaction 后回溯)里成立且好用**:
|
|
26
|
+
|
|
27
|
+
1. **丢context自知**:快照的 segments + 内联 manifest 让模型精确知道 shadow 了什么(825 items / 386k tokens)以及每段摘要——不需要盲猜。
|
|
28
|
+
2. **三级召回粒度齐全**:摘要(episode 面)→ 精确行(`:N-M` raw 窗口)→ 全文定位(grep 物化检索),三者共用同一套规范坐标,可组合。
|
|
29
|
+
3. **索引面价值实测**:injections 台账在本会话里直接回答了"哪些 subagent 何时 settle 过"这类跨天问题。
|
|
30
|
+
4. **错误质量好**:废路径、未知 key、越界元素全部结构化且回显可操作的修复指引。
|
|
31
|
+
|
|
32
|
+
## 三、Findings(按 §〇.5 攒批,不烧版本)
|
|
33
|
+
|
|
34
|
+
- **F1(utility gap + 错误外 观)**:裸 `ctx://session/user_prompts`(tool_calls / agent_responses 同)→ `CTX_NO_SUCH_ELEMENT`,且错误回显为 `ctx://…[]`——**空括号 URL 不是模型输入的 URL**。impl 把裸集合面当元素查找(`handlers/ctx.ts:486` 的条件把无名 bracket 落进元素分支)。spec 侧该三集合是否应有 index face 存在歧义("user_prompts continues to list" 一句两读);从 utility 看,user_prompts(15 条)加 seq+预览索引面价值高,tool_calls/agent_responses(343/405 条)裸索引过长、宜支持窗口化索引。至少:错误不应回显空括号。
|
|
35
|
+
- **F2(召回盲点,非 ctx:// 渲染缺陷)**:大输出 tool result 在 `tool_calls` 元素面与 transcript 面均为**空串**(样本 seq 2379 / 2406,`resultTextOf` 产出空)。两 face 一致 → 归因于持久层对大 result 的省略存储;但"大输出"恰是长会话里最想召回的内容。建议后续核实上游持久化行为,若确为 elision,ctx:// 侧至少回显 `(result elided, N chars)` 而非静默空。
|
|
36
|
+
- **F3(UX 小刺)**:`read` 的 `offset`/`limit` 分页参数对 `ctx://` URI **静默忽略**(实测 limit:15/20 均无效,injections 返回全量)。行窗口的 sanctioned 机制是 `:N-M`,但原生 read 契约写明"File reads page with offset/limit"——URI 读既不分页也不提示,宜在文档或错误提示里点名。
|
|
37
|
+
|
|
38
|
+
## 四、判定
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 五、第二轮活体复测(2026-09-28 晚,同一会话、4 次 compaction 后)
|
|
43
|
+
|
|
44
|
+
同一长会话的后续采样:距首轮报告又历经 3 次 compaction(现役 4 块 shadow + live 段仅 51 items;totals 1371 tool calls / 35 prompts / 1248 agent messages;会话 2026-09-23 起、跨约 5 天,shadow 合计 2715 items / ~1.40M tokens)。被测构建不变:better-dsh **0.2.4-c** 仍在 prod web profile(磁盘核实),harness 基座 0.1.7-rc.2。
|
|
45
|
+
|
|
46
|
+
| 探测 | 结果 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `ctx://session` 快照 | ✅ 4 块 compaction 全清单内联(2485 / 4634 / 5637 / 7033,含 `replaces_checkpoint` 链与 8 段 preview),segments 图一次读全 |
|
|
49
|
+
| `grep path: ctx://session/transcript`(pattern `0\.1\.3-v`) | ✅ **跨全部 4 块 shadow 命中 16 处**(materialized canonical 行 14998–15308,深处远超 live 起点);召回内容与本会话 checkpoint 事实逐项吻合(0.1.3-v commit 文全文、dev3 满堂红探针命令、prod 安装命令与输出)——跨天跨 compaction recall 零失真实证 |
|
|
50
|
+
| `compactions[2485]:1-2` | ✅ 4 层 compaction 之前的会话首条真实指令 **verbatim 召回**(`[0000012] USER`:0.1.7 对齐令) |
|
|
51
|
+
| `compactions[2348]`(首轮报告引用的旧 label) | ⚠️ **label 漂移(新 F4)**:`CTX_NO_SUCH`,错误列出现役 labels `(2485, 4634, 5637, 7033)` 可即时恢复;但首块 shadow 已从报告时的 label 2348 / span 16–2336 / 825 items / 386,226 tokens 重划为 label 2485 / span 12–2477 / 967 items / 365,535 tokens——后续 compaction 会吸收旧 checkpoint 之后的 live 段并重贴 label |
|
|
52
|
+
| 裸 `ctx://session/user_prompts`(F1 复测) | ⚠️ 依旧 `CTX_NO_SUCH_ELEMENT` + 空括号回显 `ctx://…[]`;错误文案现含集合长度与 0-based 提示(更可用),缺陷面不变 |
|
|
53
|
+
| `read(ctx://session, limit:1)`(F3 复测) | ⚠️ limit 静默忽略、全量快照卡返回——F3 照旧 |
|
|
54
|
+
|
|
55
|
+
### 第二轮结论
|
|
56
|
+
|
|
57
|
+
- **核心承诺在 4×compaction 规模下依旧成立**:快照自知、清单内联、跨 shadow grep、深层 verbatim 召回全部可用,且 grep 召回经与 checkpoint 事实比对无失真。长会话跨 5 天后,scheme 仍是「我丢了什么 / 怎么拿回来」的完整答案。
|
|
58
|
+
- **F4(新,compaction label 非稳定引用键)**:后续 compaction 重划更早 shadow 的 label 与 span(2348→2485),跨 turn 按 label 引用会悬空。建议:文档点名「compaction label 仅对当次 shadow 结构有效,跨 turn 引用先重读快照」(错误信息已支持该恢复路径);或提供快照中已有的 `compactionId`(uuid)作稳定寻址键。
|
|
59
|
+
- F1 / F3 复现如前,攒批不变。判定维持**通过**。
|
|
60
|
+
**通过**。0.2.4-c 的 `ctx://` 面在真实超长会话中全部核心承诺兑现:快照自知、清单内联、三级召回、跨 compaction grep。F1–F3 均为小瑕,按惯例攒批并入下次发布轮处理。
|
|
61
|
+
|
|
62
|
+
## 六、第三轮活体复测(2026-09-28 14:03,同工作线后继会话实例、1×compaction)
|
|
63
|
+
|
|
64
|
+
第三轮换载体:不再是前两轮的长会话本体(09-23 起、4×compaction),而是同一 superd 工作线的**后继会话实例**(`session-9d55447a`,cwd `/home/u1/workspaces/superd`,创建于 2026-09-25 11:34,2026-09-27 14:15 经历唯一一次 compaction)。采样时点参数:shadow seq 16–2099 = **681 items / 361,515 tokens**、live 仅 36→54 items(两次读数间自增)、totals ≈ 349 tool calls / 11 prompts / 315 agent messages / 193 reasoning blocks。被测构建磁盘再核实不变:better-dsh **0.2.4-c**(prod web profile)+ harness 0.1.7-rc.2。本轮顺带回答一个问题:**scheme 在「普通」形态(仅 1×compaction)下是否同样成立**。
|
|
65
|
+
|
|
66
|
+
| 探测 | 结果 |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `ctx://session` 快照 | ✅ 单 compaction 全清单内联(label 2108 / checkpoint_seq 2109 / `compactionId` uuid / `replaces_checkpoint: null` / 8 段 preview)+ segments 图;两次读取间 totals 活体前移(tool_calls 343→349、live 36→54)——快照与持久层实时一致 |
|
|
69
|
+
| `compactions[2108]:1-3` | ✅ shadow 首事件 verbatim(`[0000016] USER` @native-ui-fusion 两份计划文档),与 checkpoint「Primary Request」吻合 |
|
|
70
|
+
| `user_prompts[0]` | ✅ 同一事件的元素面 verbatim(`[0]` ≡ seq 16 二象性复现);episode 面与元素面跨 face 一致 |
|
|
71
|
+
| grep `82de0f3` on `ctx://session/transcript` | ✅ 5 命中横跨 shadow+live:台账终局 bash 命令全文、memory_add 载荷、checkpoint 摘要行、以及 grep 调用自身(检索自包含);召回内容与本线真实终局(0.1.5 merge/tags/publish/rig 迁移)逐项吻合,零失真 |
|
|
72
|
+
| `tool_calls[342]` | ✅ name+arguments verbatim;result 空串 → **F2 三度复现** |
|
|
73
|
+
| 裸 `ctx://session/user_prompts`(F1 复测) | ⚠️ 照旧 `CTX_NO_SUCH_ELEMENT` + 空括号回显;错误含集合计数与 0-based 提示 |
|
|
74
|
+
| `read(ctx://session, limit:1)`(F3 复测) | ⚠️ 照旧静默忽略、全量快照返回 |
|
|
75
|
+
| `?q=` 行过滤(新探测) | ❌ **F5(新)**:`Error: ctx://: unsupported selector kind "query"`——harness 内部 scheme 选择器契约记载 `?q=<q>`(dot-path 搜索 / 行过滤),ctx provider 在 selector 解析层即拒;fail-closed、错误干净,但回显丢 face(只剩裸 `ctx://`)。实用面无损(grep on ctx path 即行过滤替代,三轮均已证),属契约/文档缺口而非功能缺陷 |
|
|
76
|
+
| `thinking[0]:1-2` / `system:1-3` | ✅ 两面首次入矩阵:首个 reasoning 块、会话级 system 消息 verbatim,`:N-M` 在元素面照常生效。另观察:快照 `system_prompt.chars` 恒 0(preset prompt 统计)与 system 消息面是两回事,前者语义未表(记录,不立案) |
|
|
77
|
+
| F4 label 漂移 | N/A——单 compaction、轮内无重划;`compactionId` uuid 确认在清单在场,round 2 的稳定键建议继续成立 |
|
|
78
|
+
|
|
79
|
+
### 第三轮结论
|
|
80
|
+
|
|
81
|
+
- **核心承诺在普通形态(1×compaction、live 36 items)全额兑现**:快照自知、清单内联、三级召回、跨 shadow grep、跨 face 一致性全部复现,grep 召回与外部事实(git/npm/rig 终局)比对无失真。scheme 的 utility 不依赖极端 compaction 深度,首次 compaction 后即达设计意图。
|
|
82
|
+
- **F5 入批**(`?q=` selector 未实现 + 错误回显丢 face);F1/F2/F3 三度复现、攒批不变;F4 本轮无复现机会。判定维持**通过**。
|
|
83
|
+
|
|
84
|
+
## 七、设计复核:compaction 面的体量语义与渐进披露(2026-09-28 14:2x,user 提问触发,源码+实测双证)
|
|
85
|
+
|
|
86
|
+
user 之问:裸读 `compactions[<id>]` 返回 digest 还是 shadowed 全文?若 auto-compaction 阈值 500k tokens,召回工具自己会不会把上下文塞爆?核对 `better-dsh/src/url-schemes/handlers/ctx.ts`(L332–426)后的事实:
|
|
87
|
+
|
|
88
|
+
| URL 形态 | 返回 | 体量 |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `ctx://session` | 快照卡:8 段 ×100 字 summary_preview + shadowed range/items/**tokens** + compactionId | 有界(本会话实测 ~2k tokens) |
|
|
91
|
+
| `ctx://session/compactions` | 逐 episode 一行:label / checkpoint_seq / compactionId / at / range+items+tokens / replaces_checkpoint / 120 字 preview | 每块 ~1 行 |
|
|
92
|
+
| `compactions[<id>]`(裸) | **仅 digest**(= compaction 时定稿的 8 段 checkpoint 摘要,`applyFace(..., 'prepared')`);不随 shadowed 体量增长(本会话 361k shadow → ~4.5k digest,≈80:1) | 有界 |
|
|
93
|
+
| `compactions[<id>]:N-M` | shadowed span 行窗口 | 窗口即上界 |
|
|
94
|
+
| `compactions[<id>]:raw`(span > 64 KiB) | **仍返回全文**,仅尾注一句「original span is N chars — page with :N-M or grep」(L419,warn-don't-block) | ⚠️ **无硬护栏** → **F6** |
|
|
95
|
+
|
|
96
|
+
- **结论(user 的设计诉求已大半在场)**:默认路径(一切裸 URL)永不返回 bulk 原文;「digest + 寻址范围 + statistics」正是快照/清单/episode 三层的现役形态,digest 体量 = checkpoint 本身(模型上下文里已有同一份,重读≈复读)。**残余风险一处 = F6**:>64 KiB span 的裸 `:raw` 只警示不拦截。500k-token shadow(≈2 MB)一次裸读仍会倾泻。建议升级为 bash 式 spill-to-file(本仓 grep 物化 `/dev/shm/dashr-url-*/content.txt` 已有先例可复用:截断 + 落盘 + 报路径),或硬拒并指引 `:N-M` / grep。**F5 修正**:`?q=` 不支持并非首发现——2026-09-12 `url-schemes-grammar-matrix` 报告已记录同缺陷(彼处亦编 F5),本轮系复测而非新发现。
|
|
97
|
+
- **Context injection root**:`injections` 裸读 = 索引台账(seq + source kind + 100 字预览,L436–442),**非全文**——比 user 预期(「直接给可以」)更省;全文按条 `[n]`,`:raw` 才全量拼接(该 face 无 oversize 注记,同类小隐患,量级低,附于 F6 备注)。
|
|
98
|
+
- **Sub-agent(user 之前提需修正)**:master 会话日志**并不内嵌** child 全 transcript——内嵌的只有终态工件:`agent` 工具调用的 arguments+result(`tool_calls[k]` 可寻址,result 携带 durable subagent id)与 report/settled 注入(`injections[k]`)。child 全 transcript 是独立 session 文件,专用寻址面 = **`agent://`**(design.md D6):`agent://` 家族 roster(仅 continuable 后代;**one-shot child 不入 roster**——只能经 master transcript 的 tool_calls 找回,小 gap 备注)/ `agent://<id>` 终态输出 / `agent://<id>/transcript` 全 transcript / `agent://<id>/<child>` 嵌套;settled child 经 sessionPersistence 仍可寻址;跨家族 id 一律 `AGENT_UNKNOWN_ID`(寻址范围 = 自家族,含授权语义)。两 scheme 组合即完整链:`ctx://session/tool_calls[k]` 拿 id → `agent://<id>/transcript` 拿全文。ctx://session 无需也不应再抠 subagent 专字段。
|
|
99
|
+
|
|
100
|
+
## 八、长会话导航化:设计定调与 findings F7–F10(2026-09-28,user 提问触发;下一波开发即做此项)
|
|
101
|
+
|
|
102
|
+
### 载体与证法
|
|
103
|
+
|
|
104
|
+
本轮实测载体 = 本会话 `session-36c2b2ef-a498-49d0-8ff6-af1a92a758ad`(探测时 **1×compaction**:shadow seq 16–2336 = 825 items / 386,226 tokens,live 2337–2379,totals 343 tool calls / 15 prompts;同轮内 totals 已前移至 17 prompts)。**F7–F10 均为代码/规格级缺陷**(与载体无关),活体探测仅作证;§七 的源码复核(`handlers/ctx.ts` L332–426)与本轮互为正交。
|
|
105
|
+
|
|
106
|
+
### 范畴声明(user 裁决 — 写死为非目标)
|
|
107
|
+
|
|
108
|
+
本工具族 = **以文本关键词为主的可回溯导航**(原文 + 索引 + 寻址)。**语义层不是我们的工作**:向量检索、语义索引属于记忆类工具(本 profile 并装 corti-memory 一类),属不同工具分类。理由:大模型本身就是语言模型——同义替换、中英转换、换关键词变着法 grab 都是它的本职;我们只需保证**原文可取 + 可寻址**。故:不做 embedding、不做语义排序、不做「我记不清那个词」的检索。我们提供的是电话簿 + 索引 + 指针,不是记忆。
|
|
109
|
+
|
|
110
|
+
### Findings
|
|
111
|
+
|
|
112
|
+
**F7(高 — 必须先修):surface 单位 ≠ 可寻址单位(seq vs line)**
|
|
113
|
+
|
|
114
|
+
- manifest 的 `shadowed_range` 是 **seq 单位**(`{start:16, end:2336}`);但唯一的窗口选择器 `:N-M` 是 **line 单位**。
|
|
115
|
+
- 实测:`compactions[2348]:16-16` → 空行(seq 16 实际位于 transcript 行 1);该 span 实际占 transcript 行 ≈1–5230。
|
|
116
|
+
- 后果:照 manifest 字面下 `compactions[2348]:16-2336`,拿到的是 **~45% 的静默截断视图**——不报错、内容相关,模型会自信地以为「我已读过 shadowed 范围」。对导航器而言这是最坏的失败模式(静默非完整)。
|
|
117
|
+
- 修法(改动很小):manifest / episode 携带 `lines:{start,end}`(或改以行区间为主、seq 仅作元数据)。episode 面**本已接受**行窗口,缺的只是把「可寻址范围」告诉模型。
|
|
118
|
+
|
|
119
|
+
**F8:`:path/` 选择器在 ctx:// 未实现(F5 的姊妹项)**
|
|
120
|
+
|
|
121
|
+
- 实测 `ctx://session:path/totals` → `unsupported selector kind "path"`;`?q=` 为 F5(§六已录,且据 §七 更正系 2026-09-12 旧账复测)。
|
|
122
|
+
- 二者在模型面 `url-schemes-instruction.md` 中列为**通用**选择器、无 per-scheme 免责;`CTX_BAD_SELECTOR` 文案不回显支持集(ctx 其它错误均为模范级)、且回显丢 face(只剩裸 `ctx://`)。
|
|
123
|
+
- utility 影响:窄读一个字段(`:path/totals.tool_calls`,省去整张快照卡)与过滤一个索引面(`injections?q=subagent-settled`)恰是长会话导航要的窄口径。
|
|
124
|
+
|
|
125
|
+
**F9(低):快照无 `asOf`** — totals 在会话推进中前移(本轮 15→17;§六亦观察 live 36→54)。模型缓存一次快照后在陈旧数字上推理,无自知。建议快照带 `asOf`(seq/line),或明示「每次读都是即时值」。
|
|
126
|
+
|
|
127
|
+
**F10(中):越界静默空串** — 实测 `compactions[2348]:3300` 有内容、`:5500` → 空串。episode 面确实被 span 约束(好),但:① 越界与 span 内空行不可区分;② **上界落在 3300–5500 之间且无从得知**(无任何面告知)——这本身就是 N1 要解决的问题。建议边界显式(如 `[end of episode span at line N]`)。
|
|
128
|
+
|
|
129
|
+
### 设计立场(本轮定调,供下波开发直接采)
|
|
130
|
+
|
|
131
|
+
1. **坐标统一不变式(user 点明)**:scheme 展示给模型的每一个数字/单位(行、段、seq、label),都必须是**同一 URL 族内可直接寻址的**;不可寻址的数字不得作为指针出现(纯 metadata 须显式标注单位)。当前违背者 = F7。这是「导航系统」与「一堆面」的分界,应写成规格不变式。
|
|
132
|
+
2. **给指针,不给统计(user 校正用词)**:原提案的「statistics」实指**可导航坐标 + 方向标**(user 原用「state」一词,其预设 = surface 出来的 sequence/line/段落等同于工具可寻址的 selector——该预设正确,当前实现违背它,即 F7)。计数只在作为 **fidelity 信号**时保留一行:`user_turns : tool_calls` 比 → 决定摘要该不该信(tool 重的 span 摘要可信、细节可再生;user 意图密集的 span 必丢细节 → 必须下钻)。**方向标** = 按类型分组的坐标清单,全部以行坐标输出、直接可喂 `:N-M`:
|
|
133
|
+
- user turn 坐标(实测:17 个 user prompt 的行号清单一眼看出会话重心分布——前 1500 行仅 4 轮,其后密集;但今天需要模型自己发明 `grep '^\[\d{7}\] USER$'`,非 scheme 给的 affordance);
|
|
134
|
+
- 失败 tool call / 重试坐标(「哪里出过事」);
|
|
135
|
+
- **touch 过的文件路径 + 次数**(编码场景最值的语义索引:「哪个 episode 动过 `auth.ts`」);
|
|
136
|
+
- span 内**前序 checkpoint 数**(决定「这是不是摘要的摘要、该往哪个 label 下钻」;本会话实测 = 1,链深 1)。
|
|
137
|
+
3. **渐进披露与递归扇出**:10M–100M token 规模下聚合计数可活、扁平名册活不下来(5 亿 token 可能有数千 user turns)→ 每层必须用一屏回答「这里有什么 + 下一步去哪」。到那个尺度 seq/line 都失去直觉,**时间**与**主题(文件/子系统)**才是稳定轴,故两者必须进每个节点的坐标块。
|
|
138
|
+
4. **digest 复读问题的两看(user 提出,本轮定论)**:
|
|
139
|
+
- **latest compaction**:其 digest 已作为 checkpoint 消息**驻留在当前上下文**里(实测:digest 即 seq 2349 的 `compact-checkpoint` 注入,可寻址于 `transcript:5230-5299`,下一事件 seq 2358 起于行 5300)。故裸读**不应再倾泻 digest**,而应回**自定位提醒**:「本次 digest 已在你上下文中(`transcript:5230-5299`),需要原文可自行取;这里有用的是 span 导航」+ 指针块。` :raw` 仍返回原文跨度 ⇒ digest 永不丢失(它本身可寻址)。
|
|
140
|
+
- **older compaction**:其 digest 已被二次压缩进更新的 checkpoint,只存在于 span 内 ⇒ **应当照常返回全文 digest**(它是该段历史最便宜的入口,且不构成「吃回来」)。
|
|
141
|
+
- **规则化**:digest 正文的返回条件 = **该 digest 未驻留于 live 上下文**(即仅非 latest episode)。
|
|
142
|
+
- **设计警戒(user 赞同)**:stat/digest 只能是指针、不能是内容——嵌摘要 = 把刚 compact 掉的东西又吃回来。
|
|
143
|
+
|
|
144
|
+
### 下波开发 backlog(建议序)
|
|
145
|
+
|
|
146
|
+
| # | 项 | 依据 |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| N1 | episode 节点坐标可寻址化:manifest / episode 暴露 `lines:{start,end}`;越界边界显式 | F7 / F10 |
|
|
149
|
+
| N2 | episode prepared 面改「导航块」:latest → 自定位提醒 + 指针(不倾泻 digest);older → 全文 digest + 指针 | 设计立场 4 |
|
|
150
|
+
| N3 | 方向标(scoped landmark 名册):user turns / failures / touched paths / prior checkpoints,行坐标输出 | 设计立场 2 |
|
|
151
|
+
| N4 | fidelity 一行(`user_turns : tool_calls`)内联进 manifest 每 episode | 设计立场 2 |
|
|
152
|
+
| N5 | `:path/` + `?q=` 在 ctx:// 落地,或在 instruction 明示 per-scheme 差异;`CTX_BAD_SELECTOR` 回显支持集与 face | F8 / F5 |
|
|
153
|
+
| N6 | 快照 `asOf`(或明示即时性) | F9 |
|
|
154
|
+
|
|
155
|
+
- 判定:**通过,且方向确认**。方案不需要新机制——F7 的修法是把已有数字换成可寻址的那套单位;N2–N4 都是在现有 episode/快照结构上加指针,不引入新检索层。
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# v0.2.4-d `dashr-web-password` 密码门(token → password)实测报告
|
|
2
|
+
|
|
3
|
+
日期:2026-10-01
|
|
4
|
+
组件:`better-dsh/web-password`(新 row `dashr-web-password`),dev 版本 `0.2.4-d`
|
|
5
|
+
裁决来源:user 直接指令 —— 「take the native cookie minting, only replace the pw for token url, i.e. 30 days cookie expiry, ask user for pw again to mint cookie」+「credential store, default, hash of "admin", dun invent a pw setup step」
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 一、要解决的问题与结论
|
|
10
|
+
|
|
11
|
+
原生 `dsh web` 的门是一枚 **per-boot 的 `?token=` URL**:它只负责首铸一枚 30 天签名的浏览器 cookie,之后靠 cookie 通行(`$DSH_HOME/.credentials.yaml` 里的 `client-connection/browser-session` 是签名密钥,持久)。
|
|
12
|
+
|
|
13
|
+
user 要求:**把这扇门换成密码**,cookie 仍用"原生的那一套"(同样的密钥、同样 30 天)。
|
|
14
|
+
|
|
15
|
+
结论:**可行,且无需改动任何上游代码。** 关键裁决 ——「整个子包 patch 掉」不成立:`@deepseek-ai/dsh-client-connection` 1493 行里认证只占一个 311 行文件(`browser-auth.ts`),其余是 RPC 载体 / `/api` 桥 / trust fence;而它的 row 同时供养浏览器半边(`dsh.client`),换 row name 会连带干掉前端传输。真正的缝不在包,在**路由表**与**cookie 规范的公开性**:
|
|
16
|
+
|
|
17
|
+
1. webserver dispatch = `exact` → longest `prefix` → `fallback`(`packages/host/webserver/src/index.ts:318`),而 **exact `/` 上游无人占用** → 我们拿下。
|
|
18
|
+
2. 页面侧的唯一鉴权点是 fallback owner 里的 `ctx.connection.authorizeIndex`,而 `?token=` 兑换**只在 `pathname === '/'` 分支存在**(`browser-auth.ts:238`)。占了 `/`,token 门自然退休。
|
|
19
|
+
3. `/index.html`、`/api` 与其余路径继续走原生校验器;我们铸的是**同规范、同密钥**的 cookie,原生校验器直接放行。唯一的例外是 `/` 本身:cookie 有效时由本插件**用上游自己的 dist 解析器渲染同一份 index**(见下 §二 的二次修订),所以登录后 URL 停在 `/`,不产生任何跳转。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 二、改动点
|
|
24
|
+
|
|
25
|
+
| 文件 | 性质 |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `better-dsh/src/web-password.ts` | 新增(~640 行,host-only 插件,无 client 半边) |
|
|
28
|
+
| `better-dsh/test/web-password.spec.ts` | 新增(14 例;**用上游真实 `BrowserAuth` 类做 oracle**,非自证) |
|
|
29
|
+
| `better-dsh/cordis.patch.yml` | 新增 1 条 insert 行 `dashr-web-password`(Plugins 页可独立开关的组件) |
|
|
30
|
+
| `better-dsh/tsdown.config.ts` · `package.json` | 新 subpath entry `./web-password`;peer `dsh-credentials` / `dsh-host-webserver` |
|
|
31
|
+
| `@deepseek-ai/*` 上游 | **零改动**(这是本方案的全部意义) |
|
|
32
|
+
|
|
33
|
+
密码本身是插件自己的 credential record `dashr-web-password/passphrase`:`{version:1, algorithm:'scrypt', salt, hash, N:16384, r:8, p:1, keylen:32}`。**首次激活若无记录就自动播种 `scrypt('admin')`** —— 零设置步骤,开机即用。改密码 = 替换该 record(无 UI / 无 CLI,user 明令不发明设置步骤)。
|
|
34
|
+
|
|
35
|
+
流程:`GET /` 无有效 cookie → 服务端渲染密码表单;`POST /` 校验通过 → 铸**原生格式** cookie(`dsh-auth-<b64url(sha256(authority))>`,`v1.<b64url(json)>.<b64url(HMAC-SHA256)>`,`Max-Age/Path/Expires/HttpOnly/SameSite=Strict` 与原生逐字一致)→ `303 /`。带 cookie 的 `GET /` 由本插件直接渲染 SPA index(dist 锚点取自 `@deepseek-ai/dsh-web-app` 导出的 `internals.resolveDistIndex()`,即上游 fallback 自己用的那个函数;`<base href="./">` 插入与 `host-frontend-static` 逐字一致),**零跳转,URL 保持 `/`**。连续 6 次失败起按 peer 指数退避(上限 60s,429 + `Retry-After`)。
|
|
36
|
+
|
|
37
|
+
> 二次修订(2026-10-01,user 反馈「登录后 URL 不该变成 /index.html」):初版是 `303 /index.html` 借原生 fallback 出页面,代价是 URL 脏。现在改为在 `/` 原地渲染,`/index.html` 不再是流程的一部分(直接访问仍由原生放行,不做重定向)。dist 锚点一旦解析失败(例如上游不再导出 `internals`),本插件**降级**回 `303 /index.html` 而不是 503 —— 只有渲染这一环失败,认证本身完好。
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 三、验证
|
|
42
|
+
|
|
43
|
+
### 3.1 单测(20/20,含与上游实现的互操作 + root 门端到端)
|
|
44
|
+
|
|
45
|
+
`test/web-password.spec.ts` 直接 import 上游源码导出 `@deepseek-ai/dsh-client-connection/src/browser-auth.ts`,用**真实 `BrowserAuth` 类**当 oracle 做双向交叉验证:
|
|
46
|
+
|
|
47
|
+
- 我们铸的 cookie → 真实 `auth.isAuthenticated()` = `true`;
|
|
48
|
+
- 真实类经 `?token=` 兑换铸出的 cookie → 我们的 `decodeSessionCookie` + `sessionAuthenticated` = `true`;
|
|
49
|
+
- 篡改 body / 篡改签名 / 换密钥 / 过期 / 超 30 天 / authority 错绑 → 全部拒绝。
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Test Files 1 passed (1) Tests 14 passed (14)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
全量回归(合入后):
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Test Files 57 passed (57) Tests 641 passed | 1 skipped (642)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`npm run typecheck:host` 0 错;`npm run build` 产出 `lib/web-password.js` + `.d.ts`。
|
|
62
|
+
|
|
63
|
+
### 3.2 4999 rig 第一人称实测(真实 HTTP + 真实原生校验器)
|
|
64
|
+
|
|
65
|
+
交付形态:`npm pack` → `better-dsh-0.2.4-d.tgz` → `plugin remove` → `plugin add` → `start.sh`(`DSH_HOME=.test/home/compat`,物理安装,非 symlink)。
|
|
66
|
+
|
|
67
|
+
| # | 动作 | 结果 |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| A | `GET /`(无 cookie) | `200` + 密码表单(`action="/"`) |
|
|
70
|
+
| B | `GET /?token=<本 boot token>` | `200` 表单,**`Set-Cookie` 计数 = 0** ⇒ token 门已退休 |
|
|
71
|
+
| C | `POST /` 密码错 | `401` + "Wrong password." |
|
|
72
|
+
| D | `POST /` 密码 `admin` | `303 → /`(不再 `/index.html`) + `Set-Cookie: dsh-auth-…; Max-Age=2592000; … HttpOnly; SameSite=Strict`(=30 天,与原生同口径) |
|
|
73
|
+
| E | `GET /`(带 cookie) | **`200` + 37787 B 完整 index**(`<base href="./">` ×1、`__DSH_BOOT__` ×1),**无 `Location` 头** ⇒ URL 就是 `/` |
|
|
74
|
+
| F | `GET /index.html`(带 cookie) | `200`(原生路径仍在,不做重定向) |
|
|
75
|
+
| G | `GET /api` | 无 cookie `401`;带 cookie `404`(越过鉴权栅栏,落到路由解析)⇒ `/api` 侧原生 `isAuthenticated` 同样放行 |
|
|
76
|
+
| H | 连错 6 次 → 第 7 次 | 第 1–6 次 `401`,第 7 次 `429 Retry-After: 2`;窗口过后 `admin` 恢复 `303` |
|
|
77
|
+
| I | `PUT /` / `HEAD /` | `405` / `200` |
|
|
78
|
+
| J | **跨重启**:cookie 早于本 boot 铸出 | `GET /` → `200` 直接出 app(密钥在 credential store,重启不掉) |
|
|
79
|
+
| K | `web --dump-config` | 含 `- id: dashr-web-password / name: better-dsh/web-password` |
|
|
80
|
+
|
|
81
|
+
### 3.3 真浏览器端到端(headless Chrome,dvc://browser)
|
|
82
|
+
|
|
83
|
+
1. 打开 `http://127.0.0.1:4999/` → `title: dsh web`,表单在场;
|
|
84
|
+
2. 填 `admin` 提交 → **URL 仍是 `http://127.0.0.1:4999/`**(无 `/index.html`),`title: DSH Local Build`,`window.__DSH_BOOT__` 在场,`#root` 已挂载(`childElementCount = 1`);
|
|
85
|
+
3. 等 2.5s 读页面文本:`"Into the Unknown Preview superd Standard mode Describe what you want to build, / commands, @ files or sessions Workspace Write GLM-5.3-Flash Default"` ⇒ **SPA 真的起来了**;
|
|
86
|
+
4. 再导航/刷新 `/` → 直接出 app,**不再问密码**(30 天 cookie 生效),URL 保持 `/`。
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 四、已知边界 / 未做
|
|
91
|
+
|
|
92
|
+
1. ~~登录后 URL 是 `/index.html`~~ —— 已修(见 §二 二次修订):登录后 URL 就是 `/`,`/index.html` 不再出现在流程里。
|
|
93
|
+
2. **host 日志在本 composition 下不打印**(`ctx.logger('dashr-web-password')` 的 info/warn 没进 rig 日志——原生 web composition 只输出 URL 行)。失败诊断因此写进 503 响应体(自包含文案),日志调用保留(换 composition 仍有效)。
|
|
94
|
+
3. **密码明文过 HTTP**:user 明确裁决 —— 本地/LAN,公网走 HTTPS,不再是问题。
|
|
95
|
+
4. **`?token=` 链接仍在启动时打印**(`web-runtime` 的 `printUrl: true`),但它现在只把人带到密码页。刻意不改:省一条 patch,且打印的 URL 仍然可用(只是多一步)。
|
|
96
|
+
5. **未发 npm**。按本仓红线,发布需 user 单次明确放行;本次仅 dev 版本 `0.2.4-d` + rig 物理安装。
|
|
97
|
+
6. **未改上游任何文件**;回滚 = 在 profile 用户层给 `dashr-web-password` 行写 `{disabled: true}`(原生 Plugins 页 toggle 即可),或退回 `0.2.4-c`。
|
|
98
|
+
7. **新增一处上游耦合(有意的,且降级安全)**:`/` 的 index 渲染依赖 `@deepseek-ai/dsh-web-app` 导出的 `internals.resolveDistIndex()`。选它而不是自己拼路径,是因为 dist 锚点属于该包的装配事实(它从已安装的 `@deepseek-ai/dsh-web-frontend` 推导),复制一份必然随上游漂移。上游若删掉该导出,本插件不会崩——降级回 `303 /index.html`(旧行为),只是 URL 又脏一次。新增 peer:`dsh-web-app`(optional,懒 import,非 Web composition 不触达)。
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 五、操作备忘(给下一位)
|
|
103
|
+
|
|
104
|
+
- 本机 `pnpm` 在 `PATH` 上的默认是 `/usr/local/bin/pnpm` **10.29.2**(store `v10`),而 rig profile 的 `node_modules` 是用 **11.7.0** 装的(store `v11`)→ 直接跑 `dsh plugin add/remove` 会 `ERR_PNPM_UNEXPECTED_STORE`。**先 `export PATH="$HOME/.local/bin:$PATH"`**(那里的 pnpm 是 11.7.0)。
|
|
105
|
+
- tarball 改内容必须 `remove` → `add` 一个来回,`add` 幂等不刷新(同路径同版本 = `added 0`)。
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# ctx:// 长会话导航化实测报告(2026-10-02)
|
|
2
|
+
|
|
3
|
+
- **对象**:better-dsh `ctx://` scheme 长会话导航化 —— backlog N1–N6 + findings F1/F2(自 `2026-09-28-ctx-scheme长会话utility实测报告.md` §八)
|
|
4
|
+
- **被测构建**:better-dsh 0.2.4-d(+ 本次改动,未发布),harness 基座 **0.2.0-rc.2**(本轮对齐)
|
|
5
|
+
- **载体**:单测夹具 + 4999 rig 第一人称活体(headless 真实 agent session,模型 = deepseek-flash)
|
|
6
|
+
- **设计/规格**:`docs/superpowers/specs/2026-10-02-ctx-navigation-design.md`;live spec `docs/specs/ctx/spec.md`
|
|
7
|
+
|
|
8
|
+
## 一、改动一览
|
|
9
|
+
|
|
10
|
+
| 项 | 内容 |
|
|
11
|
+
|---|---|
|
|
12
|
+
| N1/F7/F10 | 新增 transcript line index(`buildTranscript`);episode/manifest/快照暴露 `lines:{start,end}` + 标注 `seq=`;episode 行窗 **transcript 相对**(`compactions[l]:N-M` ≡ `transcript:N-M`),越界返回显式边界注记(不再静默空/截断) |
|
|
13
|
+
| N2 | digest residence:**latest** episode prepared face = 导航块(不重吐 digest,指向 `digest resident at seq=<checkpointSeq>`);older = 全文 digest + 指针块 |
|
|
14
|
+
| N3 | landmark 名册(user turns / failures / touched paths / prior checkpoints,全为 transcript 行坐标,封顶) |
|
|
15
|
+
| N4 | `fidelity=<user_turns>:<tool_calls>` 内联 manifest/快照/episode 指针块 |
|
|
16
|
+
| N5/F5/F8 | `:path/` + `?q=` 在 ctx:// 落地(复用 `applySelector`),manifest 也走 `applySelector` |
|
|
17
|
+
| N6/F9 | 快照 `asOf:{seq,line}` |
|
|
18
|
+
| F1 | `user_prompts`/`tool_calls`/`agent_responses` 裸读给索引面(长集合封顶 20 + tail),错误不再回显空括号 |
|
|
19
|
+
| F2 | `resultTextOf` 增加 flat text-block 兜底 |
|
|
20
|
+
|
|
21
|
+
## 二、F2 根因更正(重要)
|
|
22
|
+
|
|
23
|
+
报告 §八 曾推断「持久层对大 result 的省略存储」。实测 0.2.0-rc.2 真实 `tool/result` 事件后确认根因是**内容块形状变化**:0.2.0 的 tool-result message `content` 是**平铺** `[{type:"text",text:"…"}]`,而 `resultTextOf` 只取**嵌套** `tool-result` 块 → 对所有 result 一律产空。本次改为嵌套优先、平铺兜底,`tool_calls[<seq>]` 的 result 恢复非空。非「省略」,无需 elision 标记。
|
|
24
|
+
|
|
25
|
+
## 三、验证
|
|
26
|
+
|
|
27
|
+
**单测**:`ctx.spec.ts` 23→30(新增 7:N1 坐标/asOf、N1/F10 transcript 相对 + 越界注记、N2 最新/旧 episode、N3 landmark、N5 `:path/`+`?q=`、F1 索引面、F2 flat result)。全量 **648 passed / 1 skipped**(57 文件);`tsc --noEmit` **0 错**。关键不变式测试:episode `:N-M` ≡ `transcript:N-M`(episode span ≡ transcript slice,结构上保证坐标一致)。
|
|
28
|
+
|
|
29
|
+
**第一人称(headless,dsh 0.2.0-rc.2)**:真实 session 内逐面活体探测,agent 复述各步通过:
|
|
30
|
+
- `ctx://session` 解析,含 `asOf:{seq:26,line:311}` 卡 + totals(`user_prompts:1` 等);
|
|
31
|
+
- `ctx://session:path/totals.tool_calls` 窄读 → 数字(`3`);
|
|
32
|
+
- `ctx://session/user_prompts` / `tool_calls` 索引面正常(含 in-progress 调用的 `(no result captured)` 行);
|
|
33
|
+
- `tool_calls[20]` result 非空(`result: hello-probe-1790893221`,F2 修复实证)。
|
|
34
|
+
|
|
35
|
+
compaction 特定面(lines/fidelity/landmark/digest-residence)为代码级缺陷,单测夹具(2×compaction)覆盖;本短活体无 compaction 事件,与报告 §八「活体探测仅作证」一致。
|
|
36
|
+
|
|
37
|
+
## 四、判定
|
|
38
|
+
|
|
39
|
+
**通过**。N1–N6 + F1/F2 全部落地,单测全绿,0.2.0-rc.2 上第一人称活体逐面兑现。坐标不变式成立(transcript 单一坐标空间,越界显式)。prod 3080 未部署;发布走 §〇.5 门(第一人称 + user 确认),本轮不发包。
|
|
40
|
+
|
|
41
|
+
## 五、独立复核(2026-10-02,本轮报告发布后的第三方复验)
|
|
42
|
+
|
|
43
|
+
**缘由**:user 在报告落盘后要求独立确认 §一 声称的修复是否真在场,不复述原文。复核采用三重证据:
|
|
44
|
+
|
|
45
|
+
1. **部署物同一性**:4999 rig profile 内 `better-dsh/lib/url-schemes/index.js` 与构建产物 md5 一致(`ad5b4820c4ca97520ccc196d72b3aa3f`,286,916 B)→ 活体进程加载的确实是本次改动,而非旧构建。
|
|
46
|
+
2. **第一人称活体探测**:本会话即 4999 运行实例(`session-6c5f8e8e-0cd7-42a0-85da-3aec7256339f`,harness 0.2.0-rc.2),逐面实读。
|
|
47
|
+
3. **回归全量**:`tsc --noEmit` **0 错**;`vitest run` **648 passed / 1 skipped**(57 文件)——与 §三 数字一致。
|
|
48
|
+
|
|
49
|
+
### 5.1 逐项复核结果
|
|
50
|
+
|
|
51
|
+
| 项 | 结论 | 证据(活体 / 代码) |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| F1 | ✅ 已修 | 裸 `user_prompts`/`tool_calls`/`agent_responses` 返回索引面(`seq=<n>` + ≤100 字预览);长集合封顶 20 + `… +N more — use :raw / ?q= / [n\|seq]` 尾注;越界错误列集合名与条数,无空括号回显 |
|
|
54
|
+
| F2 | ✅ 已修 | `resultTextOf` 嵌套优先、平铺兜底(`ctx.ts` L128–137);活体 `tool_calls[99]` result 非空;in-progress 调用显式 `(no result captured)` |
|
|
55
|
+
| F5 | ✅ 已修 | 活体 `ctx://session/tool_calls?q=bash` 行过滤生效 |
|
|
56
|
+
| F7 | ✅ 已修 | 快照/manifest 内 `seq=` 与 `lines=` 双坐标并存;坐标不变式已入 spec(Requirement: Coordinate invariant) |
|
|
57
|
+
| F8 | ✅ 已修 | 活体 `ctx://session:path/asOf` → `{"seq":198,"line":1431}`;`:path/totals.tool_calls` → `13`(数字,非 JSON 包裹) |
|
|
58
|
+
| F9 | ✅ 已修 | 快照 `asOf:{seq,line}` 在场,且与后续窄读的前移一致(模型可自知陈旧) |
|
|
59
|
+
| F10 | ✅ 已修(episode 面) | `applyEpisodeLines` 越界追加 `[ctx:// note: episode span is transcript lines s-e]`(`ctx.ts` L291–318);单测 `N1/F10` 断言 |
|
|
60
|
+
| N1 | ✅ 已修 | 上述 F7/F10 证据;transcript 行索引为单一坐标源 |
|
|
61
|
+
| N2 | ✅ 已在代码 | latest episode 走 `digest resident at seq=<checkpointSeq> (transcript:<s>-<e>)` 指针块,older 出 digest + 指针块 |
|
|
62
|
+
| N3 | ✅ 已在代码 | `landmarkBlock`:user turns / failures / touched paths(含次数)/ prior checkpoints,全为行坐标并封顶 |
|
|
63
|
+
| N4 | ✅ 已在代码 | `fidelity=<user_turns>:<tool_calls>` 三处内联(manifest / 快照 `compacted[].fidelity` / episode 指针块) |
|
|
64
|
+
| N5 / N6 | ✅ 已修 | 同 F5/F8 与 F9 |
|
|
65
|
+
|
|
66
|
+
**N2–N4 的活体限度**:本会话 `compactions: 0`(快照实证),compaction 特定面无法活体触达;证据 = 代码 + 2×compaction 单测夹具,与 §三 口径一致,不构成缺口。附带观察:快照 `segments[].lines` 对 `live` 尾段为 `null`(开放区间无上界),compaction 段才带 `lines:{start,end}`——与「live 无 end」语义自洽。
|
|
67
|
+
|
|
68
|
+
### 5.2 未闭合项(本轮未声称修复,复核确认仍开)
|
|
69
|
+
|
|
70
|
+
- **F3 仍开**:`read` 的 `offset`/`limit` 对 `ctx://` 依旧静默忽略——活体 `read(ctx://session, limit:1)` 返回全量快照 JSON。
|
|
71
|
+
- **F4 仍开**:compaction label 仍为事件 seq,后续 compaction 重划 span 时仍会漂移;未改稳定键,亦未加文档点名(`compactionId` 为既有字段)。
|
|
72
|
+
- **F6 仍开**:episode `:raw` > 64 KiB 仍为 warn-don't-block(返回全文 + 注记,`ctx.ts` L528–536),无 spill-to-file / 硬护栏。
|
|
73
|
+
|
|
74
|
+
### 5.3 新发现 F11:spec 宽于实现(越界注记仅 episode 面兑现)
|
|
75
|
+
|
|
76
|
+
spec「Canonical and prepared content faces」写明*任何*越过 canonical 范围的 `:N-M` 都应回显显式边界注记;实测仅 **episode 面**成立:
|
|
77
|
+
|
|
78
|
+
- 活体 `ctx://session/transcript:1-3` → 正常返回该行窗内容;
|
|
79
|
+
- 活体 `ctx://session/transcript:9000-9010`、`:999999-999999` → **静默空串**(`applyLines` 无 extent 概念、无注记逻辑)。
|
|
80
|
+
|
|
81
|
+
即 §一 表中「越界返回显式边界注记(不再静默空/截断)」仅在 episode 窗口范围内为真,spec 文字面(全资源)未兑现。建议入批 F11:把 `applyLines` 升格为带 canonical extent 入参的同款注记,或把 spec 措辞收窄到 episode 面。
|
|
82
|
+
|
|
83
|
+
### 5.4 复核判定
|
|
84
|
+
|
|
85
|
+
**通过,无夸大**——§一/§三 声称的 N1–N6 + F1/F2 全部经独立证据兑现;§四 的部署与发布口径亦复核无误:4999 rig 已加载修复(md5 同一),prod 3080 仍为 **0.2.4-c**,修复未发布;发布仍走 §〇.5 门(第一人称实测 ✅ + user 确认)。遗留 F3/F4/F6 + 新增 F11 按 §〇 惯例攒批,不单烧版本。
|
|
86
|
+
|
|
87
|
+
## 六、F11 修复(2026-10-02,复核后同波闭合)
|
|
88
|
+
|
|
89
|
+
§五.3 的 F11 属实:本波 spec 文字面宽于实现(越界注记只在 episode 面)。因本改动**尚未发布**,不适用「攒批」——同波闭合:
|
|
90
|
+
|
|
91
|
+
- **修法**:ctx 侧 `applyLines` 升格为 extent-aware —— 越界窗口按 canonical 上界截断并追加 `[ctx:// note: canonical content ends at line <N>]`;`:N-` 开尾读**豁免**(刻意读到尾,非越界);manifest 的 line 窗口也改走同一函数(原先走共享 `applySelector`,无注记)。
|
|
92
|
+
- **未采纳**另一选项(把 spec 措辞收窄到仅 episode 面):不收窄,因为「不静默截断」是 N1/F10 的原意,应全资源成立。
|
|
93
|
+
- **验证**:单测新增 `F11`(越界 → 注记;`1-2` in-range 与 `1-` 开尾 → 无注记);全量 **649 passed / 1 skipped**(57 文件)+ `tsc` 0 错;**第一人称活体**(headless,0.2.0-rc.2)读 `ctx://session/transcript:9000-9010` → 输出含 `ctx:// note`(`F11=yes`)。4999 rig 已重启加载修复(`lib/url-schemes/index.js` md5 `48771cb6…` 与构建产物同一)。
|
|
94
|
+
- **仍开**:F3(read offset/limit 静默忽略)、F4(compaction label 漂移)、F6(episode `:raw` >64 KiB warn-not-block)——三者不在本波 N1–N6 范围,按 §〇 攒批。
|
|
95
|
+
|
|
96
|
+
## 七、第二轮复核记录(2026-10-02)与越界注记语义定论
|
|
97
|
+
|
|
98
|
+
第三方复核独立确认 F11 修复已在**运行进程**中生效(构建产物与 rig lib md5 同一 + 重启后取到新行为),并逐条活体复验:
|
|
99
|
+
|
|
100
|
+
| 探测 | 结果 |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `transcript:9000-9010` / `:999999-999999`(完全越界) | 仅注记(`canonical content ends at line <N>`),**不再静默空** ✅ |
|
|
103
|
+
| `transcript:1940-2000`(部分越界) | 上界截断 **+ 尾注** ✅ |
|
|
104
|
+
| `transcript:1-3`(范围内) | 正常内容,无注记 ✅ |
|
|
105
|
+
| `transcript:1945-` / `compactions:1-`(开尾) | 无注记(豁免)✅ |
|
|
106
|
+
| `compactions:2-`(起点越界) | 仅注记 ✅ |
|
|
107
|
+
| `compactions:1-3` / `compactions:9000-9010`(manifest 新路径) | 文本+注记 / 仅注记,上界正确 ✅ |
|
|
108
|
+
|
|
109
|
+
回归扫:F1/F2/F5/F7/F8/F9 全部仍绿;`tsc` 0 错、`vitest` 649 passed / 1 skipped(与 §六 一致)。
|
|
110
|
+
|
|
111
|
+
### 7.1 语义定论:上界越界**保留**注记(不软化)
|
|
112
|
+
|
|
113
|
+
复核提出一档可议行为:**上界越界也注记**,使 `:N-M`(M 贴/略过上界)从「纯值」变为「值 + 注记」;其测试后果即既有断言 `injections:4-5` 改为 `injections:4-`。
|
|
114
|
+
|
|
115
|
+
**定论:保留现语义,不采纳「`a <= total < b` 时不注记」的软化方案。** 依据 = F10 原意本身:
|
|
116
|
+
|
|
117
|
+
- F10 的病症是「越界与 span 内空行**不可区分**、上界落在何处**无从得知**」。若上界越界不注记,`:1940-2000`(1947 行)静默回 1940–1947,模型无法判断 1948–2000 是「空行」还是「不存在」——**正是 F10 要修的歧义**;软化 = 回退该修复。
|
|
118
|
+
- 两种「读到尾」的正规形已豁免/覆盖:**开尾 `:N-`** 无注记(刻意读到尾);**上界恰为 total**(`:4-4`)无注记。故越界注记只在「模型对内容长度有错误假设」时出现,而该注记正是纠正该假设的信息。
|
|
119
|
+
- 代价可接受:一行元信息;远小于「误以为已读全」的风险。若未来真会话统计证明其为高频噪音,另立 finding 重议;本轮不改。
|
|
120
|
+
- 规格已同步补 scenario「Over-read notes, open tail does not」(`docs/specs/ctx/spec.md`)。
|
|
121
|
+
|
|
122
|
+
### 7.2 仍开(复核独立确认,非本波 N1–N6 范围)
|
|
123
|
+
|
|
124
|
+
F3(`read` offset/limit 静默忽略)、F4(compaction label 漂移,无稳定键)、F6(episode `:raw` >64 KiB warn-not-block)——按 §〇 攒批。发布仍待 user 明确放行。
|
|
125
|
+
|
|
126
|
+
## 八、第三轮复核:spec 措辞收窄 + 「spec > impl」模式记录
|
|
127
|
+
|
|
128
|
+
第三轮复核(**无代码改动轮**,唯一 commit `6e3db37` = §七 + 一条 spec scenario)确认 §七 属实,并指出:**上轮新加的 spec scenario 措辞仍比实现宽**。
|
|
129
|
+
|
|
130
|
+
- **事实**:`applyLines` 的开尾豁免带前置守卫 —— `b === Infinity ? total` 之后仍有 `if (a > total) { noted = true }`([ctx.ts:250](/home/u1/workspaces/dashr/better-dsh/src/url-schemes/handlers/ctx.ts#L250))。故 `compactions:1-`(起点在界内)无注记,而 `compactions:2-`(canonical 仅 1 行、**起点已越界**)返回**仅注记**。我上轮写的 THEN 是无条件句,按字面读 `:2-` 会算违例。
|
|
131
|
+
- **定论:实现是对的**(起点越界时无内容可回,必须出声),错的是 spec 措辞。已改 `docs/specs/ctx/spec.md`:开尾 THEN 补限定「provided the window's start is within the extent」;新增 WHEN/THEN 覆盖「起点越界的开尾 → 仅注记」;新增 scenario「Upper bound exactly at the extent is not an over-read」(`:1-1` 恰为 total → 无注记),两个豁免均成明文。
|
|
132
|
+
- **模式记录(同类再现,继 F11 之后;不计序号,避免与复核口径打架)**:spec 散文倾向把行为写得比实现的**守卫条件**宽 —— F11 属**行为缺陷**(spec 全资源 vs impl 仅 episode 面,已修码),本处属**措辞缺陷**(无条件开尾 vs 起点守卫,已改 spec)。教训:写/改 spec 的 WHEN/THEN 时逐条对照实现的 guard(`b < 1 || a > total`、`bRaw !== Infinity && b > total`、`bRaw === Infinity`),把守卫写成限定词;新增 scenario 按此自查。
|
|
133
|
+
- **仍开**:F3 / F4 / F6(同 §七.2)。
|
|
134
|
+
|
|
135
|
+
### 8.1 部署与发布口径(不变)
|
|
136
|
+
|
|
137
|
+
本轮**无代码改动**:`git diff 44a88f5..HEAD -- better-dsh/src better-dsh/lib better-dsh/test` 为空;4999 rig 内 lib 仍 `48771cb6…`(未重建、未重启,仍是同一运行进程)。prod 3080 仍 `0.2.4-c`;修复未发布,发布待 user 明确放行。
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# v0.2.0-rc.2 对齐轮实测报告(2026-10-02)
|
|
2
|
+
|
|
3
|
+
- **对象**:better-dsh 对齐 upstream dsh **0.2.0-rc.2**(npm `latest`;upstream tag `dsh-v0.2.0-rc.2`)
|
|
4
|
+
- **基线**:better-dsh 0.2.4-d(当前分支 `align/v0.2.0-rc.2`,从 `align/v0.1.7-rc.1` 切出)
|
|
5
|
+
- **证法**:源码级 4999 rig(`upstream/deepseek-harness` 原位重检出)+ better-dsh 全量 typecheck/test + 第一人称活体(headless 真实 session + headless-Chrome 驱动 web UI)
|
|
6
|
+
|
|
7
|
+
## 一、环境迁移
|
|
8
|
+
|
|
9
|
+
1. `upstream/deepseek-harness` 原位重检出 `dsh-v0.2.0-rc.2`(tags 已 fetch;本地 0.1.7-rc.1 patch 先存 `.scratch/upstream-local-patches-0.1.7-rc.1.diff`)。
|
|
10
|
+
2. 三处本地 patch 在 0.2.0 下**仍全部必要**,逐条重放(均标注 `LOCAL PATCH` 注释便于下次 tag 切换):
|
|
11
|
+
- `packages/client/tsdown.client.ts` `resolveRepositoryRoot()`(0.2.0 仍 `new URL('../..', import.meta.url)`);
|
|
12
|
+
- `pnpm-workspace.yaml` `storeDir`/`verifyDepsBeforeRun:false`/`allowBuilds`(zeromq/ssh2/cpu-features;0.2.0 仍 strictDepBuilds);
|
|
13
|
+
- `apps/web` react→preact 三件套(0.2.0 仍真 React,`@vitejs/plugin-react`);`preact` devDep + 根 `unrun`/`vite` devDep。
|
|
14
|
+
3. `vendor/{AGENTS,CLAUDE,README}.md` 三文件移除(0.2.0 版存 `.scratch/vendor-docs/*-0.2.0-rc.2.md`)。
|
|
15
|
+
4. `pnpm install`(339 workspace 项目,21s,供应链门 1685 条目过)→ `pnpm run build`(347 client artifacts)全绿。
|
|
16
|
+
|
|
17
|
+
## 二、对齐结果 — 结论:zero better-dsh 源码改动
|
|
18
|
+
|
|
19
|
+
| 检查 | 结果 |
|
|
20
|
+
|---|---|
|
|
21
|
+
| better-dsh `npx tsc --noEmit`(farm relink 至 0.2.0-rc.2,329 包) | **0 错误** |
|
|
22
|
+
| better-dsh `npx vitest run` | **641 passed / 1 skipped**(57 文件)全绿 |
|
|
23
|
+
|
|
24
|
+
即用户判断成立:0.2.0 相对 0.1.7-rc.2 的 448 个 commit / 1014 个文件变更,**未触及 better-dsh 消费的 harness API 面**(消费 24 包;`dsh-tools`/`dsh-agent`/`dsh-settings`/`dsh-client-ui-settings` 等类型面兼容)。上游 0.2.0 亦**未发布 upgrade guide**(09-28 才引入该机制,仅回填 v0.1.7-rc.2)。
|
|
25
|
+
|
|
26
|
+
## 三、回归门(第一人称,4999 rig,0.2.0-rc.2)
|
|
27
|
+
|
|
28
|
+
0.1.7 轮的两处**静默**失败面(settings 行消失 / failover 存不进)是重点复检对象:
|
|
29
|
+
|
|
30
|
+
- **boot graph**:`"id":"better-dsh"` + `plugins/??better-dsh/client.js&rev=…` 200,字节与构建产物一致(仅服务端追加 `;`+sourceMappingURL)。
|
|
31
|
+
- **Settings/General 两行**(headless-Chrome 驱动真实 UI):`Model failover`(两个 select)+ `Auto-compact threshold 90 %` 均在渲染;版本行显示 `0.2.0-rc.2`。
|
|
32
|
+
- **failover save**:UI 改 `fallback2` → 落 `profiles/web/cordis.patch.yml` 用户层,无 toast 无 `settings/rejected`(写路径 = 0.1.7 崩点)。
|
|
33
|
+
- **web-password 门**:默认 `admin` 登录 → 303 → authenticated index(better-dsh 0.2.4-d 的门在 0.2.0 上照常)。
|
|
34
|
+
- **活体 session(headless)**:`ctx://session` → 真实 session id;`bash` → `gate-ok`;`eval` → `2`。
|
|
35
|
+
|
|
36
|
+
## 四、判定
|
|
37
|
+
|
|
38
|
+
**通过**。0.2.0-rc.2 对齐为纯「重检出 + patch 重放 + 重建」,better-dsh 零改动;回归门全绿。prod 3080(仍 0.1.7-rc.2 + better-dsh 0.2.4-c)本轮未动。下一步 Change B(ctx:// 导航化 N1–N6)在此已验基线上开发。
|