zephyrrtos.cnZephyr 生态 · 中国驱动软件系统

← 全部插件 · 当前:dsh-compliance

DSH 插件 · 合规门禁 · 可复现反证

dsh-compliance:让每个「已完成」都带可复现的反证

典型场景:车规 / 工业功能安全一类项目开始把 AI 代理放进开发流程——让它写代码、改配置、跑验证、甚至发版。 这类项目最怕的不是代理写错,而是说不清:这条需求谁实现、按哪条判据验证过、当时放宽了什么边界、发布快照里还有哪些 open 偏差。 本插件提供的正是这个场景需要的机制:把「每一个『已完成』的结论都带可复现的反证」变成机器的默认动作——校验器、生成器、空模板与 CI 片段。 只发机制,不发结论。

包产物 0.1.1(私有 Gitea registry,latest)· 治理基线 v1.0.0 · 许可 MIT · 分发:私有 registry / git 依赖(钉标签)/ vendored · 源码仓库(私有,需账号或会员)

典型场景:AI 代理进入受控开发流程

当一个「能读写文件、能在远端执行命令、能发布包」的代理进入工程流程,交付物的可信度就不再由「它说做完了」决定。 下面四种场景是它被造出来的直接原因——每条都写明它管得住什么、管不住什么。

① 车规 / 工业功能安全类项目,让代理参与开发 需求 → 判据 → TCL 定级 → 验证证据 → 发布记录,每一步都要能回答「谁实现、按哪条判据验证过、依据在哪」。 插件把这张链上的引用可解析性做成门禁:需求 / FMEA / 证据 / 基线 / 工具路径悬空即失败,孤儿文档与到期偏差同样被拦。
管不住:判据本身要你自己写进 spec/;规程类措施「有没有照做」无法被机械验证。
② 交付要给客户 / 第三方看 发布记录由 tools/release-check.mjs 从标签快照生成(不读工作树):tag → commit → treeHash,文件身份用 git blob SHA。 「发布时有哪些 open 偏差」只能由标签回答——拿今天的登记册去写昨天的发布记录,正是这类文档最常见的失真。
管不住:它不产出认证结论,也不是审计意见。
③ 让代理自己跑门禁 插件形态把同一组检查交给代理(compliance_list / check / gen / audit),且非零退出码原样上报而不抛异常; 未启用的检查打印 SKIP 与 PASS 分列,明确写出「跳过 ≠ 通过」——它防的是「全绿」里混着从未执行的东西。
管不住:代理可以忘记跑门禁。这也是插件本身写下的第一条铁律:它不能替代 CI。
④ 凭据与发布安全 扫描覆盖三类载体:工作树文件、提交补丁、提交信息。实测价值:把令牌只放进提交信息时,前两道扫描器都报干净,第三道拦下。 发布侧还校验发布记录与标签快照一致、发布时不得把 open 偏差藏起来。
管不住:否定性结论只覆盖已声明的载体;将来出现新载体(issue、附件、release note)不会自动覆盖。
关于标准,必须说清的一件事:本项目的 TCL 定级框架借用 ISO 26262-8 第 11 章的工具置信度方法论(TI 工具影响 × TD 错误检出置信度 → TCL1–4), 但项目自己的 TCL 方法论里有一条硬约束 L4: 「本仓库中任何出现 TCL 的文档,都不得被解读为『符合 ISO 26262』」——本框架用于工程治理,不构成任何功能安全合规声明, 且 ISO 26262-8 标准原文至今未直接查阅(依据三个二手来源交叉比对,登记为 DEV-007)。 换句话说:它能帮你把「证据链与门禁」这一层做实,不能替你取得任何认证。

它替代的是哪三种失真

在一个「代理拥有几十个工具、能读写文件、能在远端执行命令、能发布包」的环境里,能力的输出直接充当工程结论,而结论的得出过程没有独立复核。由此产生三种固定形状的失真:

