← 返回列表
未验证
从 DeepSeek Harness 验证并搭建 Crusader Kings III 模组。四个宿主平面工具:
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/19 · 已提供中文文档
DeepSeek Harness 主机平面插件:针对真实的原版安装验证 Crusader Kings III 模组(39 项检查,4 个工具)。
综合分
29.5
GitHub 分
29.5
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add ABccgh/dsh-ck3-modcheck该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
信任档位:已验证本站已于 1 天前真实安装成功(L4 · 真实安装)
- 是什么
- dsh 原生插件 · market
- 装得上吗
- 本站已真实安装成功(L4 · 真实安装,非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 6 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/24(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-ck3-modcheck
从 DeepSeek Harness 验证并搭建 Crusader Kings III 模组。四个宿主平面工具:
| 工具 | 功能 |
| --- | --- |
| ck3_modcheck | 对照 39 项检查验证磁盘上的模组——布局、两个 .mod 文件、路径、编码、标识符、花括号平衡、针对已安装原版树的脚本词汇,以及对原版内容的整文件覆盖。除非 fix: true,否则为只读。 |
| ck3_mod_init | 生成一个最小的可加载模组骨架,然后对它刚写入的内容运行 ck3_modcheck,使结果得到验证而非仅凭断言。除非明确要求,否则绝不覆盖。 |
| ck3_mod_status | 读取启动器自身的数据库并报告启动器的看法:已注册的模组、它们的 status,以及当前游玩集的加载顺序。要读取哪个数据库文件是探测出来的,而非硬编码——见下文。还会报告启动器注册表不知道的 .mod。只读。 |
| ck3_mod_evidence | 读取运行时 logs\ 目录,该目录每次启动都会被重写——报告会标注自身日期并说明它描述的是哪一次运行。其独特价值在于可达性信号——一个被引用但从未触发的事件——这是任何静态检查都无法看到的,并且只有在引擎实际写入 event_log.csv 时才可读(实测在 1.19.0.6 上它并不会写入,因此该工具报告“无法读取它”而非“没有问题”)。对错误进行跨接收端去重计数(一条消息会落入 debug.log + error.log + game.log,因此按文件求和会膨胀 3 倍),并将 Script system error! 外壳与其续行合并(实测:1,780 行 E 行折叠为 43 个外壳,而真正的故障位于下一行)。 |
作为宿主平面插件安装在 $DSH_HOME/plugins/ 下,由
$DSH_HOME/profiles/web/cordis.patch.yml 中的一行 insert: 挂载。它不发布任何服务——它只将工具注册到
宿主 tools 注册表中——因此不需要 isolate 领域,也不会与宿主服务冲突。
它运行在 HOST 平面上,因此 web profile 的行在启动时挂载:安装或
更改插件后,重启 Host。在此之前,这些工具在活动会话中都不存在。
配置
profile 补丁会替换此行的整个 config,而不是合并进去,因此在那里省略的键
会静默回退到下面的默认值。
| 键 | 默认值 | 用途 |
| --- | --- | --- |
| gameRoot | D:\Program Files (x86)\Steam\steamapps\common\Crusader Kings III | 安装根目录。游戏数据位于 \game\。 |
| modDir | D:\CK3Mods | 模组工作区。必须全为 ASCII——见下文。 |
| strict | true | 为 false 时,条目形状和样式警告会被抑制。 |
| launcherDir | C:\Users\\Documents\Paradox Interactive\Crusader Kings III | 启动器的 launcher-v2.sqlite 所在位置。由 ck3_mod_status 读取。由 ck3_mod_evidence 读取以获取 logs\。 |
modDir 不得位于 Documents 下。 CK3 Wiki 的 Mod structure 页面原文如下:
“目录不能包含非英文字符。如果你的 Windows 账户名包含此类字符,
你必须使用 Documents 文件夹之外的目录。”* 在撰写本文所针对的机器上,
账户名包含非 ASCII 字符,这就是默认值为 D:\CK3Mods 的原因。
launcherDir 是唯一确实位于 Documents 下的路径,而这并不矛盾:
wiki 的限制适用于模组自身的目录,游戏在加载时必须解析该目录。
launcherDir 由 Node 读取,而非由游戏的模组加载器读取,并且它是启动器的固定位置。
读取的是哪个启动器数据库——经过实测,而非假设
一个已选择加入 beta 通道的启动器会保留不止一个数据库,而启动器
实际写入的那个并不总是 launcher-v2.sqlite。在此部署上实测:
| 文件 | mtime | 已注册模组 | playset 行数 |
| --- | --- | --- | --- |
| launcher-v2.sqlite | 2026-09-15 20:05 | 0 | 0 |
| launcher-v2_openbeta.sqlite | 2026-09-16 23:44 | 7 | 7(全部启用) |
| launcher-v2_openbeta-backup.sqlite | 2026-09-16 19:05 | 3 | 3 |
读取硬编码的名称产生了一份错误报告:“没有已注册的模组”以及“启动器/磁盘
无分歧”,而启动器自己的模组文件夹中放着七个 .mod 文件,游戏的日志中也列出了
它们。ck3_mod_status 现在会探测每一个 launcher-v2.sqlite,按证据对它们排序(有已注册
模组 → playset 已激活 → 最新 mtime),读取胜出者,并打印完整表格,附上
它跳过的每一个数据库的原因。因此,备份副本即使更新,也会输给实时数据库,
而空数据库永远不会胜过有数据的数据库。
这些检查依据什么
每一项检查都可追溯到一个一手来源——CK3 Wiki 页面(Mod structure、Modding、
Event modding、Localization、Interface、Patch 1.5/1.13)或真实原版
安装中的某个文件——绝非凭记忆。其中起支撑作用的几项:
| 规则 | 来源 |
| --- | --- |
| (name).mod 位于文件夹旁边且是必需的;descriptor.mod 放在内部并省略 path | Mod structure:“没有它,启动器将无法识别该模组”;描述符排除了“包含 path 键的那一行,因为它在描述符文件中不需要”* |
| version、name、path 是必需的;supported_version 仅在同级文件中是必需的 | 该页面的“必需?”表格 |
| path 相对于用户文件夹(或绝对路径) | “不再相对于主 Crusader Kings III 文件夹,而是相对于 Crusader Kings III 用户文件夹” |
| 相同路径且相同文件名的文件会替换整个原版文件;新文件名则是追加性的 | “如果一个模组拥有与游戏相同的文件,它会替换该文件的所有内容……除非你打算覆盖整个文件,否则避免这样做!” |
| replace_path 会抑制原版文件 | “不会为指定路径加载原版文件。” |
| 本地化需要 UTF-8 BOM,l_: 必须位于开头,并且可以省略版本计数器 | Localization;实测——122/122 个原版英文文件带有 BOM,25,431 个条目省略了计数器 |
| localization/replace/english/ 和 localization/english/replace/ 都有效 | Localization:“两者……都有效,但第一个路径优先于另一个” |
| 事件文件需要 namespace,id 会使用它;id 到 9999 为止 | Event modding;实测——536 个原版事件文件中有 516 个符合,且 536 个文件名中有 0 个与其 namespace 匹配 |
| 加载顺序就是播放集顺序,位置更低的胜出 | Modding:“播放集中位置更低的模组会覆盖上方模组的相同文件。” |
测试套件中断言了两个校准项,因为一个会标记游戏自身文件的检查会教会其读者忽略它:
* 编码检查在整个原版目录树中报告 0 个发现(2,536 个 common + 536 个事件脚本);
* namespace 检查在所有 536 个原版事件文件中报告恰好 20 个(19 个不匹配 + 1 个缺失)。
它有意不检查的内容
* 标签词汇表。 wiki 的 21 个标签列表被标记为“最后验证于版本 1.1”(2023 年),
而这里的游戏是 1.19.0.6;磁盘上不存在标签列表(启动器通过网络获取它),
并且启动器自己的数据库存储了 ["1.16 'Chamfron'"]——一个游戏版本字符串——
以及该模组的状态 ready_to_play。在那里做成员资格测试会把有效模组报告为错误,因此只检查
形状(列表 vs 标量)。
* 来自 _.info 文件的字段级 schema 验证。 本节长期携带的数字——“162 个中只有 6 个包含可解析的 Valid : 列表”——无法通过三次独立计数复现,并且在其模式被找到之前不应被引用:在此安装的 162 个 _.info 文件中,69 个包含字符串 Valid,且 1 个匹配形如
^\sValid\s+\S+:\s$ 的行。结论的方向仍然成立(这些是散文式文档,不是 schema),但一个没人能重新推导出的数字比没有数字更糟。可复现的是:目录树中有 162 个 _.info 文件,而检查实际引用的两个——_events.info 和
_decisions.info——在消息中按文件和行号引用。
任何需要游戏运行的内容。 一份绿色报告并不意味着游戏会加载该模组。
ck3_mod_status 读取启动器的判定,这比我们的更强,但仍然不是游戏本身。
它不能做什么
* 证明游戏会加载某个模组。 它读取文件以及启动器的数据库。
* 判断启动器是否接受了某个 path= 值。 三种拼写已有文档说明;启动器对你的写法做了什么,并不是该文件的属性。
* 看到启动器尚未注册的模组。 ck3_mod_status 现在会列出位于
在启动器自己的 mod 文件夹中,其注册表中没有对应行,但该文件夹之外的 mod 完全不在本工具的视野范围内。
* 证明正在运行的进程加载了哪些代码。 每份报告都以一份带日期的凭据结尾——进程 id、启动时间,以及 lib/index.js 和 lib/rules.mjs 的修改时间。这是一份凭据,而非裁决:文件比启动时间更新意味着该编辑不在进程中(Node 在首次导入时缓存模块,因此被编辑过的插件会继续提供旧代码,直到 Host 重启),但它并不证明进程持有的是什么。
* 将运行时错误归因到你的 mod。 日志带有原版自身的噪声——实测:在完全未启用 mod 的情况下,setup.log 中有 512 行 W 级日志,而在另一次干净运行中,error.log 中有 2 行 E 级日志。归因需要同一次运行的差异(启用和不启用你的 mod);两次不同的运行无法相减,因为每次启动都会重置日志。
* 在此构建上读取事件可达性信号。 它需要 event_log.csv,而 1.19.0.6 从不创建该文件:控制台命令 event_queue 会运行,将报告写入 debug.log,但不写入任何文件。该工具会说“无法读取它”,而不是返回空结果。
如何检查
node test/falsify.mjs # 153 assertions, offline
该测试套件覆盖每项检查的正例和反例、上述两项原版校准、写入路径(applyFixes 端到端,包括第二次运行是空操作)、启动器数据库的选择(包括同一组三个候选的六种输入顺序)、未注册 .mod 的比较、日志读取器的 shell 行合并,以及四个工具描述——这之所以可能,仅仅是因为它们位于导出的 TOOLS_META 表中,而不是内联在 apply() 中。它并不证明 Cordis 服务注入——那需要一个实时 harness 进程。
为什么这个数字比看起来更重要。 该测试套件曾经在生成器正在产生六个真实缺陷的情况下通过了 107/107,因为当时每个断言测试的都是结构(文件是否存在、BOM 是否正确),而没有测试功能。此后添加的生成器断言与它们必须拒绝的特定错误值相耦合,并通过重新植入那些缺陷得到了验证:错误的 theme 产生 1 个 FAIL,恢复的深度为 1 的 icon 产生 2 个,删除调用点产生 1 个。一个不会失败的测试套件不是测试,因此这里的绿色运行只有与它本应捕获的内容放在一起,才算作证据。
关于插件自身契约的两点说明,均为实测:
* lib/ 中没有任何裸包导入。 经认可的安装程序会对此包建立符号链接,因此裸说明符(例如 @deepseek-ai/…)无法从链接的真实路径解析,会报 ERR_MODULE_NOT_FOUND。只出现 node: 内置模块和相对路径。
* bin/preflight.mjs 不验证此插件的配置。 该脚本读取某一行的 Config
仅当它是函数时才导出;此插件导出的是普通对象形式的 Standard Schema,因此
preflight 会打印 skip … (exports no usable Config schema)。配置自身的校验位于
test/falsify.mjs。
给未来编辑者的说明
* lib/rules.mjs 将每一项检查都保存为纯函数;lib/index.js 保存 Cordis 接线、
配置 schema 和报告渲染器。
* parseModFile 区分标量(values)与列表(lists)语法,而搞错这一点
正是这个文件已经犯过三次的错误:tags 是列表,replace_path 是标量。
* collectFiles(root, { extensions: [] }) 表示每个文件;省略该选项则只表示 .txt。
空数组过去表示“什么都不收集”,这会悄无声息地禁用一项检查。
* 花括号和引号的转义由 stripScriptNoise 处理;要统计花括号,请统计其输出,绝不要统计
原始文本。