dsh-fast-mode 1.5.30 → 1.5.31
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/CHANGELOG.md +7 -0
- package/bench/README.md +2 -0
- package/bench/turns.py +22 -3
- package/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.31(`turns.py` 顺手审另一条提醒:压缩后重述规则的那条,会不会无理由地多出来)
|
|
4
|
+
|
|
5
|
+
- 插件只主动发两条提醒:入场步的「少写散文」(每轮恰好一次)和压缩后的「规则重申」(每次压缩后一次,因为规则可能被裁掉)。`bench/turns.py` 原来只审第一条,第二条只当噪音忽略——如果它的标志位泄漏,就会在每个合格轮里白送一段规则文本。
|
|
6
|
+
- 新增读数:有多少轮带过重述、其中有多少轮的重述条数**超过**该轮的压缩次数 + 1(+1 是允许的:压缩发生在上一轮末尾时,重申落在下一轮第一步)。近 72 小时真实会话:**624 轮**带重述,**0 轮**没有压缩可指。
|
|
7
|
+
- 同时把「首次提醒落在第几步」的直方图、`--explain-doubles`(列出每个重复提醒的轮、步号、seq 与压缩点)固化进脚本,方便下次换版本时重跑对照。
|
|
8
|
+
- 只动 `bench/turns.py` 与文档,`src/` 无改动。
|
|
9
|
+
|
|
3
10
|
## 1.5.30(把 1.5.28 的修复拿真实流量做 A/B:同一份会话,同一串事件,两个版本)
|
|
4
11
|
|
|
5
12
|
- **新增 `bench/replay.mjs`**:把一份留存会话的事件流原样喂给插件自己的钩子(`session/event` + `agent/pre-step`),数出「这一版会发几条提醒、落在第几步」。会话 id 是合成的,`metrics`/`benchmarkFile` 关掉,不碰 `~/.dsh` 状态。
|
package/bench/README.md
CHANGED
|
@@ -146,6 +146,8 @@ node bench/replay.mjs <transcript> --json
|
|
|
146
146
|
node bench/replay.mjs <transcript> --simulate-reentry # 每次压缩后按当前 turn 号重入
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
`turns.py` 同时审两条提醒:入场步的「少写散文」(每轮恰好一次)与压缩后的「规则重申」(每次压缩后一次)。后者允许比该轮压缩次数多一条(压缩发生在上一轮末尾时重申落在下一轮第一步),超过就是标志位泄漏;近 72 小时真实会话是 624 轮带重申、0 轮无压缩可指。`--explain-doubles` 会逐条列出重复提醒所在的轮、步号、seq 与压缩点。
|
|
150
|
+
|
|
149
151
|
`--simulate-reentry` 补的是会话记录里**不存在**的那条事件:宿主压缩后重入同一轮时用同一个 turn 号再发一次 `turn/start`,而这次重入不落盘。加上它以后,1.5.27 与 1.5.28 的差别就能在同一份数据上量出来(1529 个合格轮:940 → 0)。
|
|
150
152
|
|
|
151
153
|
### 提醒是否每轮重新上膛、且每轮只发一次
|
package/bench/turns.py
CHANGED
|
@@ -33,6 +33,11 @@ import time
|
|
|
33
33
|
|
|
34
34
|
SESS = os.path.expanduser('~/.dsh/sessions')
|
|
35
35
|
NEEDLE = 'this turn is long enough that prose'
|
|
36
|
+
# The other notice the plugin can deliver, the one that restates the rules after a
|
|
37
|
+
# compaction. It is *supposed* to repeat, once per compaction whose rules were
|
|
38
|
+
# evicted; the audit question is only whether it ever fires with no compaction to
|
|
39
|
+
# point at, which would mean a stale flag.
|
|
40
|
+
REASSERT = 'the context was just compacted'
|
|
36
41
|
# A delivered directive is a message part; the model quoting it back inside its
|
|
37
42
|
# own prose is an echo, so assistant-authored text never counts as delivery.
|
|
38
43
|
PLUGIN_ROLES = {'user/message', 'agent/inbox/spliced', 'system/message'}
|
|
@@ -70,10 +75,11 @@ def scan(path):
|
|
|
70
75
|
started = 0
|
|
71
76
|
turns = []
|
|
72
77
|
cur = {'steps': 0, 'reminders': 0, 'reminderSeqs': [], 'compactions': [],
|
|
73
|
-
'reminderSteps': []}
|
|
78
|
+
'reminderSteps': [], 'reasserts': 0}
|
|
74
79
|
for line in p.stdout.decode('utf-8', 'replace').splitlines():
|
|
75
80
|
if ('turn/start' not in line and 'step/start' not in line
|
|
76
|
-
and 'Auto schedule' not in line and 'compaction/start' not in line
|
|
81
|
+
and 'Auto schedule' not in line and 'compaction/start' not in line
|
|
82
|
+
and 'context was just compacted' not in line):
|
|
77
83
|
continue
|
|
78
84
|
try:
|
|
79
85
|
o = json.loads(line)
|
|
@@ -87,11 +93,13 @@ def scan(path):
|
|
|
87
93
|
if cur['steps'] or cur['reminders']:
|
|
88
94
|
turns.append(cur)
|
|
89
95
|
cur = {'steps': 0, 'reminders': 0, 'reminderSeqs': [], 'compactions': [],
|
|
90
|
-
|
|
96
|
+
'reminderSteps': [], 'reasserts': 0}
|
|
91
97
|
elif kind == 'step/start':
|
|
92
98
|
cur['steps'] += 1
|
|
93
99
|
elif kind == 'compaction/start':
|
|
94
100
|
cur['compactions'].append(o.get('seq'))
|
|
101
|
+
elif kind in PLUGIN_ROLES and REASSERT in text_of(data):
|
|
102
|
+
cur['reasserts'] += 1
|
|
95
103
|
elif kind in PLUGIN_ROLES and NEEDLE in text_of(data):
|
|
96
104
|
cur['reminders'] += 1
|
|
97
105
|
cur['reminderSeqs'].append(o.get('seq'))
|
|
@@ -121,6 +129,7 @@ def main():
|
|
|
121
129
|
later_qualifying = later_reminded = 0
|
|
122
130
|
per_session_turns = collections.Counter()
|
|
123
131
|
entry_steps = collections.Counter()
|
|
132
|
+
reasserted = reassert_orphan = 0
|
|
124
133
|
offenders = []
|
|
125
134
|
cutoff = (time.time() - a.since_hours * 3600) * 1000 if a.since_hours else 0
|
|
126
135
|
skipped_old = 0
|
|
@@ -151,6 +160,12 @@ def main():
|
|
|
151
160
|
later_reminded += 1 if t['reminders'] else 0
|
|
152
161
|
if t['reminders']:
|
|
153
162
|
entry_steps[t['reminderSteps'][0]] += 1
|
|
163
|
+
if t['reasserts']:
|
|
164
|
+
reasserted += 1
|
|
165
|
+
# One reassert belongs to a compaction from the previous turn: the
|
|
166
|
+
# flag is set, the turn ends, the next step of the next turn speaks.
|
|
167
|
+
if t['reasserts'] > len(t['compactions']) + 1:
|
|
168
|
+
reassert_orphan += 1
|
|
154
169
|
if t['reminders'] > 1:
|
|
155
170
|
doubled += 1
|
|
156
171
|
seqs = t['reminderSeqs']
|
|
@@ -178,6 +193,8 @@ def main():
|
|
|
178
193
|
'doubled': doubled,
|
|
179
194
|
'doubled_with_compaction_between': doubled_compacted,
|
|
180
195
|
'entry_steps': dict(sorted(entry_steps.items())),
|
|
196
|
+
'turns_with_compaction_reassert': reasserted,
|
|
197
|
+
'reasserts_without_compaction': reassert_orphan,
|
|
181
198
|
'later_qualifying_turns': later_qualifying,
|
|
182
199
|
'later_reminded': later_reminded,
|
|
183
200
|
'skipped_old': skipped_old,
|
|
@@ -195,6 +212,8 @@ def main():
|
|
|
195
212
|
f"(with a compaction between: {doubled_compacted})")
|
|
196
213
|
if entry_steps:
|
|
197
214
|
print(f"first reminder landed at step: {dict(sorted(entry_steps.items()))}")
|
|
215
|
+
print(f"compaction re-assert: {reasserted} turns carried one, "
|
|
216
|
+
f"{reassert_orphan} had more of them than compactions to point at")
|
|
198
217
|
if a.explain_doubles and offenders:
|
|
199
218
|
print('doubled turns:')
|
|
200
219
|
for o in offenders[:20]:
|
package/index.js
CHANGED
|
@@ -97,7 +97,7 @@ const TAG = '[fast-mode]'
|
|
|
97
97
|
* Shipped identity of this build. Traced into the debug log so a stale install is
|
|
98
98
|
* visible at a glance, and pinned by a test against `package.json`.
|
|
99
99
|
*/
|
|
100
|
-
export const VERSION = '1.5.
|
|
100
|
+
export const VERSION = '1.5.31'
|
|
101
101
|
const GLOBAL_AGENT = '__global__'
|
|
102
102
|
|
|
103
103
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-fast-mode",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.31",
|
|
4
4
|
"description": "DeepSeek Harness fast mode: same thinking effort, fewer round trips. An adaptive parallel tool fan-out, output discipline that never trims the answer, and a cancellable stall guard. Never changes reasoning effort, the model, or the request body. Provider-agnostic, one dependency (@deepseek-ai/schemastery).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|