dsh-drill-script-check — Emergency drill script completeness and arithmetic check
DSH Market
dsh-drill-script-check reads one emergency drill script — the drill header plus one row per step — and checks that script's own completeness and arithmetic: that each step records its drill phase or its script content, that it names a commander, that the response level comes from the vocabulary you configure, that a step with a script action lists the resources it needs, that the step durations total the drill's planned duration, that a key checkpoint states its judgement condition, that no step number is repeated, and that the header names the drill and the organising unit.
What it looks like
Terminal demo of dsh-drill-script-check: real output over its DR-007 fixture
Real output from this plugin over its own DR-007 test fixture — not a mock-up. The rule pack ships no invented quotations, so a finding names both the clause it applied and the fact that the clause text was not obtained.
What it answers
| You ask | What it answers |
|---|
| A step has neither its drill phase nor its script content filled in. Is that reported? | Yes. DR-001 asks for the phase and script columns together and reports the step where neither of the two is filled — one of them is enough to pass. It checks that the column is filled, not whether the action is correct or matches your emergency plan. |
I filled in the response level, but DR-003 reports itself in skipped. Why? | DR-003 compares the level column with the vocabulary in values, which ships empty, so until you configure your own levels the rule reports that it could not run instead of passing silently. It only checks that the value is one of yours — it never judges which level an event should trigger. |
| A step that is purely informational lists no equipment. Is that flagged? | No. DR-004 asks for the resource column only when that step's script content is filled, so an informational step is not asked for equipment. It checks that the resources are listed, not that they are sufficient or that they match what is actually on site. |
| The step durations do not add up to the drill's planned duration. Will the check catch it? | Yes. DR-005 adds the durationMin values of the steps and compares that total with totalDurationMin, which it takes from the header of the material — it looks inside the row first and falls back to the header. It is an addition check only: it does not judge whether the time arrangement is reasonable or sufficient. |
| What must the checkpoint column of a step contain? | DR-006 requires the checkpoint column — the key node together with its judgement condition — to be filled on the step. It checks that something has been written there, not that the condition is observable or appropriate. |
| One phase is split over three action rows and two of them carry the same step number. | DR-007 reports the repeated stepNo, because a repeat makes the duration total and the step count unreliable. Splitting one phase into several action rows is normal — give each row its own step number. |
Standards it follows
| Document | Number | Cited by rules |
|---|
| 《生产安全事故应急演练基本规范》 | YJ/T 9007—2019(原 AQ/T 9007—2019,2025 年第 1 号公告调整代号;本次未取得条文) | DR-001, DR-002, DR-004, DR-005, DR-006, DR-007, DR-008 |
| 本单位应急预案体系(本机构配置) | 无统一标准(本条依据为本机构预案的分级口径) | DR-003 |
Boundary: this plugin checks an 应急演练脚本 for completeness and arithmetic — that each step names its
phase and script content, that it names a commander, that the response level comes from your vocabulary, that a
step with an action lists the resources it needs, that the step durations total the drill's planned duration, that
key checkpoints state their judgement condition, that step numbers are unique, and that the script names its drill
and organiser. It does not decide whether a drill was realistic or effective, whether the response level was
right, whether the actions were correct, or whether the drill met its objectives.
⚠️ Read this before trusting a citation in the report
Every excerpt in this plugin's rule pack says, in so many words, that the clause text was not
obtained. The regime lives in AQ/T 9007—2019, 《生产安全事故应急条例》(国务院令第708号) and each
institution's emergency plans. The verification pass could not retrieve verbatim clause text, so rather than
paraphrase a quotation the pack states the gap in the excerpt field itself and puts the honest reasoning in
note. Every rule is therefore warn or info, and a test asserts that no rule claims a quotation it does
not have. When the texts are in hand, replace each excerpt with the real clause and raise kind to
direct.
No response-level scale is built in. Levels differ between plan systems — general / larger / major /
especially major, or a unit's own Ⅰ–Ⅳ — so DR-003 reports itself in skipped until you configure your
vocabulary, and it never judges which level an event should trigger. That is the incident commander's call.
The resource rule fires only when a script action is present, so a step that is purely informational is not
asked for equipment. And the duration total is read from the header, where a drill's planned length normally
lives.
Compatibility
| Surface | Status |
|---|
| Harness | Peer range >=0.1.2-rc.1 <0.2.0 || >=0.2.0-0 <0.3.0 — verified to accept both 0.2.0-rc.2 and 0.2.1-alpha.1. engines.dsh is deliberately not declared: it has no reader and cannot reject a host |
| Node | `^22.19.0 |
| Platforms | All (plain ESM; no native code, no network, no model call) |
| Tool mode | Works in native, ptc and both; for a full script use ptc |
What it does
Registers the drill_script_check tool. It reads one drill script — the drill header plus one row per step —
applies a versioned rule pack, and returns a report.
| Rule | Check | Severity | Basis kind |
|---|
DR-001 | the phase and script content are recorded | warn | principle |
DR-002 | a commander is named | warn | principle |
DR-003 | the response level comes from your vocabulary (off by default) | info | local |
DR-004 | a step with an action lists its resources | warn | principle |
DR-005 | step durations total the planned duration | warn | principle |
DR-006 | a checkpoint states its judgement condition | warn | principle |
DR-007 | step numbers are unique | warn | principle |
DR-008 | the script names its drill and organiser | warn | principle |
Install
dsh plugin --profile <name> add dsh-drill-script-check
dsh --profile <name> --dump-config | grep 'dsh-drill-script-check'
Configuration
| Key | Type | Default | Description |
|---|
rulesFile | string | rules/drill-script-check.yaml | Rule-pack path, relative to the package root |
disabledRules | string[] | [] | Rule ids to stop running; each appears in skipped |
onlyRules | string[] | [] | Run only these rule ids; empty runs every rule |
skipNotes | string | "" | Note appended to every skipped reason |
timeoutMs | number | 120000 | Cooperative tool timeout budget |
Rule-level parameters worth knowing:
DR-003 values — your response levels, e.g. [Ⅰ级, Ⅱ级, Ⅲ级, Ⅳ级]. Empty means no check.
DR-005 field / headerField / tolerance — the duration column and the header total it must match.
DR-004 conditionField / requiredFields — what triggers the resource requirement.
Material format
The tool accepts JSON or YAML:
drillName: 某某装置泄漏事故应急演练
drillType: 综合演练
organizer: 某某公司应急管理部
plannedAt: 2026-06-10
totalDurationMin: '15'
rows:
- { 序号: '1', 演练阶段: 预警与信息报告,
脚本内容: 值班员发现泄漏报警,电话报告应急指挥部,
指挥人: 张指挥, 参演人员: 值班员、调度员,
所需资源: 对讲机 4 台、气体检测仪 2 台, 计划时长: '15',
响应级别: Ⅲ级, 关键节点: 指挥部确认接报并启动响应(判定条件:指挥人下达启动指令) }
Column names are matched case-insensitively and ignoring spaces, underscores and hyphens; the script's own column
names are kept, so a finding names the column it read. The duration total may live in the header.
Rule sources
Rule data lives in rules/drill-script-check.yaml. The pack's header states the citation gap in full, and each
rule's note repeats the part that matters for that rule. The load-time guard that normally enforces "an excerpt
must be a real quotation of at least eight characters" cannot tell a quotation from a description — so this pack
leans on the header, the per-rule notes and a test that asserts every excerpt admits the gap.
Troubleshooting
DR-003 never runs. Its vocabulary is empty; fill it with the levels your emergency plans use.
DR-005 reports itself as skipped. The header carries no planned duration, or no step records one.
DR-005 fires although the script looks right. The step durations disagree with the header total — usually
a missing step or a mistyped figure.
DR-004 fires on a step I consider informational. The step has script content, so the rule wants its
resources named. If the step genuinely needs none, say so in the cell rather than leaving it blank.
DR-007 fires on two steps of one phase. Give each step its own number.
- The plugin installs but the tool never appears. Check that
main resolves to lib/index.mjs and
that pnpm run build produced it; a wrong main makes the loader skip the entry silently.
dsh plugin add refuses the package as incompatible. The peer range covers 0.1.x and 0.2.x; if
your runtime sits outside it, grant an explicit exemption:
dsh plugin --profile <name> allow-version dsh-drill-script-check@0.1.0 --dsh-version <runtime> --accept-risk
check reports manifest-peers as failed. The static checker compares against a hard-coded peer
range that predates the 0.2 line. The runtime enforces peer compatibility at install time, so the
declared range is the correct one; this is a known upstream issue in dsh-plugin-dev.
Development
pnpm install
pnpm run typecheck # tsc --noEmit
pnpm test # vitest, the shared table-plugin suite plus paired fixtures
pnpm run build # tsdown -> lib/index.mjs + lib/index.d.mts
node ../scripts/sync-shared.mjs dsh-drill-script-check # refresh src/shared from ../_shared
The plugin is data-only: src/model.ts declares the table shape, the shared kit supplies the reader and the
check engine, and the rule pack declares every check.
License
Apache License 2.0 © 2026 dsh-drill-script-check contributors.