Skip to content

About

DeepSeek Harness 插件 — 招标文件实质性要求核对:依据《中华人民共和国招标投标法》(1999年8月30日通过,2017年12月27日修正)。仅提示差异,不作出定性结论。

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dsh-tender-extract — Tender document clause-extract table check (source and raw text)

English · 简体中文 · Español · Português · हिन्दी

DSH Market dshfind

dsh-tender-extract reads one clause-extract table — the package header plus one row per extract — applies a versioned rule pack and returns a report on that table alone: that every row gives its source (sourceRef), that the raw clause text column (rawText) is filled in, that the distilled requirement (requirement) shares at least some terms with that raw text, that a recorded category is on your institution's list, that no extract number (seq) is repeated, that the header names the project and the source document, and that no template placeholder survives in the raw text. The clause-category vocabulary ships empty, and with nothing configured TE-004 reports itself in skipped instead of passing quietly.

Install

dsh plugin --profile <name> add dsh-tender-extract
dsh --profile <name> --dump-config | grep 'dsh-tender-extract'

What it looks like

Workflow diagram for dsh-tender-extract: call → plugin → result.

Workflow overview: call → plugin → result. The examples below use the real command surface.

What it answers

Examples

The table below is the example set: the first row is the detailed walkthrough, the remaining rows are short cases.

Detailed output

Tool tender_extract

Input

{"rows":[{"原文":"甲乙丙丁戊己庚辛","要求":"一二三四五六七八"}]}

Output

{
  "id": "dsh-tender-extract.TE-003.de09b5a6",
  "ruleId": "TE-003",
  "severity": "warn",
  "locator": {
    "row": 1,
    "field": "requirement"
  },
  "found": "第 1 行「requirement」与「rawText」没有共同词(共同词 0 个,配置下限 2 个)",
  "expected": "「requirement」应与「rawText」在字面上相关",
  "fix": "本条只提示两栏看不出关系、值得人工复核,不断言提炼有误;同义改写会拉低共同词数,可调整 minShared"
}

Observed from dsh-tender-extract/tests/fixtures/TE-003/TE-003-unsafe.json

You ask What it answers
One extract in my table has nothing in the source column. Is that reported? Yes. TE-001 requires sourceRef on every extract and reports each row where it is blank. It checks that the source is recorded, never that it points to the right place, and it does not prove that an extract is missing — completeness can only be judged against the whole tender document, which this plugin never sees.
The raw text column is filled in — does the plugin confirm it matches the tender document word for word? TE-002 only checks that the rawText column is filled. It does not compare that text against the tender document; that comparison needs the document itself in hand.
The distilled requirement looks as if it came from somewhere else entirely. Will that be flagged? TE-003 looks for shared terms between requirement and rawText — overlapping Han bigrams and whole Latin words — and reports the row when the two share nothing. Paraphrase legitimately changes wording, so a finding means the two columns look unrelated and are worth a human look, never that the distillation is wrong. It also cannot catch a distillation that is wrong while sharing vocabulary, and the minShared floor of 2 is a local convention, not a standard figure.
We have not decided how to classify our clauses yet. What happens to the category column? Its values ship empty, so TE-004 reports itself in skipped rather than passing quietly until you fill them in. Once configured it checks only that the recorded value is on your list; it does not decide which category a clause belongs to.
Two extracts in the table carry the same number. TE-005 compares the seq values ignoring whitespace differences and reports the repeat, because a number that appears twice cannot be cited unambiguously. It does not judge whether the numbering is otherwise sensible.
The raw text of one extract is still the template wording. TE-007 reports a row whose rawText still contains a placeholder from the factory list — 【, 】, {{, }}, XXX, xxx, 待填, 待补充, TBD, todo, 示例 — because an extract still carrying one was copied from the template rather than filled in. The list deliberately excludes (略), a legitimate way to abridge a long clause, and it can only find the words on that list.

Standards it follows

