Bundle
dsh-drill-script-check
应急演练脚本核对(按阶段、响应分级、指挥与资源要素核对脚本齐备,仅提示差异,不作出定性结论)
- Source
- PerryLink
- License
- Apache-2.0
- Updated
- Updated 7 days ago
Readme
# dsh-drill-script-check — Emergency drill script completeness and arithmetic check
[](https://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

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 || >=24.0.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
```sh
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:
```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
```sh
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](LICENSE) © 2026 dsh-drill-script-check contributors.
Install
dsh plugin --profile web add github:PerryLink/dsh-drill-script-check
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-drill-script-check from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.