「做了」≠「做对」工具返回成功即当作事实,返回为空即当作「没问题」。
实例:扫描器在管道被截断时只扫了部分历史,却输出 no leaks found(FM-ENV-019)。
门禁自己会撒谎检查器检查的是「有没有这东西」,而不是「这东西是否成立」。
实例:门禁要求提交带 Requirement: trailer,却从不验证它指向什么——实测 31 条 trailer 全部指向不存在的要求,而门禁一直是绿的。
放宽边界不留痕越权操作被记录为正常流程,事后无法区分。
沙箱拒绝、一次性升权、审批结论三者若不成链,回放就不出「当时到底放宽了什么」。

针对这三条,它给出的不是流程要求,而是执行点:每个检查必须报告覆盖量与退出码(空输出不得作为通过依据); 所有引用(提交 trailer、文档 front-matter、偏差登记册、工具路径)必须可解析,且每个门禁必须有反向用例证明它能拦下目标缺陷; 策略状态、审批请求与结论都是被审计的事件——越权放宽必定留下 approval/asked + approval/decided。

它是什么

三层结构控制层 spec/:机器可读真源,判据与实测值只存在这里 · 文档层:表格由真源生成,手工编辑会被 --check 逐字节比对拦下 · 证据层 evidence/:只由工具产生、带时间戳与校验和、只增不改。
两种形态CLI bin/dsh-compliance.mjs(init / list / check / gen / audit / run)给人、CI 用 · DSH 插件 plugin/(compliance_list / compliance_check / compliance_gen / compliance_audit)给代理用。插件不重新实现任何检查逻辑,只是 CLI 的薄包装——同一件事有两个真源,迟早会给出不同答案。
两个版本轴治理基线 v1.0.0(绑定 treeHash 与发布时 open 偏差)与 包产物 0.1.x 是两条独立轴:一次包补丁不该动基线标签轴,基线发布也不必等于一次包发布。

七个检查各自在防什么

secrets三类载体(工作树文件 / 提交补丁 / 提交信息)里的凭据。实测:把令牌只放进提交信息时,前两道扫描器都报干净,第三道拦下。
requirements需求规范与注册表的双向漂移。
tcl定级不可复算;「已落地」的措施指向不存在的目标。
fmeaAP 手写、策略不单调、AP=H 的条目开着没人管。
permissions用「看起来失败了」代替精确拒绝标记;覆盖缺族。
traceability引用悬空(需求 / FMEA / 证据 / 基线 / 工具路径)、孤儿文档、到期未处理偏差。
release发布记录与标签快照不一致;发布时把 open 偏差藏起来。
跳过不是通过。被配置关闭的检查打印为 SKIP,与 PASS 分列,并明确写出「跳过 ≠ 通过——跳过的检查未被执行」。 这条看似琐碎,但它防的是「全绿」里混着从未执行的东西。

安装与接入(三种方式)

它不在公共 npm 上(dsh-compliance 这个名字已被他人占用)。分发走下面三条路,其中只有 registry 那条会强制分发边界:

registry(推荐)消费者拿到 files 过滤后的 40 个文件(bin/ lib/ tools/ templates/ plugin/ cordis.patch.yml)。边界成立:spec/ evidence/ 10-records/ baseline/ 均不在包内。
git 依赖消费者拿到整个仓库的检出(含本项目的 spec/ 实测值、evidence/、记录、基线)。边界不成立——git 不认 files 字段。
本地目录(vendored)指向工作树的联接(junction),同样看到整个仓库。边界不成立。
必须让消费者知道的一条:仓库里的 spec/ 是本项目的实测值,消费者不得把它当成自己的证据。 dsh-compliance init 生成的骨架来自 templates/(空模板 + declaredGaps「到现在为止没人测过」的清单),永远不会复制本项目的 spec。

方式 A · 私有 Gitea registry(边界强制生效)

# 已发布版本:0.1.0、0.1.1(dist-tag latest = 0.1.1)
npm i -D dsh-compliance --registry https://zephyrrtos.cn:3000/api/packages/hakehuang/npm/

该 registry 需要凭据(匿名请求返回 401 reqPackageAccess)——账号与访问令牌见加入会员说明。 仓库与 registry 均为私有,这也是本页能给出的最完整公开说明。