Document Number Cited by rules
《中华人民共和国招标投标法》 1999年8月30日通过,2017年12月27日修正(全国人大常委会《关于修改〈中华人民共和国招标投标法〉、〈中华人民共和国计量法〉的决定》),本法自2000年1月1日起施行 TE-001, TE-002, TE-003, TE-004, TE-005, TE-006, TE-007

Boundary: this plugin checks a 招标文件条款摘录表 for what a checklist can be held to — that every extract gives its source, that the raw clause text is recorded, that the distilled requirement bears some lexical relation to that text, that the category comes from your vocabulary, that numbers are unique, and that no placeholder survives.

⚠️ What this plugin can and cannot do

It cannot prove that a clause was missed. Deciding whether an extract is complete requires comparing against the whole tender document, and this plugin only ever sees the extract table. It does not claim otherwise, and its rule notes say so: TE-001 checks that a source is recorded, never that the extract is exhaustive.

TE-003 is the only content judgement here, and it is deliberately weak. It looks for shared terms between the raw text and the distilled requirement, using overlapping Han bigrams and whole Latin words, and reports only when the two share nothing. Paraphrase legitimately changes wording, so a finding means "these two columns look unrelated, worth a human look" and never "the distillation is wrong". It also cannot catch a distillation that is wrong while sharing vocabulary — that limit is stated in the rule's own note and in its README entry.

