# dsh-hazchem-check — 危险化学品台账与重大危险源辨识核对

### 快速试跑（1 分钟）

```bash
node samples/quickstart/run.mjs --check
```

样例在 `samples/quickstart/input/`，期望输出在 `samples/quickstart/expected/result.json`；截图见 `docs/assets/quickstart.png`。


[English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)

<!-- topblock:v1 -->
> **这是什么**　危险化学品台账与重大危险源辨识核对。输出一份「哪一行、哪一栏、差什么」的清单。
> **给谁用**　安全管理员、危化品管理岗；不用懂命令行。
> **你交什么**　这项核对用到的原始材料（表格、清单或文书）；不改原件。Excel 可先转成 JSON/YAML，对话里也能代转。
> **它不做什么**　不判合规、不认定责任、不替代审核人；只列材料内部能逐条指认的差异。
> **怎么开始**　在 WorkBuddy / 扣子搜「安全合规核对包」（本检查是其中一项；上架以商城为准）；或命令行：
> `dsh plugin --profile <name> add dsh-hazchem-check`
<!-- /topblock:v1 -->

[![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-listed-en.svg)](https://dsh.market/)
[![dshfind](https://dshfind.com/api/badge/PerryLink/dsh-hazchem-check?metric=downloads)](https://dshfind.com/en/plugins/PerryLink/dsh-hazchem-check?ref=badge)

`dsh-hazchem-check` 读取一份危险化学品台账与重大危险源辨识记录——表头加每种化学品一行——核对这份台账自身的齐备与算术：化学品名称与危险性类别是否填写、储存量是否可解析为数值、是否记录了临界量、「是否重大危险源」的判定是否与台账自己写的储存量和临界量的关系相符、有储存量的是否记录了安全技术说明书编号、CAS 号是否重复、表头是否声明辨识依据、品名栏是否残留模板占位符。

## Install

```sh
dsh plugin --profile <name> add dsh-hazchem-check
dsh --profile <name> --dump-config | grep 'dsh-hazchem-check'
```

## 实际输出长什么样

![dsh-hazchem-check 工作流图：文档 → 规则包 → 核对结果。](docs/assets/dsh-hazchem-check-flow.svg)

*工作流概览：文档 → 规则包 → 核对结果。下面的示例使用实际命令面。*


本插件对自己 `HZ-002` 测试夹具的**真实输出**，不是示意图。规则库不伪造引文，因此每条发现都会同时写明所引条款，以及该条款原文本次未取得。

## 它回答什么问题

### 示例

下表是示例集：第一行是详细走查，其余行是简短案例。


#### 详细输出

**工具** `hazchem_check`

**输入**

~~~json
{"rows":[{"化学品名称":"甲醇","最大储存量":"满罐","计量单位":"t"}]}
~~~
 
**输出**

~~~json
{
  "id": "dsh-hazchem-check.HZ-002.de09b5a6",
  "ruleId": "HZ-002",
  "severity": "warn",
  "locator": {
    "field": "maxStorage",
    "row": 1
  },
  "found": "第 1 行「maxStorage」的值「满罐」无法解析为数字",
  "expected": "「maxStorage」应填写数字",
  "fix": "储存量应填写数值；本条只核对可解析性，不判断数量是否真实"
}
~~~

*来源 `tests/fixtures/HZ-002/HZ-002-unsafe.json (cases.json expects HZ-002 count 1); run via lib/index.mjs rules/hazchem-check.yaml`*

| 你会问 | 它怎么答 |
|---|---|
| 台账写的是「否」，但储存量超过了旁边写的临界量，能查出来吗？ | 能。`HZ-003` 拿台账自己写的两个数相比，判定与这个关系不符时逐行报出；某个单元是否真的构成重大危险源，它不作判断。 |
| 某行的临界量栏是空的，会被报出吗？ | 会。`HZ-004` 要求每行都填写临界量。它只核对这一栏是否填了，不判断填的值是不是该品种的临界量——填 `0` 也会通过。 |
| 化学品名称填了，危险性类别空着。 | `HZ-001` 要求每行同时有名称与危险性类别，缺其一即报出该行。它不判断类别填得对不对。 |
| 储存量写的是 `1,500 kg`，还读得出来吗？ | 读得出来。`HZ-002` 取其中的数字部分，只有解析不了的储存量才报出。数量是否真实、是否按设计最大量填写，它不核对。 |
| 哪些行必须填写安全技术说明书编号？ | `HZ-006`：凡是填了储存量的行。它只核对编号栏是否填写，不判断说明书是否完整、是否与该化学品对应。 |
| 同一个 CAS 号在两个库房各出现一次。 | `HZ-007` 会报出重复的 CAS 号，因为重复既妨碍去重，也让储存量合计被重复计算。同一物质分库房登记属于正常情形：请在储存位置栏加以区分，或停用本条。台账没有 CAS 号栏时，本条报告「无法执行」，而不是静默通过。 |

## 依据的标准

| 文件 | 文号 | 引用它的规则 |
|---|---|---|
| 《危险化学品安全管理条例》 | 国务院令第591号（2002年1月26日国务院令第344号公布，2011年2月16日国务院第144次常务会议修订通过，自2011年12月1日起施行） | HZ-001, HZ-002, HZ-003, HZ-004, HZ-006, HZ-008 |
| 《危险化学品重大危险源辨识》 | GB 18218—2018（2018-11-19发布，2019-03-01实施；全部技术内容为强制性；代替GB 18218—2009） | HZ-002, HZ-003 |
| 《危险化学品重大危险源辨识》 | GB 18218—2018（本次未取得条文） | HZ-005 |
| 《危险化学品安全管理条例》 | 国务院令第591号（本次未取得条文） | HZ-007 |

**边界（中文译文，以英文原文为准）：** 本插件核对一份**危险化学品台账与重大危险源辨识记录**的齐备性与算术——每种化学品是否写明自身名称与危险性类别，储存量是否可解析，是否记录临界量，**重大危险源判定结论是否与「储存量相对于台账写明的临界量」的比较结果一致**，在库化学品是否记录安全技术说明书编号，CAS 号是否不重复，台账是否声明辨识依据，以及是否残留占位符。它**不**判定某单元是否构成重大危险源、是否必须备案登记、是否需要进行安全评估，也不判定其是否属于重大隐患。

> ### ⚠️ 标准怎么规定，以及本插件找不到的四类错误（以英文原文为准）
>
> **GB 18218—2018 已经取得并逐字阅读**（见 `rules/evidence/clause-verification-tables.md`）：**2018-11-19 发布，2019-03-01 实施**，前言写明「**本标准的全部技术内容为强制性的**」——整部标准都是强制性的——且它**取代 GB 18218—2009**（2000 年版与 2009 年版均已废止，引用它们本身就是错误的）。临界量（3.3）、单元（3.2）与重大危险源（3.4）的定义、判定规则 4.1.2，以及**表 1 的前 35 行**，都在该报告中引录。
>
> **表 1 只完整到第 35 行，表 2 本次未取得**，因此没有内置任何临界量数值，也无法核对任何数值。`HZ-003` 把储存量与**台账自身记录的**临界量相比较，并核对判定结论是否一致。因此它**找不到四类错误**，其说明也这样写明：
>
> 1. **临界量取自错误的物质或危险性类别**——4.1.2 要求：列名物质用表 1，其他物质用表 2。
> 2. **具有多种危险性的物质未被取最低临界量**——4.1.2 b)：「若一种危险化学品具有多种危险性，按其中最低的临界量确定」。台账只记一个数字，因此向上取整会漏掉重大危险源。
> 3. **多物质校正**——在同一单元内，`S = q₁/Q₁ + q₂/Q₂ + … + qₙ/Qₙ ≥ 1` 同样构成重大危险源。**本插件不进行这项求和**，因为辨识是按**生产或储存单元**（3.2、3.5、3.6）进行的，而台账列出物质时并不按单元分组。
> 4. **数量基准**——4.2.2 要求数量**按设计最大量**取，而台账可能记录的是实际库存量。
>
> ⚠️ **不要超出标准的适用范围。** 第 1 章排除**危险化学品的场外运输**（铁路、公路、水路、航空、管道）、核设施与军事设施、采矿（不含加工与储存），以及海上石油天然气开采。把本插件用于**运输**货物属于超出范围——那由危险货物运输规则管辖，而不是 GB 18218。
>
> 因此，一条发现只意味着“**你写的这两个数字与你自己的判定结论不一致**”。上述四项需要在标准下逐单元计算，那是安全评价与监管认定的任务。**每条 `excerpt` 仍写着“本次未取得”，每条规则也仍为 `warn` 或 `info`**，因为本插件核对的是台账的内部一致性，而不是某个临界量数值是否正确。

## Compatibility

| 项目 | 状态 |
|---|---|
| Harness | 对等版本范围 `>=0.1.2-rc.1 <0.2.0 \|\| >=0.2.0-0 <0.3.0` —— 已实测同时接受 `0.2.0-rc.2` 与 `0.2.1-rc.2`。**已声明 `engines.dsh`**：0.2.1 起由宿主单独裁决，范围为 `>=0.2.1-0 <0.3.0` |
| Node | `^22.19.0 || >=24.0.0` |
| 平台 | 全平台（纯 ESM；无原生代码、无联网、不调用模型） |
| 工具模式 | `native` / `ptc` 均可；批量校验整个目录时建议 `ptc`，schema 成本只付一次 |

## What it does

规则表、字段说明与行为细节见 [README.md](README.md#what-it-does)（英文主版本）。本插件只列出材料与所引条款之间的字面差异，并对无法执行的检查在 `skipped` 中逐项说明。

## Configuration

全部可调参数都在 `src/config.ts` 的 Schemastery schema 中，只改 `cordis.yml` 即可生效，无需改代码；逐条阈值在 `rules/` 下的规则库文件里。

| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `rulesFile` | string | `rules/hazchem-check.yaml` | 规则库文件路径，相对插件包根目录 |
| `disabledRules` | string[] | `[]` | 要停用的规则 id 列表；每条都会出现在 `skipped` 中 |
| `onlyRules` | string[] | `[]` | 只执行这些规则 id；留空表示执行全部规则 |
| `skipNotes` | string | `""` | 附加到每条 `skipped` 说明后的备注 |
| `timeoutMs` | number | `120000` | 工具协作式超时预算（毫秒） |

## Material format

支持 JSON 与 YAML。完整字段示例见 [README.md](README.md#material-format)（英文主版本）。字段在读取层是可选的，由检查引擎校验，因此部分导出的材料会产生"缺项"类差异，而不是让程序崩溃。

## Rule sources

规则数据与代码分离，每条规则都带文件名、文号、按原文自身编号体系的条款号、逐字摘录与来源地址。加载期强制：摘录必须是真实引文且不少于八个字符；依据仅为原则性条款（`kind: derived-from-principle`，严重级上限 `warn`）或本机构配置（`kind: institutional-configuration`，上限 `info`）的检查不得标为 `error`。夸大依据的规则库会在加载期失败，而不会产出一份看起来很有底气的报告。

核验中确认的边界与"刻意没有作出的结论"见 [README.md](README.md#rule-sources)（英文主版本）与随包的 `rules/evidence/` 目录。

## Troubleshooting

- **插件装上了但工具不出现**：确认 `main` 指向 `lib/index.mjs` 且 `pnpm run build` 已生成该文件；`main` 写错会让加载器静默跳过该条目。
- **`dsh plugin add` 报版本不兼容**：peer 范围覆盖 `0.1.x` 与 `0.2.x`；若运行时在其之外，可显式豁免：`dsh plugin --profile <name> allow-version <包名@版本> --dsh-version <runtime> --accept-risk`
- **某条规则没有执行**：查看 `skipped` 数组，其中写明了规则 id 与原因。
- **`check` 报 `manifest-peers` 失败**：静态检查器比对的是一份早于 0.2 世代的硬编码 peer 范围；安装期的 peer 校验以运行时为准。这是 `dsh-plugin-dev` 的已知上游问题。
- **时间看起来偏移**：全部计算都是对输入字符串做墙上时钟运算，不做时区换算。

## Development

```sh
pnpm install
pnpm run typecheck
pnpm test
pnpm run build
node ../scripts/sync-shared.mjs dsh-hazchem-check
```

第 4 项把 `../_shared` 的共享件同步进 `src/shared/`；每次改动共享件后都要重跑。

## PerryLink DSH Plugin Family

完整清单（62 个核查器 + 通用插件）见 [按材料选核查器](https://perrylink.github.io/zh/checkers/choose/)；本仓只是其中一个。

## License

[Apache License 2.0](LICENSE) © 2026 dsh-hazchem-check contributors.
