dsh-dd-forge
Due-diligence document review for DeepSeek Harness: opcore deterministic engine (documents -> rule packs -> risk report) plus review/report-writing agent skills. Rules are data (YAML), not code. 适合需要对企业合规、合同等文档进行规则化审查并输出风险报告的法务任务。
설치
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:McBonB/dsh-dd-forgedsh-dd-forge — due-diligence document review (DeepSeek Harness plugin)
English | 中文
Documents → rule packs → risk report: feed the deterministic engine a due-diligence folder (registry / equity / financials / contracts / charters / employment contracts) and get a sourced risk report. Built for DeepSeek Harness (dsh); the engine (opcore) itself has zero dsh dependencies and runs standalone.
┌──────────────────────────────────────────────────┐
│ dsh session (model + judgement) │
│ skills: dsh-dd-forge-review / -report │ ← judgement layer (prompt skills)
│ tools: dd_review / dd_rules │ ← deterministic layer (registered tools)
├──────────────────────────────────────────────────┤
│ opcore engine (engine/, zero dsh deps) │
│ loader (docs → facts) → rule execution → report │
├──────────────────────────────────────────────────┤
│ packs/ (YAML rule packs — data, not code) │
│ general-company 12 · contract-basics 8 │
│ trade-contract 8 · trade-bulk 10 │
│ logistics 8 · labour 8 · credit-financials 8 │
│ guarantee 5 · corporate-charter 5 │
└──────────────────────────────────────────────────┘
Install
dsh plugin --profile add dsh-dd-forge
Local development: dsh plugin --profile add /path/to/dsh-dd-forge — pnpm link: installs do not auto-install dependencies, so run npm install in this directory first.
Use
In a dsh session, hand a target folder to the model ("run a due-diligence review on ./target-company"), or call the tools directly:
dd_review— run all rule packs over a folder (thepacksparameter optionally narrows to a pack subset); returns findings and writes the report into the workspace (reportPathoverrides the report location); theformatparameter selectsmd/docx/xlsx(comma-separated, defaultmd); the top-up loop parameters aresaveRun(serialize this run into a re-runnable review.json snapshot) andbaseline(diff against a previous snapshot — see "Top-up re-run loop"); pass atargetsarray to review several folders in one call (see "Batch review")dd_rules— list packs and every rule with severity, category, and public reference
Skills: dsh-dd-forge-review (folder conventions + verification discipline for high findings), dsh-dd-forge-report (writing the full DD report on top of engine output).
Batch review (several folders)
To review several subjects in one session, dd_review takes a targets array (mutually exclusive with target): targets=["./companyA","./companyB"]. Each folder gets its own report set (exported per format as /dd-review-report-.; the folder name when no registry document names the subject; duplicates get -2/-3 suffixes), plus one summary index at /dd-review-index.md (indexPath overrides the location): a per-subject conclusion/stats table, a cross-subject high-severity quick view, totals, and relative links to every report — closed by the same disclaimer.
Every folder is validated up front (one inaccessible folder fails the whole call — no half delivery). reportPath / saveRun / baseline are single-run parameters and are rejected with targets — to take one folder through the top-up loop, call the tool with target for it alone.
Folder conventions
The engine recognizes documents by filename patterns; anything missing simply leaves the corresponding rules as missing_data:
| Document | File | Format |
|---|---|---|
| Registry | 工商信息.json (or any json matching 工商/registry) | Chinese or English keys; capital in 万元 |
| Equity | *股权*.csv or .xlsx (filename/sheet matching 股权/股东) | header: 股东,认缴出资(万元),实缴出资(万元),持股比例(%),备注 |
| Financials | *资产负债*.csv, *利润*.csv, *现金流量*.csv (or same-named xlsx sheets) | accounts as rows, years as columns (科目,2024,2023), 万元 |
| Contracts | contracts/*.md / .txt / .docx | one contract per file; optional frontmatter: 标题, 签订日期 |
| Charter | any 章程-matching .md / .txt / .docx | extracts company name, registered capital, shareholder rows, mandatory items, share-transfer clause |
| Employment contract | any .md / .txt / .docx whose filename contains 「劳动合同」 or whose body contains 「劳动合同期限」 | extracts contract term, probation months and its statutory tiered cap, probation/agreed salary, non-compete term and compensation, service period with training cost and penalty, mandatory items and rules-policy wording |
docx (contracts/charters) and xlsx (financials/equity) are parsed natively (mammoth/exceljs, lazily loaded — zero cost when absent). Only scans/images need in-session conversion first.
The loader also extracts clause facts from contract bodies for the specialized packs: deposit amount and ratio ("定金…N 元"), advance amount and ratio (amount form "预付款 N 元" or percent form "预付 N%", feeding the bulk-trade pack), payment term days ("N 日内付清/支付" — deadlines that pay a deposit/advance do not count; read by both the trade and logistics packs), daily penalty rate ("万分之X/日", auto-annualized), trade-contract classification (购销/买卖/采购/销售/供货/大宗商品/贸易 — bulk-trade rules report 不适用 on non-trade contracts), logistics-contract classification (货物运输/运输服务/承运/仓储/配送 — logistics rules report 不适用 on non-logistics contracts; a counterparty named 「物流」 does not classify a contract), plus 36 clause-presence probes (risk transfer, force majeure, notice, acceptance, exclusivity, third-party inspection, price adjustment/点价, deposit-vs-penalty election, documents of title, auto-renewal, performance bond, settlement & invoicing, foreign-related & dispute institution, cargo damage liability, insured/declared-value carriage, loading duties, subcontracting restrictions, POD & reconciliation, cargo claims, vehicle & driver qualifications, …).
Employment contracts are parsed as their own document type (they never enter the commercial-contract candidate set): contract term in years (date form 「劳动合同期限自 X 起至 Y 止」 first, stated years as fallback; open-ended contracts detected separately), probation months with the statutory tiered cap (Labour Contract Law art. 19 tiers: = 财务/资产负债表.csv L3:「流动资产合计,1330,1180」 > 财务/资产负债表.csv L8:「流动负债合计,1650,1420」
## Delivery formats (md / docx / xlsx)
One review exports to three formats sharing one report number and one disclaimer (number = `OPC--`; the same inputs re-exported the same day keep the number, so the files of one delivery cite each other):
- **md** (default) — the session-friendly anchor format shown above
- **docx** (`docx` npm package, MIT, pure JS) — delivery Word document: cover (company / report number / date / engine version / disclaimer summary), table of contents (a static outline — no field-update prompt in Word/WPS/Pages), overall conclusion, risk summary table (severity / id / risk / location / reference), per-finding detail with evidence quotes, passes & data gaps, and a signature block (审查 / 复核 / 签发日期, left blank) closed by the full disclaimer
- **xlsx** (exceljs) — three-sheet risk register: `风险明细` (one row per finding: id / severity / risk / location / message / evidence / remediation / reference, severity colouring, report-number + disclaimer footer), `数据缺失清单` (rules awaiting inputs and exactly which inputs; an explicit none-row when clean), `规则清单` (every loaded rule with its public reference — what was checked, against what)
CLI: `--format md,docx,xlsx` (comma-separated multi-select; `-o` names the report base, each format gets its extension; without `-o` the default is `dd-review-report.`). The `dd_review` tool takes a `format` parameter that passes through to the engine exporters (report paths swap extensions per format; the tool returns a `reportPaths` array).
```bash
node engine/cli.js review fixtures/demo-company -o report --format md,docx,xlsx
# → report.md / report.docx / report.xlsx
npm test includes roundtrip checks: mammoth reads the generated docx back and asserts cover/TOC/summary-table/evidence/signature-block content; exceljs reads the xlsx back and asserts the three sheets and row counts (45 findings, 72 rules, the data-gap list).
Top-up re-run loop (two-round diff)
Due diligence is multi-round. The engine serializes each run into a re-runnable snapshot and diffs the re-run against it:
# round 1: review and save the run snapshot (findings / missingData / stats)
node engine/cli.js review --save-run review.json
# …client tops up documents per the report's data-gap table (keep file names stable)…
# round 2: re-run the current folder against the old snapshot
node engine/cli.js diff review.json # three-way classification + closure rate
node engine/cli.js diff review.json --json # machine-readable
node engine/cli.js diff review.json -o report.md # report embeds the 与上轮对比 section
node engine/cli.js review --baseline review.json # or: review takes the baseline directly
- Matching key: a finding is
ruleId@file(ruleId@casewithout a document scope); re-rendered numbers do not change its classification. A renamed document shows up as resolved+新增, not as a match. - Three-way classification: 消除 (old run, gone — resolved or withdrawn) / 新增 (new this round — verify each one) / 残留 (both rounds — escalate or explicitly accept).
- Missing-data closure rate = previous gaps decidable this round / previous gaps. A closed gap may become a pass or a finding (the data arrived and tripped the rule) — the latter also appears under 新增.
- Reports: with a baseline, md/docx render a 「与上轮对比(补料复跑)」 subsection under the overall conclusion (previous/current stats, the classification table, closure rate) and tag new findings 「— 本轮新增」 in the detail walk; xlsx appends a fourth sheet 与上轮对比 (row-per resolved/added, remaining aggregate, gap list, closure-rate line). Without a baseline all three formats are unchanged.
- Tool: the
dd_reviewparameters aresaveRun(write the snapshot) andbaseline(diff and render); the return value carriescomparison.
Standalone (without dsh)
node engine/cli.js review [-o report.md] [--json] [--format md,docx,xlsx] [--save-run review.json] [--baseline review.json]
node engine/cli.js diff [folder] [--json] [-o report.md] [--save-run review.json] [--format md,docx,xlsx]
node engine/cli.js rules
node engine/cli.js review --packs
Batching several folders (targets) is a dsh tool-side capability; with the CLI, loop review over the folders.
Engine API: import { runReview, loadPacks, renderReport, renderBatchIndex, renderDocxReport, renderXlsxReport, snapshotFromResult, readSnapshot, diffRuns } from 'dsh-dd-forge/opcore' (docx/xlsx renderers load lazily — nothing is paid unless that format i