The rule pack states its citation status rule by rule. 1 of its 7 rules quote verbatim clause text and are marked direct; the remaining 6 state in the excerpt field itself that the text was not obtained, and stay at warn or info. Where a rule still carries that note, treat it as a lead rather than as a citation. The regime lives in 《中华人民共和国招标投标法》and its implementing regulations. For the rules whose text the verification pass could not retrieve, the pack states the gap in the excerpt field itself rather than paraphrasing it, and those rules stay at warn or info. When the texts are in hand, replace each excerpt with the real clause and raise kind to direct. The clause-category vocabulary ships empty; with nothing configured, TE-004 reports itself in skipped rather than passing quietly.

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-rc.2. engines.dsh is declared as >=0.2.1-0 <0.3.0 and is enforced by the host since 0.2.1
Node `^22.19.0
Platforms All (plain ESM; no native code, no network, no model call)
Tool mode Works in native and ptc; for a whole document use ptc

What it does

Registers the tender_extract tool. It reads one clause-extract table — the package header plus one row per extract — applies a versioned rule pack, and returns a report.

Rule Check Severity Basis kind
TE-001 every extract gives its source warn principle
TE-002 every extract records the raw text warn principle
TE-003 the requirement shares terms with the raw text warn direct
TE-004 the category comes from your vocabulary (off by default) info local
TE-005 extract numbers are unique warn principle
TE-006 the table names its project and source document warn principle
TE-007 the raw text holds no unreplaced placeholder warn principle

Configuration

Key Type Default Description
rulesFile string rules/tender-extract.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:

  • TE-003 leftField / rightField / minShared — the two columns and the shared-term floor, 2 by default. Set it to 1 to be more permissive; the floor is a local convention, not a standard figure.
  • TE-004 values — your clause categories, e.g. [资格条件, 技术规格, 商务条款, 评标办法, 合同条款]. Empty means no check.
  • TE-007 terms — the placeholders to look for. 「略」 is deliberately absent: ……(略) is a normal and legitimate way to abridge a long clause, so it is not treated as a placeholder.

Material format

The tool accepts JSON or YAML:

project: 某某工程施工招标
tenderNo: ZB-2026-018
source: 招标文件 2026-02-10 版
rows:
  - { 序号: '1', 出处: 第三章 第 3.2 条,
      原文: 投标人应具有建筑工程施工总承包二级及以上资质,并附资质证书复印件。,
      类别: 资格条件, 要求: 需具备建筑工程施工总承包二级及以上资质并提供证书复印件,
      是否实质性: 是, 响应: 需响应, 责任部门: 经营部 }

Column names are matched case-insensitively and ignoring spaces, underscores and hyphens; the table's own column names are kept, so a finding names the column it read.

Rule sources

Rule data lives in rules/tender-extract.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

  • TE-003 fires on a distillation I am happy with. The two columns share no terms — usually because the requirement was reworded into different vocabulary. Raise minShared to 1, or disable the rule.
  • TE-003 does not catch a distillation I know is wrong. It cannot: the columns share vocabulary. This is the documented limit of a lexical check.
  • TE-007 does not fire on (略). That is deliberate; add 「略」 to terms if your template really uses it to stand in for a whole clause.
  • TE-004 never runs. Its vocabulary is empty; fill it with your register's categories.
  • 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-tender-extract@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-tender-extract   # 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.

PerryLink DSH Plugin Family

This project is part of the DeepSeek Harness plugin family from PerryLink. The roster stays collapsed below so every README keeps a short first screen; expand it to see every row and its status.

Expand all plugins
Plugin Status
dsh-aqua-input-check
dsh-archive-check
dsh-auto-review
dsh-autotier
dsh-bid-ca-precheck
dsh-bid-qual-check
dsh-cert-mcp
dsh-checkpoint-rewind
dsh-click
dsh-composer-history
dsh-contract-stance
dsh-customs-doc-check
dsh-data-quality
dsh-demurrage-ledger
dsh-doublecheck
dsh-drill-script-check
dsh-eia-guide-check
dsh-emergency-plan
dsh-essay-rubric-check
dsh-evidence-check
dsh-export-ctl-check
dsh-fast
dsh-fmea-table-check
dsh-forecast-penalty
dsh-fund-research
dsh-github
dsh-gongwen-flow-check
dsh-gongwen-word-check
dsh-guard-plan-qc
dsh-hazchem-check
dsh-hazplan-check
dsh-hidden-risk-map
dsh-hs-classify
dsh-icd-rule-check
dsh-industry-research
dsh-lawcite-adapter
dsh-laya
dsh-lc-doc-check
dsh-learning-gap-check
dsh-library
dsh-local-ai
dsh-lsp-actions
dsh-mask
dsh-mcp-panel
dsh-medrec-qc
dsh-memento
dsh-nsfc-form-check
dsh-nurse-record-check
dsh-observe
dsh-origin-rvc-check
dsh-ota-review-check
dsh-output-styles
dsh-paper-doc-adapter
dsh-permission-rules
dsh-permit-report-check
dsh-pipeline-check
dsh-pleading-draft
dsh-plugin-doctor
dsh-plugin-guide
dsh-plugin-kit
dsh-plugin-upgrade
dsh-policy-brief-draft
dsh-power-loss-split
dsh-power-ticket-check
dsh-ppap-check
dsh-protest-deadline
dsh-railway-window
dsh-repair-order-qc
dsh-research-report
dsh-review-reply-check
dsh-rulefile-check
dsh-safety-brief-check
dsh-score
dsh-session-sync
dsh-site-log-check
dsh-skill-pack-security
dsh-soe-decision-check
dsh-soilwater-check
dsh-sop-sync-check
dsh-spc-gbt-adapter
dsh-talk
dsh-tender-extract
dsh-tender-matrix
dsh-test-drive
dsh-ticktick
dsh-translate
dsh-warranty-calc
dsh-budget 🧊 FROZEN — see the repo README
dsh-claude-move 🧊 FROZEN — see the repo README
dsh-defend 🧊 FROZEN — see the repo README
dsh-draw 🧊 FROZEN — see the repo README
dsh-reach 🧊 FROZEN — see the repo README
dsh-background-agents 🚫 RETIRED — see the repo README
dsh-session-pin 🚫 RETIRED — see the repo README
dsh-team-rooms 🚫 RETIRED — see the repo README

License

Apache License 2.0 © 2026 dsh-tender-extract contributors.

About

DeepSeek Harness 插件 — 招标文件实质性要求核对:依据《中华人民共和国招标投标法》(1999年8月30日通过,2017年12月27日修正)。仅提示差异,不作出定性结论。

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages