Files
deepseek-harness/.agents/notes/implemented/simplification/2026-07-26-consolidate-gate-scripts-on-existing-deps.zh.md
T
Tianyi Cui ebdcb5776a fix(scripts): address review findings on the gate consolidation
- publint-all: the recursive publication view uses readdirSync
  {recursive} again instead of globSync('**/*') — the glob skips
  dot-prefixed segments (verified empirically), but npm pack publishes
  dotfiles inside included directories, so hidden exports were
  reported missing and other hidden files escaped validation
- markdown.ts/verify-type-equiv: markdownFences now reports whether a
  closing delimiter terminates the block (mdast silently closes an
  unterminated fence at EOF), and verify-type-equiv rejects unclosed
  type-equivalence fences again — the Agent Note claimed such a block
  still fails at the manifest checks, but its comparisons can succeed
- Agent Note EN+ZH: record the restored rejection; rewrite the zh
  Problem section into past tense to match the English side's shipped
  reality; pair re-recorded
2026-07-27 12:02:39 +08:00

5.2 KiB
Raw Blame History

Agent Note: 把门禁脚本统一到已有依赖与内置模块上

Status: implemented

English | 中文

问题

scripts/ 下的门禁大多本已在用正确的工具(15 个以上的门禁使用 node:fsglobSyncmarkdown 门禁使用 mdast/micromark),但少数几个掉队的脚本曾手写同类门禁早已用既有依赖或内置模块完成的事情:

  • 重复的围栏扫描器。scripts/md-fences.ts(约 55 行,由 doc-typecheck.ts 消费)和 scripts/verify-type-equiv.ts 中的 extractEquivBlocks(约 39 行)曾是同一个围栏代码块正则行扫描器的两份拷贝,而 scripts/verify-mermaid.ts 早已通过访问 mdast code 节点来提取代码围栏;scripts/markdown.ts 自己的 markdownProseLines 也曾先解析成 mdast,再用第二个正则手工跟踪围栏状态。这两个正则扫描器只识别第 0 列的反引号围栏,因此在波浪线围栏和缩进围栏上与基于 mdast 的门禁悄悄不一致。
  • 手写的 argv 解析。scripts/publint-all.ts 中的 parseOptionsscripts/verify-built-package-invariants.mjs 中与之几乎相同的拷贝(约 26 行)曾手工推进 argv 下标,而同类脚本(verify-runtime-closure.tsbuild-exe-for-python-sdk.tspackages/sdk/scripts/src/args.ts)早已在使用 node:util 的内置 parseArgs
  • **手写的目录遍历。**五处代码曾各自重写 globSync 已覆盖的嵌套 readdirSync 遍历:verify-runtime-closure.ts 对 packages 与 vendor manifest(元数据清单)的扫描、dev-web.tsdiscoverPluginDirsverify-package-paths.tsrealPackageNamesverify-client-domain-graph.tslistSources,以及 publint-all.tsaddPath(合计约 5565 行)。scripts/package-invariants.ts 展示了一行式的 globSync 模板。

所有替换都不需要引入新依赖;每一处替换用的都是既有的 devDependency 或 Node 内置模块。

决策

  • scripts/markdown.ts 中的共享 mdast 围栏辅助函数 markdownFences 访问 code 节点,读取语言、完整 info string、块体以及以 1 起始的开围栏行号;doc-typecheck.tsverify-type-equiv.ts 通过它提取代码围栏。md-fences.ts 和重复的 extractEquivBlocks 扫描器已删除,markdownProseLines 也改为从解析出的 code 节点位置推导围栏内的行,而不再用第二个正则。
  • 两个 CLI 都改用 parseArgs 解析 argv;未知选项和缺失取值仍然大声失败,只是错误文案换成了 parseArgs 自带的文本,而非原先手写的用法字符串。
  • 那五处掉队的目录遍历改用 globSynccheck-workspace-constraints.tsclean.ts 中的遍历保留:它们需要 dirent 级别的细节来诊断结构异常的目录树,按模式匹配的 glob 报告不了这些信息。

曾考虑的替代方案

  • **新的 glob/目录遍历依赖(tinyglobbyfdir)。**不予采纳:内置模块已在全仓库范围内胜出;这几处只是掉队者,不是能力缺口。
  • **用 p-map 替换 publint-all.ts 中约 19 行的有序 worker 池。**刻意未纳入:为一次小删除引入一个新 devDependency,正处在依赖策略门槛的边缘,而且该池的需求(worker 数量有界、确定性顺序、环境变量覆盖)已记录在并行 pre-push 门禁决策记录中。仅当 p-map 赢得第二个消费方时再顺带纳入。
  • **保留这两个围栏扫描器。**不予采纳:在第三个正确实现旁边放着两份逐渐漂移的解析器拷贝,正是共享的 markdown.ts 辅助函数要防止的那种重复;「只认第 0 列反引号」的限制也是同类门禁之间的潜在不一致。

后果

  • 只剩一个围栏解析器:所有 markdown 门禁现在都经由 mdast 归类代码围栏,因此波浪线围栏、缩进围栏和四反引号容器围栏在各处的行为完全一致。文档树中不存在正则扫描器处理有误的围栏形态,所以在落地这次替换的代码树上门禁结果不变:pnpm run doc-sync 及每个被改写的门禁在改动前后各跑一遍,输出逐字节相同(doc-typecheck 的块数/opt-out 计数、verify-type-equiv 的匹配计数、publintverify-built-package-invariantsverify-runtime-closureverify-package-pathsverify-client-domain-graph,以及两个包 README 散文门禁)。
  • verify-type-equiv 仍然拒绝未闭合的类型等价围栏:mdast 会在文件末尾静默闭合未闭合的代码块(其比较随后可能通过),因此共享辅助函数会报告闭合定界符是否存在,门禁在块未闭合时报错,保留了被删扫描器的这条拒绝路径。doc-typecheck 的扫描器本来就没有这条错误路径。
  • parseArgs 对重复出现的选项保留最后一个值而不报错——一个测试未固定的开发工具边缘用例,作为删除两份手写解析器的交换被接受。(严格模式下,需要取值处遇到以 -- 开头的 token 仍会拒绝,与被替换的解析器行为一致。)