dsh-log-contract 0.3.14 → 0.3.15

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/README.md CHANGED
@@ -15,8 +15,7 @@ offline health check + pre-write validation. The business layer's **doctor**.
15
15
 
16
16
  </div>
17
17
 
18
- Formerly `log-contract-validator` (candidate #2); named **`dsh-log-contract`**
19
- per the OfferKuai three-piece plan.
18
+ Formerly `log-contract-validator`; now **`dsh-log-contract`**.
20
19
 
21
20
  A fuse for DSH session logs (`*.jsonl` / `*.jsonl.zstd`): format drift that humans
22
21
  cannot see but parsers crash on is caught and reported here. It does **not** judge
@@ -289,17 +288,16 @@ if (!verdict.ok) {
289
288
  ## Tests
290
289
 
291
290
  ```bash
292
- pnpm check && pnpm test # syntax check + 79 unit tests (incl. incident regressions)
291
+ pnpm check && pnpm test # syntax check + contract-doc drift gate + all unit tests
293
292
  ```
294
293
 
295
294
  - **Synthetic fixtures** (in-repo): legal session / seq gap / empty sourceEventSeqs
296
295
  / turn-null append / unknown type / bad chunk row / torn tail frame / unknown
297
296
  marker prefix / self-shadowing etc.
298
- - **Real fossils** (not in-repo, contain user data): run locally
299
297
 
300
- ```bash
301
- node scripts/check-local-fossils.mjs # scans ../ for backup-session-*.jsonl.zstd
302
- ```
298
+ > **Scope of the published package**: it contains the runtime code and documentation only.
299
+ > Local maintainer tooling is not part of the public repository, so `pnpm check` and `pnpm test`
300
+ > work from a clean clone.
303
301
 
304
302
  Known truth table (updated 2026-08-31 — after 0.3.5 added I1, `spliced-orphan`
305
303
  now FAILs; the old PASS row was stale):
@@ -336,7 +334,11 @@ MIT © OfferKuai Team
336
334
 
337
335
  ---
338
336
 
339
- ## ⚠️ Upgrading to 0.3.14 — behaviour changes you must know (0.3.12 → 0.3.14)
337
+ ## ⚠️ Upgrading to 0.3.15 — behaviour changes you must know (0.3.12 → 0.3.15)
338
+
339
+ > **0.3.15 itself changes no behaviour.** It removes two internal identifiers that had leaked into the
340
+ > 0.3.14 published artifact (a README naming note and one source comment) and widens the pre-publish
341
+ > leak gate vocabulary. Everything below applies unchanged when going from 0.3.12 to 0.3.15.
340
342
 
341
343
  **1. New exit codes `3` / `4` — a defect fix that is also a breaking change.**
342
344
  - `3` = **not assessable on this host**: the file's `header.version` is higher than the host supports
package/README.zh.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
  > DSH(DeepSeek Harness)会话日志的**结构契约保险丝**:离线体检 + 写前校验。
21
- > 原名 `log-contract-validator`(候选二号),按 Offer快 三件套规划定名 **`dsh-log-contract`**。
21
+ > 本包名 **`dsh-log-contract`**;早期工作名 `log-contract-validator`。
22
22
 
23
23
  给 DSH 会话日志(`*.jsonl` / `*.jsonl.zstd`)装一条保险丝:人眼看不出、程序解析会崩的日志格式漂移,在它这里被拦下并告警。它不判断日志**内容**对不对,只守护日志**结构**是否破坏了下游消费者(Harness 读路径、客户端引擎、插件 marker 语义)的预期。
24
24
 
@@ -257,15 +257,13 @@ if (!verdict.ok) {
257
257
  ## 测试
258
258
 
259
259
  ```bash
260
- pnpm check && pnpm test # 语法检查 + 79 个单测(含事故回归用例)
260
+ pnpm check && pnpm test # 语法检查 + 契约文档漂移闸 + 全部单测(含事故回归用例)
261
261
  ```
262
262
 
263
263
  - **合成夹具**(入库):合法会话 / seq 缺口 / 空 sourceEventSeqs / turn=null append / 未知 type / 坏 chunk 行 / 撕裂尾帧 / 未知 marker 前缀 / 自指 shadowed 等。
264
- - **真实化石**(不入库,含用户隐私):本地跑
265
264
 
266
- ```bash
267
- node scripts/check-local-fossils.mjs # 扫描 ../ backup-session-*.jsonl.zstd
268
- ```
265
+ > **发布包范围**:只含运行时代码与文档。维护者本地工具不在公开仓内,
266
+ > 因此 `pnpm check` / `pnpm test` 在干净的克隆里即可通过。
269
267
 
270
268
  已知真值表(2026-08-31 实测更新——0.3.5 加 I1 后,`spliced-orphan` 已可报错,旧表 PASS 过时):
271
269
 
@@ -297,7 +295,11 @@ MIT © OfferKuai Team
297
295
 
298
296
  ---
299
297
 
300
- ## ⚠️ 升级到 0.3.14 —— 必须知道的行为变更(0.3.12 → 0.3.14
298
+ ## ⚠️ 升级到 0.3.15 —— 必须知道的行为变更(0.3.12 → 0.3.15
299
+
300
+ > **0.3.15 本身不含行为变更。** 它只做两件事:清掉 0.3.14 已发布产物里的两处内部标识
301
+ > (README 的定名说明 + 一处源码注释),并补齐发布前泄漏闸门的词表。
302
+ > 从 0.3.12 升到 0.3.15 时,下面各条与原来完全一致。
301
303
 
302
304
  **1. 新增退出码 `3` / `4`:本质是缺陷修复,形式上也是破坏性变更。**
303
305
  - `3` = **不可在本宿主评估**:被检文件的 `header.version` 高于当前宿主支持的上限
@@ -106,7 +106,7 @@ const USAGE = `dsh-log-contract —— 日志契约守护(DSH session log cont
106
106
 
107
107
  dsh-log-contract extract <session-log> --pattern <regex> [--out DIR] [--min-size N] [--json]
108
108
  考古提取:按命令正则导出工具输出(只读)。--out 写到目录(保留原始文本),
109
- 否则打印前 3 条摘要。--min-size 过滤小输出(默认 50,任务书口径)。
109
+ 否则打印前 3 条摘要。--min-size 过滤小输出(默认 50)。
110
110
 
111
111
  dsh-log-contract audit-report <session-log> [--json]
112
112
  考古审计报告:调用数 / 配对率 / 孤儿数 / 命令分布。
@@ -407,7 +407,7 @@ function cmdFix(args) {
407
407
  const trimBudget = budgetIdx >= 0 && args[budgetIdx + 1] ? Number(args[budgetIdx + 1]) : undefined;
408
408
  const compactIdx = args.indexOf('--compact-last');
409
409
  const compactLast = compactIdx >= 0 && args[compactIdx + 1] ? Number(args[compactIdx + 1]) : undefined;
410
- // L4 新原语(2026-08-30 任务书 §L4 收编 tools/)
410
+ // L4 新原语(2026-08-30 收编外部验证工具)
411
411
  const tailIdx = args.indexOf('--tail-renumber');
412
412
  const tailRenumberDelta = tailIdx >= 0 && args[tailIdx + 1] ? Number(args[tailIdx + 1]) : undefined;
413
413
  const neutralizeOrphan = args.includes('--neutralize-orphan');
package/docs/CONTRACTS.md CHANGED
@@ -3,6 +3,7 @@
3
3
  > **自动生成**(2026-09-06 起):本文件由 `node scripts/gen-contracts-doc.mjs`
4
4
  > 从 `lib/contracts.js` 的 `CONTRACT_RULES` 注册表生成——**勿手改**,规则只增不减,
5
5
  > 新增规则后跑一次生成即同步(此前手工维护滞后 15+ 条,外部审计指出)。
6
+ > **漂移闸**:`pnpm check` 会跑 `--check` 逐字节比对,改了注册表没重生成 ⇒ 直接红。
6
7
  >
7
8
  > DSH 会话日志契约的**可执行 spec**。每条规则在 `lib/checks.js`(逐事件判定)
8
9
  > 与 `lib/prewrite.js`(写前校验)中有对应实现;离线体检(`lib/validate.js`)
@@ -231,7 +232,7 @@
231
232
  ### E7 — ignorable 未知 type 合法性(带被忽略标记的未知事件须有消费者)
232
233
 
233
234
  - **层级**: persistence | **严重度**: warning
234
- - **出处**: 反向挑刺 2026-09-09 T2(E3 ignorable 无合法性校验 = 后门)
235
+ - **出处**: 对抗性复查 2026-09-09 T2(E3 ignorable 无合法性校验 = 后门)
235
236
  - **契约**: 未知 type + ignorable:true 被读路径接纳但无人消费 = 静默垃圾。排除已知消费者白名单(retrace/marker、retrace/goal-marker、message-editor/ 前缀等 retrace 客户端消费的插件 marker)后,其余 ignorable 未知事件报 warning。
236
237
 
237
238
  ### E8 — 事件信封键白名单(多余键:seed/restore 路径会拒)
@@ -255,19 +256,19 @@
255
256
  ### Z3 — 空会话文件(有 header 无事件)显式报出
256
257
 
257
258
  - **层级**: framing | **严重度**: warning
258
- - **出处**: 反向挑刺 2026-09-09 T3(36 条规则全来自有内容事故,空态无覆盖)
259
+ - **出处**: 对抗性复查 2026-09-09 T3(36 条规则全来自有内容事故,空态无覆盖)
259
260
  - **契约**: 有 header 但零事件 = 异常空会话(新建即空或写入未落盘)。空态不在任何有内容规则的覆盖下,显式 warning 供人判断。
260
261
 
261
262
  ### P3 — tool/call ↔ tool/result 配对完整性(考古 B1)
262
263
 
263
264
  - **层级**: plugin | **严重度**: warning
264
- - **出处**: dsh-会话日志考古-插件任务与方法.md §2/§4.2(callId 配对,不可用"上一个 call"推断)
265
+ - **出处**: 考古方法 §2/§4.2(callId 配对,不可用"上一个 call"推断)
265
266
  - **契约**: 每个 tool/call 的 data.callId 必须能在 tool/result 的 data.message.source.callId 中找到配对;孤儿 call(无 result)告警——中断/失败轮次可能产生孤儿(合法但要审计),考古提取将缺该输出。
266
267
 
267
268
  ### P4 — tool/result 输出结构可解析(考古 B2)
268
269
 
269
270
  - **层级**: plugin | **严重度**: warning
270
- - **出处**: dsh-会话日志考古-插件任务与方法.md §2/§4.2(content 递归 text 结构)
271
+ - **出处**: 考古方法 §2/§4.2(content 递归 text 结构)
271
272
  - **契约**: tool/result 的 data.message.content 必须可递归解析(list[dict{type:text,text}] 或等价);不可解析片段 = 考古提取将漏数据。空 content(失败/无输出)合法。
272
273
 
273
274
  ### M1 — turn/step 为 null 的 assistant/message 只能 replace,不能 append
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * dsh-log-contract · lib/archaeology.js
3
3
  *
4
- * 会话日志考古(任务书 dsh-会话日志考古-插件任务与方法.md)——两插件共享:
4
+ * 会话日志考古 —— 两插件共享:
5
5
  * retrace 的考古界面/导出(A1-A4)与 log-contract 的 extract/audit-report
6
6
  * (B3/B4)都消费这里的纯函数。**只读不写**(纪律 §8.1)。
7
7
  *
@@ -100,7 +100,7 @@ export function indexToolCalls(events) {
100
100
  *
101
101
  * @param events - 会话事件数组。
102
102
  * @param pattern - 命令正则(字符串或 RegExp;字符串按子串匹配,空则全量)。
103
- * @param opts.minSize - 输出最小字节数过滤(默认 0;任务书用 50 过滤噪声)。
103
+ * @param opts.minSize - 输出最小字节数过滤(默认 0;CLI 默认用 50 过滤噪声)。
104
104
  * @returns {{ pairs: Array<{ callId, command, text, size }>, matched: number, total: number }}
105
105
  */
106
106
  export function extractToolOutputs(events, pattern = '', { minSize = 0 } = {}) {
package/lib/checks.js CHANGED
@@ -480,7 +480,7 @@ export function turnEndReasonViolations(events) {
480
480
  }
481
481
 
482
482
  /**
483
- * E7 —— ignorable 未知 type 合法性(2026-09-09 反向挑刺 T2 增量)。
483
+ * E7 —— ignorable 未知 type 合法性(2026-09-09 T2 增量)。
484
484
  *
485
485
  * 盲区:E3 对"未知 type + ignorable:true"直接放行(容忍更新版本 harness 写入),
486
486
  * 但 ignorable 标记无合法性校验 = 后门——被读路径接纳却无人消费的未知事件 =
@@ -509,7 +509,7 @@ export function ignorableTypeViolations(events, version) {
509
509
  }
510
510
 
511
511
  /**
512
- * P3 —— tool/call ↔ tool/result 配对完整性(考古任务书 B1)。
512
+ * P3 —— tool/call ↔ tool/result 配对完整性(考古 B1)。
513
513
  * 每个 tool/call 的 `data.callId` 必须能在 tool/result 的
514
514
  * `data.message.source.callId` 中找到配对;孤儿 call(无 result)告警——
515
515
  * 中断/失败轮次可能产生孤儿(合法但要审计)。warning 级:不破坏日志。
@@ -517,7 +517,7 @@ export function ignorableTypeViolations(events, version) {
517
517
  export function toolPairingViolations(events) {
518
518
  const out = [];
519
519
  const calls = new Map(); // callId → { command, loc }
520
- const results = new Map(); // callId → loc(双向:孤儿 result 也要指认,2026-09-09 反向挑刺 T1)
520
+ const results = new Map(); // callId → loc(双向:孤儿 result 也要指认,2026-09-09 T1)
521
521
  for (const { event, lineNo } of events) {
522
522
  if (event.type === 'tool/call') {
523
523
  const callId = event.data?.callId;
@@ -539,7 +539,7 @@ export function toolPairingViolations(events) {
539
539
  out.push(violation('P3', loc, `tool/call ${callId}(命令 ${command || '(未知)'})没有配对的 tool/result——孤儿调用(中断/失败未落结果),考古提取将缺该输出`));
540
540
  }
541
541
  }
542
- // 双向(反向挑刺 T1 增量):孤儿 result = result 无对应 tool/call。
542
+ // 双向(T1 增量):孤儿 result = result 无对应 tool/call。
543
543
  // 折叠后 wire 流中无主 tool 消息 = provider 拒绝风险(W1/W2 同族、不同层);
544
544
  // 与孤儿 call 同为 warning 级——合法场景(中断/修复产物)不破坏日志。
545
545
  for (const [callId, loc] of results) {
@@ -579,7 +579,7 @@ function findUnparsableContent(node, path) {
579
579
  }
580
580
 
581
581
  /**
582
- * P4 —— tool/result 输出结构契约(考古任务书 B2)。
582
+ * P4 —— tool/result 输出结构契约(考古 B2)。
583
583
  * `data.message.content` 必须可递归解析(list[dict{type:text,text}] 或等价);
584
584
  * 不可解析片段 = 考古提取将漏数据。空 content(失败/无输出)合法。warning 级。
585
585
  */
package/lib/contracts.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * DSH 会话日志契约规则目录(spec)。
5
5
  *
6
6
  * 规则集来源:
7
- * - `dsh-scale-audit-疑点记录.md`(59 条契约发现 / F1–F7 / N1–N6 / R1–R3)
8
- * - `复盘-会话修复事故-20260825.md`(三层契约:持久化 / 客户端引擎 / 插件语义)
7
+ * - 早期契约审计发现(59 / F1–F7 / N1–N6 / R1–R3)
8
+ * - 会话修复事故复盘(三层契约:持久化 / 客户端引擎 / 插件语义)
9
9
  * - `@deepseek-ai/dsh-session@0.1.0-rc.7` 官方源码逐行核对(见每条 `source`)
10
10
  *
11
11
  * 每条规则只描述"契约是什么";具体判定逻辑在 `lib/validate.js`(离线体检)
@@ -290,7 +290,7 @@ export const CONTRACT_RULES = [
290
290
  title: 'ignorable 未知 type 合法性(带被忽略标记的未知事件须有消费者)',
291
291
  layer: LAYER.PERSISTENCE,
292
292
  severity: SEVERITY.WARNING,
293
- source: '反向挑刺 2026-09-09 T2(E3 ignorable 无合法性校验 = 后门)',
293
+ source: '对抗性复查 2026-09-09 T2(E3 ignorable 无合法性校验 = 后门)',
294
294
  description: '未知 type + ignorable:true 被读路径接纳但无人消费 = 静默垃圾。排除已知消费者白名单(retrace/marker、retrace/goal-marker、message-editor/ 前缀等 retrace 客户端消费的插件 marker)后,其余 ignorable 未知事件报 warning。',
295
295
  },
296
296
  {
@@ -329,7 +329,7 @@ export const CONTRACT_RULES = [
329
329
  title: '空会话文件(有 header 无事件)显式报出',
330
330
  layer: LAYER.FRAMING,
331
331
  severity: SEVERITY.WARNING,
332
- source: '反向挑刺 2026-09-09 T3(36 条规则全来自有内容事故,空态无覆盖)',
332
+ source: '对抗性复查 2026-09-09 T3(36 条规则全来自有内容事故,空态无覆盖)',
333
333
  description: '有 header 但零事件 = 异常空会话(新建即空或写入未落盘)。空态不在任何有内容规则的覆盖下,显式 warning 供人判断。',
334
334
  },
335
335
  {
@@ -337,7 +337,7 @@ export const CONTRACT_RULES = [
337
337
  title: 'tool/call ↔ tool/result 配对完整性(考古 B1)',
338
338
  layer: LAYER.PLUGIN,
339
339
  severity: SEVERITY.WARNING,
340
- source: 'dsh-会话日志考古-插件任务与方法.md §2/§4.2(callId 配对,不可用"上一个 call"推断)',
340
+ source: '考古方法 §2/§4.2(callId 配对,不可用"上一个 call"推断)',
341
341
  description: '每个 tool/call 的 data.callId 必须能在 tool/result 的 data.message.source.callId 中找到配对;孤儿 call(无 result)告警——中断/失败轮次可能产生孤儿(合法但要审计),考古提取将缺该输出。',
342
342
  },
343
343
  {
@@ -345,7 +345,7 @@ export const CONTRACT_RULES = [
345
345
  title: 'tool/result 输出结构可解析(考古 B2)',
346
346
  layer: LAYER.PLUGIN,
347
347
  severity: SEVERITY.WARNING,
348
- source: 'dsh-会话日志考古-插件任务与方法.md §2/§4.2(content 递归 text 结构)',
348
+ source: '考古方法 §2/§4.2(content 递归 text 结构)',
349
349
  description: 'tool/result 的 data.message.content 必须可递归解析(list[dict{type:text,text}] 或等价);不可解析片段 = 考古提取将漏数据。空 content(失败/无输出)合法。',
350
350
  },
351
351
  // ── M · 客户端引擎层 ────────────────────────────────────────────────────
package/lib/log-reader.js CHANGED
@@ -243,8 +243,8 @@ export function loadSessionLog(path) {
243
243
  *
244
244
  * 帧布局:帧 1 = header 行(单行 JSON,~几百字节),帧 2+ = 事件流。
245
245
  * 短码推导(工作区 createdAt 序号)需要扫全部会话但只需要 header——
246
- * 读文件前缀 64KiB 足够覆盖完整帧 1,避免全量读大文件(opena 工作区
247
- * ~108MiB 压缩)。失败返回 null(调用方降级)。
246
+ * 读文件前缀 64KiB 足够覆盖完整帧 1,避免全量读大文件(大会话压缩后可达
247
+ * 数百 MiB)。失败返回 null(调用方降级)。
248
248
  *
249
249
  * @param {string} path 会话日志文件路径(.jsonl.zstd 或明文 .jsonl)。
250
250
  * @returns {object|null} header 对象;无法解析返回 null。
package/lib/repair.js CHANGED
@@ -1245,10 +1245,10 @@ export function repairSession(file, opts = {}) {
1245
1245
  issues.push({ kind: 'trim-budget', detail: `估算 ${r.estimatedTokens} tokens ≤ 预算 ${opts.trimBudget}——无需裁剪(${r.kept} 条消息全保留)` });
1246
1246
  }
1247
1247
  }
1248
- // L4 新原语(2026-08-30 任务书 §L4 收编 tools/ 验证工具)
1248
+ // L4 新原语(2026-08-30 收编外部验证工具)
1249
1249
  if (typeof opts.tailRenumberDelta === 'number') {
1250
1250
  // 起点自动推导:从首个可平移的 seq 起(即所有事件都平移)。
1251
- // fix-tail 原工具是 <startLine> <delta> 双参;任务书 §L4 简化为单参 delta
1251
+ // fix-tail 原工具是 <startLine> <delta> 双参;L4 简化为单参 delta
1252
1252
  // (尾部全部平移)。若需部分平移,传 --tail-renumber 前先 --keep-ranges。
1253
1253
  const r = tailRenumberText(plain, 0, opts.tailRenumberDelta);
1254
1254
  if (r.error) {
package/lib/validate.js CHANGED
@@ -106,7 +106,7 @@ export function validateSessionLog(log, opts = {}) {
106
106
  }
107
107
  }
108
108
 
109
- // ── Z3 · 空文件体检(2026-09-09 反向挑刺 T3 增量)──────────────────────────
109
+ // ── Z3 · 空文件体检(2026-09-09 T3 增量)──────────────────────────
110
110
  // 空态无覆盖:36 条规则全来自"有内容"事故,空会话文件应显式报(不管 DSH 编排层怎么处理)。
111
111
  // 有 header 但零事件 = 异常空会话(warning,不破坏 ok);连 header 都没有 → H1 已报。
112
112
  if (header !== null && events.length === 0) {
@@ -159,7 +159,7 @@ export function validateSessionLog(log, opts = {}) {
159
159
  violations.push(...nullTurnStepViolations(events));
160
160
  violations.push(...turnEndReasonViolations(events));
161
161
 
162
- // ── E7 · ignorable 未知 type 合法性(反向挑刺 T2)────────────────────
162
+ // ── E7 · ignorable 未知 type 合法性(T2)────────────────────
163
163
  violations.push(...ignorableTypeViolations(events, formatVersion));
164
164
 
165
165
  // ── I1 · inbox seed 相对重放(fork 边界孤儿;交接书 L1)──────────────
@@ -488,7 +488,7 @@ export function resumeVerdict(result) {
488
488
  violationsByTier: { structural: [], inbox: [], tokenMeter: [] },
489
489
  };
490
490
  }
491
- // 三档各自的「阻断规则集」——按任务书 §L3 档位定义:
491
+ // 三档各自的「阻断规则集」——按 L3 档位定义:
492
492
  // 可加载:结构层(PERSISTENCE/FRAMING)+ 引擎层非 I1/T1/T2/T3/T4 的 error;
493
493
  // 可继续:+ I1(inbox 重放);
494
494
  // 可压缩:+ T1/T2/T3/T4(token-meter 配对 + 渲染层节点 key/turn)。
@@ -500,7 +500,7 @@ export function resumeVerdict(result) {
500
500
  const has = (id) => (byId[id]?.length ?? 0) > 0;
501
501
 
502
502
  // 可加载阻断 = 除 I1/T1/T2/T3/T4 外的所有 error 违规(结构/信封/物理序/工具配对等)。
503
- // 注意:不能用 result.ok(它把 T1/T2/T3/T4/I1 也计为 error)——三档判定按任务书定义,
503
+ // 注意:不能用 result.ok(它把 T1/T2/T3/T4/I1 也计为 error)——三档判定按 L3 定义,
504
504
  // T1/T2/T3/T4 只影响「可压缩」档、I1 只影响「可继续」档。
505
505
  const loadableBlockers = violations.filter(
506
506
  (v) => v.severity === 'error' && !['I1', 'T1', 'T2', 'T3', 'T4', 'T5'].includes(v.id),
package/package.json CHANGED
@@ -1,7 +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.14",
4
+ "version": "0.3.15",
5
5
  "packageManager": "pnpm@11.7.0",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
@@ -29,9 +29,9 @@
29
29
  "README.zh.md"
30
30
  ],
31
31
  "scripts": {
32
- "check": "node scripts/check-syntax.mjs",
32
+ "check": "node scripts/check-syntax.mjs && node scripts/gen-contracts-doc.mjs --check",
33
33
  "test": "vitest run",
34
- "prepublishOnly": "node scripts/check-pkg-meta.mjs && node scripts/check-publish-leaks.mjs && pnpm check && pnpm test"
34
+ "prepublishOnly": "node scripts/check-pkg-meta.mjs && node scripts/prepublish-gate.mjs && pnpm check && pnpm test"
35
35
  },
36
36
  "keywords": [
37
37
  "dsh",