dsh-log-contract 0.3.0 → 0.3.2

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.
File without changes
package/lib/checks.js CHANGED
@@ -432,8 +432,8 @@ export function wireViolations(events) {
432
432
  } else if (op && isReplaceOp(op)) {
433
433
  const s = nodes.indexOf(op.start);
434
434
  const e = nodes.indexOf(op.end);
435
- if (s !== -1 && e !== -1 && s <= e) nodes.splice(s, e - s + 1);
436
- nodes.push(event.seq);
435
+ if (s !== -1 && e !== -1 && s <= e) nodes.splice(s, e - s + 1, event.seq);
436
+ else nodes.push(event.seq);
437
437
  }
438
438
  }
439
439
  // 展开 wire 流
package/lib/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * 日志契约守护(DSH session log contract guard)。
5
5
  * 公开 API:离线体检 + 写前校验 + 修复 + 契约目录。
6
6
  */
7
- export { loadSessionLog } from './log-reader.js';
7
+ export { loadSessionLog, tailSeq } from './log-reader.js';
8
8
  export { validateSessionLog } from './validate.js';
9
9
  export { createPreWriter, preWriterFromLog } from './prewrite.js';
10
10
  export { repairSession, strictScanText, removeMarkersText, dropFailedTurnsText, trimLastMessagesText, compactLastMessagesText, rebuildZstdText } from './repair.js';
package/lib/log-reader.js CHANGED
@@ -92,6 +92,49 @@ export function decompressZstd(buf) {
92
92
  return Buffer.concat(parts);
93
93
  }
94
94
 
95
+ /**
96
+ * 读取文件尾部最后一条事件的 seq(看门狗 R1 用,只解最后一帧,O(帧数) 内)。
97
+ *
98
+ * 语义:zstd 多帧文件取最后一个**完整**帧解压(撕裂尾帧跳过——可能正在写入),
99
+ * 从帧内末尾向前找第一条合法 JSON 行,用 `decodeStorageRecord` 展开取末事件 seq
100
+ * (chunk 行展开后末成员即该 run 的最新 seq)。明文文件直接扫末尾。
101
+ *
102
+ * @param {string} path 日志文件路径
103
+ * @returns {number|null} 尾部 seq;读取失败/无可解析行返回 null(调用方降级不检查)。
104
+ */
105
+ export function tailSeq(path) {
106
+ let buf;
107
+ try {
108
+ buf = fs.readFileSync(path);
109
+ } catch {
110
+ return null;
111
+ }
112
+ const isZstd = buf.length >= 4 && buf.readUInt32LE(0) === ZSTD_MAGIC;
113
+ let plain;
114
+ if (isZstd) {
115
+ const { frames } = scanZstdFrames(buf);
116
+ if (frames.length === 0) return null;
117
+ const [s, e] = frames[frames.length - 1];
118
+ try {
119
+ plain = zstdDecompressSync(buf.subarray(s, e));
120
+ } catch {
121
+ return null;
122
+ }
123
+ } else {
124
+ plain = buf;
125
+ }
126
+ const lines = plain.toString('utf8').split('\n');
127
+ for (let i = lines.length - 1; i >= 0; i--) {
128
+ const line = lines[i];
129
+ if (line.trim().length === 0) continue; // 帧边界产物(空行)跳过
130
+ try {
131
+ const decoded = decodeStorageRecord(JSON.parse(line));
132
+ if (decoded.length > 0) return decoded[decoded.length - 1].seq;
133
+ } catch { /* 损坏行/不可解析:继续向前找 */ }
134
+ }
135
+ return null;
136
+ }
137
+
95
138
  /**
96
139
  * 读取并解码一个会话日志文件(.jsonl / .jsonl.zstd / 任意带 zstd 魔数的文件)。
97
140
  *
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "dsh-log-contract",
3
3
  "description": "日志契约守护 — DSH session log contract guard: offline health check (CLI) + pre-write validation for DeepSeek Harness session logs",
4
- "version": "0.3.0",
5
- "packageManager": "pnpm@11.7.0",
4
+ "version": "0.3.2",
6
5
  "type": "module",
7
6
  "main": "lib/index.js",
8
7
  "bin": {
@@ -27,11 +26,6 @@
27
26
  "README.md",
28
27
  "LICENSE"
29
28
  ],
30
- "scripts": {
31
- "check": "node scripts/check-syntax.mjs",
32
- "test": "vitest run",
33
- "prepublishOnly": "pnpm check && pnpm test"
34
- },
35
29
  "keywords": [
36
30
  "dsh",
37
31
  "deepseek-harness",
@@ -64,5 +58,9 @@
64
58
  "@deepseek-ai/dsh-session": "0.1.0-rc.7",
65
59
  "esbuild": "0.28.2",
66
60
  "vitest": "4.1.11"
61
+ },
62
+ "scripts": {
63
+ "check": "node scripts/check-syntax.mjs",
64
+ "test": "vitest run"
67
65
  }
68
- }
66
+ }