方式 B · git 依赖(不需要 registry,但要钉标签)

npm i -D "git+https://zephyrrtos.cn:3000/hakehuang/dsh-compliance.git#pkg-v0.1.1"
不钉版本时每次安装都会拉最新提交;钉标签(#pkg-v0.1.1)或提交 sha 才是可复现的。 注意上表的第二行:这条路会把整个仓库交给消费者,若不可接受就走方式 A。 「克隆 → 安装 → 使用」三步在消费者视角实测通过;未验证的是 npm 自身对 git+https:// 的拉取那一步(本机沙箱禁止管道捕获子进程输出,需在你的机器或 CI 上执行)。

30 秒上手(四步)

# ① 生成骨架:14 个文件(空模板 + declaredGaps + CI 片段 + .gitattributes)
npx dsh-compliance init

# ② 看每项检查需要哪些文件、是否就绪
npx dsh-compliance list

# ③ 执行;未启用的检查显示为 SKIP —— 跳过不等于通过
npx dsh-compliance check

# ④ 只有改了判据/实测值时才动 spec/,然后让派生物与真源一致
npx dsh-compliance gen

装成 DSH 插件:把门禁交给代理

包内带 cordis.patch.yml 与 plugin/,装载后代理获得四个工具: compliance_list(哪些检查就绪)、compliance_check(跑全部检查并按逐项裁决返回)、 compliance_gen(由 spec/ 重新生成派生物)、compliance_audit(引用可解析性与发布快照一致性)。 工具在工作区根目录运行,非零退出码原样报告而不抛异常——它就是要给你看的证据。

装载状态如实说明:✅ 已验证(会话工具目录里出现这四个工具);❌ 未验证的是 cordis.patch.yml 被真实装载器挂载那一步之外的分支(如多 profile、非 desktop profile)。 插件生命周期(W6:插件全生命周期安全校验)目前仍是占位,未开始。

优势(每条附实测依据,不是形容词)

「没发现问题」必须被证明

扫描与校验都必须报告覆盖量与退出码。把令牌只放进提交信息时,前两道扫描器报「干净」,第三道拦下——这个缺口是靠实验发现的。

拒绝必须落在精确文本上

「被拒」与「真实拒绝标记」是两件事;校验器还强制形态与族一致(写错方向等于把可观测性缺口抹平),并单独核对「被拒」之后目标确实未落盘。

跳过不是通过

SKIP 与 PASS 分列。它防的是「全绿」里混着从未执行的东西。

生成而非手抄

文档表格全部由 spec/ 生成、--check 逐字节比对。实测抓到过一次生成物嵌入了「现在」——要被逐字节比对的文件不能含时间戳,否则跨 UTC 午夜必然失败。

门禁自身必须有反向用例

每个步骤都要证明它能拦下它声称要拦的东西。发布记录校验器首版把检查写在验证之前、恒报 [OK],是六条反向用例全部「通过」才把它逼出来的。

「本地过 = CI 过」可被检查

本地门禁与 CI 跑同一组检查(14 道本地 / 25 步 CI)。本月三处「本地绿、CI 红」都是这条纪律查出来的。

只发机制,不发结论

包只含校验器、生成器、schema、空模板与 CI 片段;不含任何实测值、证据或记录——registry 路径下实测 40 个文件。

局限(这一节比上面更重要)

一条不写局限的技术说明,就是它自己反对的那种失真。下面每一条都来自项目自己的受控技术说明与偏差登记册,不是我们的概括。

结构性局限:它无法机械消除的东西

规程类措施无法被验证校验器能确认某份规程存在、锚点真实,不能确认任何人在工作中照做了。这类措施的效力取决于人(REQ-GOV-004,verificationKind: procedure)。
架构级风险不靠文档消除例如「明文凭据 × 读取不设边界 × 远端免密 sudo」构成的无审批提权链——处置必须是架构改动(FM-ENV-024、DEV-011)。
单人承担全部角色「评审与被评审分离」在正式基线上是硬要求,当前由偏差承载(DEV-001)。
外部标准引用只能靠人核对TCL 框架借用 ISO 26262-8 第 11 章的方法论,但不构成任何功能安全合规声明;标准原文未直接查阅(DEV-007)。
AP 是内部策略FMEA 的行动优先级是本项目自定策略,不是 AIAG-VDA 手册的复现(DEV-008)。
否定性结论的边界「仓库里没有凭据」只覆盖已声明的载体(文件内容 / 提交补丁 / 提交信息)。将来出现新载体(issue、附件、release note),这条结论不会自动覆盖它。

环境与工程局限

必须在工作区根目录运行否则 git ls-files 与 spec/、生成物路径的基准不对(CLI 提供显式 --root)。
需要 git受控文件集、历史、标签都来自 git;不是 git 仓库时凭据扫描明确失败(不是跳过)。CI 需 fetch-depth: 0。
release 检查需要标签浅克隆取不到标签 → 校验失败。这是故意的:拿不到 git 数据时拒绝判为通过。
写进 spec/ 的路径必须 POSIX 风格Windows 上 path.join 产出反斜杠:本地能解析、Linux 上不存在(校验器有专门规则)。
本地门禁脚本是 PowerShell跨平台受限:跨平台部分在 bin/ + lib/,tools/*.ps1 仅 Windows。
某些沙箱禁用命名管道任何依赖 git 凭据助手的动作都会失败(助手经 sh.exe 派生)——在受限 shell 里表现为「凭据不存在」,实为「凭据用不了」。这是本项目反复登记的一类误判。
git / 本地目录依赖绕开分发边界files 只在打包时生效;见上面的边界表,优先用 registry。

尚未实现 / 未验证

跨仓库工具一致性声明的补偿措施(CI 比对两仓库工具文件哈希)尚未实现,目前靠人工同步(DEV-003)。
凭据吊销责任所有者选择暂缓,到期 2026-10-24;在此之前,「已清理」的说法不构成闭环(DEV-006)。
服务端 CI本仓库无 git remote 时 25 步 CI 从未真正运行,全部在容器内替代执行;现已推到 Gitea,但那份工作流尚未在其上跑过。
未被任何变更指向的需求追溯矩阵实测:96 条需求从未被任何提交指向(其中 94 条是工具族需求)。它不违反任何现有规则,因此不会被任何门禁拦下,只能被度量出来。
部分门禁项未强制reviewer != owner、approved 必须有 approver、30 天 draft、front-matter 取值合法性——四项未强制(受控文档程序里已逐项标注,不假装已强制)。
插件生命周期W6(插件全生命周期安全校验)仍是占位,未开始。

什么时候不要用它

不打算修红的时候

门禁红了却没人管,比没有门禁更糟:它训练人忽略告警。这种情况应当只开 secrets,其余显式关掉(SKIP 是诚实的)。

把它当「合规认证」用

它输出的是可复现的反证与登记,不是认证结论;它借用某些标准的方法论,但不构成对任何标准的符合性声明。

一次性脚本 / 无 CI 的项目

它的价值主要在「每次变更都被同一组检查盯着」;没有 CI、也没有提交纪律时,它只能做 secrets 那一项。

想让它替你决定判据

它不提供判据——判据必须由你写进 spec/(包括「什么算失效模式」「哪个拒绝标记才算数」)。

版本与溯源

包产物 0.1.1产出提交 e0f4fd4,标签 pkg-v0.1.1(README-PLUGIN.md 重写为接入指南)。registry 上 dist-tag latest。
包产物 0.1.0产出提交 98c2548,首次发布(打包形态 + 插件半边)。
治理基线 v1.0.0由 spec/traceability/baselines.json 声明,绑定 treeHash 与发布时 open 偏差;发布记录由 tools/release-check.mjs --release <id> 生成,不读工作树、只读标签。
为什么用标签补溯源实测发现 Gitea 的 registry 不返回 gitHead(npm view dsh-compliance gitHead 为空),所以「靠 npm 自动记录产包提交」这条链没有兑现——改用 git 标签,并把「包版本 ↔ 提交 ↔ 标签」的对应表手工维护在发布文档里。
问智能体 Zephyr 问题问答 · 直接问智能体