dsh-progress-payment 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,99 @@
1
1
  {
2
2
  "name": "dsh-progress-payment",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Audit construction progress-payment declarations against the contract baseline and export a review worksheet; amounts in integer cents.",
5
+ "type": "module",
6
+ "main": "./lib/plugin/index.js",
7
+ "types": "./lib/plugin/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/plugin/index.d.ts",
11
+ "default": "./lib/plugin/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "lib",
16
+ "cordis.patch.yml",
17
+ "README.md",
18
+ "README-zh.md",
19
+ "README-es.md",
20
+ "README-pt.md",
21
+ "README-hi.md",
22
+ "TROUBLESHOOTING.md",
23
+ "screenshots.json",
24
+ "samples",
25
+ "docs/assets",
26
+ "icon.svg"
27
+ ],
28
+ "dsh": {
29
+ "bundle": {
30
+ "patch": "./cordis.patch.yml"
31
+ },
32
+ "demo": {
33
+ "sample": "samples/quickstart/input/declaration-2026-10.csv",
34
+ "prompt": "帮我审一下这期进度款申报,按合同基准核对超量和单价,把问题清单导成底稿。",
35
+ "expect": "samples/quickstart/expected/result.json",
36
+ "screenshot": "docs/assets/quickstart.png",
37
+ "reads": [
38
+ "用户指定的进度款申报 CSV 与合同基准 CSV(样例:samples/quickstart/input/)"
39
+ ],
40
+ "writes": [
41
+ "$DSH_HOME/dsh-progress-payment/exports/"
42
+ ],
43
+ "network": false,
44
+ "external": []
45
+ }
46
+ },
47
+ "engines": {
48
+ "dsh": ">=0.2.1-rc.3 <0.4.0",
49
+ "node": ">=24.9.0 <25"
50
+ },
51
+ "packageManager": "pnpm@11.28.5",
52
+ "scripts": {
53
+ "build": "tsc -p tsconfig.json",
54
+ "lint": "node scripts/lint.mjs",
55
+ "typecheck": "tsc -p tsconfig.json --noEmit",
56
+ "test": "pnpm build && node --test test/*.test.mjs",
57
+ "gate": "node scripts/gate.mjs",
58
+ "acceptance": "node scripts/acceptance.mjs",
59
+ "quickstart": "node samples/quickstart/run.mjs --check",
60
+ "prepublishOnly": "npm run build && node scripts/lint.mjs && node scripts/gate.mjs"
61
+ },
62
+ "keywords": [
63
+ "deepseek-harness",
64
+ "dsh",
65
+ "dsh-plugin",
66
+ "progress-payment",
67
+ "construction",
68
+ "quantity-surveying",
69
+ "csv",
70
+ "perrylink"
71
+ ],
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "git+https://github.com/PerryLink/dsh-progress-payment.git"
75
+ },
76
+ "homepage": "https://perrylink.github.io/dsh-plugins/packages/dsh-progress-payment.html",
77
+ "bugs": {
78
+ "url": "https://github.com/PerryLink/dsh-progress-payment/issues"
79
+ },
80
+ "license": "Apache-2.0",
81
+ "publishConfig": {
82
+ "access": "public"
83
+ },
84
+ "peerDependencies": {
85
+ "@deepseek-ai/cordis": ">=4.0.5 <5.0.0",
86
+ "@deepseek-ai/dsh-tools": ">=0.2.1-rc.3 <0.4.0"
87
+ },
88
+ "devDependencies": {
89
+ "@deepseek-ai/cordis": "4.0.5",
90
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.3",
91
+ "@types/node": "^24.0.0",
92
+ "typescript": "7.0.2"
93
+ },
94
+ "peerDependenciesMeta": {
95
+ "@deepseek-ai/dsh-tools": {
96
+ "optional": true
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,206 @@
1
+ {
2
+ "_note": "Real tool output. The export path is normalised to exports/<file>.csv (the run directory is a temp dir); everything else is verbatim. Amounts are integer cents.",
3
+ "sample": {
4
+ "declaration": {
5
+ "path": "samples/quickstart/input/declaration-2026-10.csv",
6
+ "bytes": 412,
7
+ "sha256": "b74c68756bbd882b7b627194d772df672155d84fa7d1028182598dfa10afa2c0"
8
+ },
9
+ "contract": {
10
+ "path": "samples/quickstart/input/contract-baseline.csv",
11
+ "bytes": 159,
12
+ "sha256": "dc42b8123b3a68aa63a2be29226f73d22c614974538513bd896af53a12c1e4d3"
13
+ }
14
+ },
15
+ "ingest": {
16
+ "batch_id": "pg_ea0edb1548cb530b",
17
+ "rows": 7,
18
+ "items": 6,
19
+ "contract_items": 6,
20
+ "declaration_sha256": "b74c68756bbd882b7b627194d772df672155d84fa7d1028182598dfa10afa2c0",
21
+ "contract_sha256": "dc42b8123b3a68aa63a2be29226f73d22c614974538513bd896af53a12c1e4d3"
22
+ },
23
+ "audit": {
24
+ "batch_id": "pg_ea0edb1548cb530b",
25
+ "currency": "CNY",
26
+ "items": [
27
+ {
28
+ "row": 1,
29
+ "item_code": "010101001",
30
+ "item_name": "平整场地",
31
+ "unit": "m2",
32
+ "declared_contract_qty": 1200,
33
+ "declared_contract_unit_price_cents": 350,
34
+ "contract_qty": 1200,
35
+ "contract_unit_price_cents": 350,
36
+ "period_qty": 300,
37
+ "cumulative_qty": 900,
38
+ "period_amount_cents": 105000,
39
+ "declared_period_amount_cents": 105000,
40
+ "cumulative_amount_cents": 315000,
41
+ "contract_amount_cents": 420000,
42
+ "cumulative_ratio_pct": 75,
43
+ "issue_codes": []
44
+ },
45
+ {
46
+ "row": 2,
47
+ "item_code": "010101003",
48
+ "item_name": "挖沟槽土方",
49
+ "unit": "m3",
50
+ "declared_contract_qty": 850,
51
+ "declared_contract_unit_price_cents": 2800,
52
+ "contract_qty": 850,
53
+ "contract_unit_price_cents": 2800,
54
+ "period_qty": 120,
55
+ "cumulative_qty": 520,
56
+ "period_amount_cents": 336000,
57
+ "declared_period_amount_cents": 336000,
58
+ "cumulative_amount_cents": 1456000,
59
+ "contract_amount_cents": 2380000,
60
+ "cumulative_ratio_pct": 61.18,
61
+ "issue_codes": []
62
+ },
63
+ {
64
+ "row": 3,
65
+ "item_code": "010401001",
66
+ "item_name": "混凝土基础",
67
+ "unit": "m3",
68
+ "declared_contract_qty": 260,
69
+ "declared_contract_unit_price_cents": 48000,
70
+ "contract_qty": 260,
71
+ "contract_unit_price_cents": 48000,
72
+ "period_qty": 25.92,
73
+ "cumulative_qty": 240.5,
74
+ "period_amount_cents": 1244160,
75
+ "declared_period_amount_cents": 1244160,
76
+ "cumulative_amount_cents": 11544000,
77
+ "contract_amount_cents": 12480000,
78
+ "cumulative_ratio_pct": 92.5,
79
+ "issue_codes": []
80
+ },
81
+ {
82
+ "row": 4,
83
+ "item_code": "010402001",
84
+ "item_name": "矩形柱",
85
+ "unit": "m3",
86
+ "declared_contract_qty": 95,
87
+ "declared_contract_unit_price_cents": 61000,
88
+ "contract_qty": 95,
89
+ "contract_unit_price_cents": 61000,
90
+ "period_qty": 12,
91
+ "cumulative_qty": 101.5,
92
+ "period_amount_cents": 732000,
93
+ "declared_period_amount_cents": 732000,
94
+ "cumulative_amount_cents": 6191500,
95
+ "contract_amount_cents": 5795000,
96
+ "cumulative_ratio_pct": 106.84,
97
+ "issue_codes": [
98
+ "E_PROGRESS_OVER_QTY"
99
+ ]
100
+ },
101
+ {
102
+ "row": 5,
103
+ "item_code": "010515001",
104
+ "item_name": "现浇构件钢筋",
105
+ "unit": "t",
106
+ "declared_contract_qty": 80,
107
+ "declared_contract_unit_price_cents": 520000,
108
+ "contract_qty": 80,
109
+ "contract_unit_price_cents": 520000,
110
+ "period_qty": 4.2,
111
+ "cumulative_qty": 62.4,
112
+ "period_amount_cents": 2184000,
113
+ "declared_period_amount_cents": 2184000,
114
+ "cumulative_amount_cents": 32448000,
115
+ "contract_amount_cents": 41600000,
116
+ "cumulative_ratio_pct": 78,
117
+ "issue_codes": []
118
+ },
119
+ {
120
+ "row": 6,
121
+ "item_code": "011702001",
122
+ "item_name": "基础模板",
123
+ "unit": "m2",
124
+ "declared_contract_qty": 1800,
125
+ "declared_contract_unit_price_cents": 6500,
126
+ "contract_qty": 1800,
127
+ "contract_unit_price_cents": 5500,
128
+ "period_qty": 86.4,
129
+ "cumulative_qty": 1720,
130
+ "period_amount_cents": 475200,
131
+ "declared_period_amount_cents": 561600,
132
+ "cumulative_amount_cents": 9460000,
133
+ "contract_amount_cents": 9900000,
134
+ "cumulative_ratio_pct": 95.56,
135
+ "issue_codes": [
136
+ "E_PROGRESS_PRICE_MISMATCH"
137
+ ]
138
+ }
139
+ ],
140
+ "issues": [
141
+ {
142
+ "row": 4,
143
+ "item_code": "010402001",
144
+ "item_name": "矩形柱",
145
+ "code": "E_PROGRESS_OVER_QTY",
146
+ "kind": "cumulative_over_contract",
147
+ "field": "cumulative_qty",
148
+ "message": "累计完成量 101.5 超过合同量 95(E_PROGRESS_OVER_QTY)|下一步:核对合同量和变更签证;超量部分走变更或结算,不在本期支付",
149
+ "blocking": true
150
+ },
151
+ {
152
+ "row": 6,
153
+ "item_code": "011702001",
154
+ "item_name": "基础模板",
155
+ "code": "E_PROGRESS_PRICE_MISMATCH",
156
+ "kind": "price_mismatch",
157
+ "field": "contract_unit_price",
158
+ "message": "申报合同单价 65.00 与合同基准 55.00 不符(E_PROGRESS_PRICE_MISMATCH)|下一步:本期金额按合同单价 55.00 重算,并要求申报方改正",
159
+ "blocking": true
160
+ },
161
+ {
162
+ "row": 7,
163
+ "item_code": "010101003",
164
+ "item_name": "挖沟槽土方",
165
+ "code": "E_PROGRESS_DUP_ITEM",
166
+ "kind": "duplicate_item",
167
+ "field": "item_code",
168
+ "message": "清单编码 010101003 在本期申报里出现 2 次(行 2、7)(E_PROGRESS_DUP_ITEM)|下一步:确认哪一行是本期应报的;重复行不计入本期金额",
169
+ "blocking": true
170
+ }
171
+ ],
172
+ "summary": {
173
+ "items": 6,
174
+ "rows": 7,
175
+ "duplicate_rows": 1,
176
+ "contract_items": 6,
177
+ "period_amount_cents": 5076360,
178
+ "declared_period_amount_cents": 5162760,
179
+ "price_adjustment_cents": -86400,
180
+ "cumulative_amount_cents": 61414500,
181
+ "contract_amount_cents": 72575000,
182
+ "cumulative_ratio_pct": 84.62,
183
+ "issues": 3,
184
+ "blocking_issues": 3,
185
+ "over_qty": 1,
186
+ "price_mismatch": 1,
187
+ "duplicate_items": 1,
188
+ "contract_missing": 0,
189
+ "contract_mismatch": 0,
190
+ "qty_inconsistent": 0,
191
+ "status": "needs_review"
192
+ }
193
+ },
194
+ "export": {
195
+ "path": "exports/progress-audit-2026-10.csv",
196
+ "sha256": "24cca857d661d882968ffe16e05773636c6b669bbdd48c577fe416cc84b45e18",
197
+ "rows": 8,
198
+ "bytes": 1291,
199
+ "items": 6,
200
+ "issues": 3
201
+ },
202
+ "worksheet": {
203
+ "bom": true,
204
+ "text": "行号,清单编码,名称,单位,合同量,合同单价(元),本期完成量,累计完成量,本期金额(元),累计金额(元),累计比例(%),是否计入,问题代码,问题说明\n1,010101001,平整场地,m2,1200,3.50,300,900,1050.00,3150.00,75.00,是,,\n2,010101003,挖沟槽土方,m3,850,28.00,120,520,3360.00,14560.00,61.18,是,,\n3,010401001,混凝土基础,m3,260,480.00,25.92,240.5,12441.60,115440.00,92.50,是,,\n4,010402001,矩形柱,m3,95,610.00,12,101.5,7320.00,61915.00,106.84,是,E_PROGRESS_OVER_QTY,累计完成量 101.5 超过合同量 95(E_PROGRESS_OVER_QTY)|下一步:核对合同量和变更签证;超量部分走变更或结算,不在本期支付\n5,010515001,现浇构件钢筋,t,80,5200.00,4.2,62.4,21840.00,324480.00,78.00,是,,\n6,011702001,基础模板,m2,1800,55.00,86.4,1720,4752.00,94600.00,95.56,是,E_PROGRESS_PRICE_MISMATCH,申报合同单价 65.00 与合同基准 55.00 不符(E_PROGRESS_PRICE_MISMATCH)|下一步:本期金额按合同单价 55.00 重算,并要求申报方改正\n7,010101003,挖沟槽土方,m3,850,28.00,120,520,3360.00,14560.00,61.18,否,E_PROGRESS_DUP_ITEM,清单编码 010101003 在本期申报里重复出现(E_PROGRESS_DUP_ITEM)|下一步:确认哪一行是本期应报的;重复行不计入本期金额\n"
205
+ }
206
+ }
@@ -0,0 +1,7 @@
1
+ 清单编码,合同量,合同单价
2
+ 010101001,1200,3.50
3
+ 010101003,850,28.00
4
+ 010401001,260,480.00
5
+ 010402001,95,610.00
6
+ 010515001,80,5200.00
7
+ 011702001,1800,55.00
@@ -0,0 +1,8 @@
1
+ 清单编码,名称,单位,合同量,合同单价,本期完成量,累计完成量
2
+ 010101001,平整场地,m2,1200,3.50,300,900
3
+ 010101003,挖沟槽土方,m3,850,28.00,120,520
4
+ 010401001,混凝土基础,m3,260,480.00,25.92,240.5
5
+ 010402001,矩形柱,m3,95,610.00,12,101.5
6
+ 010515001,现浇构件钢筋,t,80,5200.00,4.2,62.4
7
+ 011702001,基础模板,m2,1800,65.00,86.4,1720
8
+ 010101003,挖沟槽土方,m3,850,28.00,120,520
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dsh-progress-payment quickstart — audits the bundled synthetic declaration
4
+ * against the bundled contract baseline and exports the review worksheet.
5
+ *
6
+ * node samples/quickstart/run.mjs # human-readable summary
7
+ * node samples/quickstart/run.mjs --json # the golden result on stdout
8
+ * node samples/quickstart/run.mjs --check # recompute and diff against the golden file
9
+ *
10
+ * The golden file `expected/result.json` is the stdout of `--json`; it is a real
11
+ * run over the committed CSVs, not hand-written output. No network, no model,
12
+ * no customer data: every code and amount is synthetic.
13
+ */
14
+ import assert from 'node:assert/strict'
15
+ import { createHash } from 'node:crypto'
16
+ import { mkdtemp, readFile, realpath, rm } from 'node:fs/promises'
17
+ import os from 'node:os'
18
+ import path from 'node:path'
19
+ import { fileURLToPath } from 'node:url'
20
+ import { createTools } from '../../lib/plugin/tools.js'
21
+
22
+ const here = path.dirname(fileURLToPath(import.meta.url))
23
+ const root = path.resolve(here, '..', '..')
24
+ const DECLARATION = 'samples/quickstart/input/declaration-2026-10.csv'
25
+ const CONTRACT = 'samples/quickstart/input/contract-baseline.csv'
26
+ const expectedPath = path.join(here, 'expected', 'result.json')
27
+ const mode = process.argv.includes('--check') ? 'check' : process.argv.includes('--json') ? 'json' : 'summary'
28
+ const sha256 = (value) => createHash('sha256').update(value).digest('hex')
29
+
30
+ class MemoryTable {
31
+ constructor() {
32
+ this.map = new Map()
33
+ }
34
+ get(key) {
35
+ return this.map.get(key)
36
+ }
37
+ put(key, value) {
38
+ this.map.set(key, value)
39
+ }
40
+ }
41
+
42
+ async function run() {
43
+ const declarationText = await readFile(path.join(root, DECLARATION), 'utf8')
44
+ const contractText = await readFile(path.join(root, CONTRACT), 'utf8')
45
+ const tempDir = await mkdtemp(path.join(os.tmpdir(), 'dsh-progress-payment-quickstart-'))
46
+ const realTemp = await realpath(tempDir)
47
+ try {
48
+ const tools = Object.fromEntries(createTools({ batches: new MemoryTable(), baseDir: tempDir }).map((tool) => [tool.name, tool]))
49
+ const exec = { callId: 'quickstart', agent: { id: 'quickstart' } }
50
+
51
+ const ingest = await tools['progress.ingest'].execute(
52
+ { declaration_csv: declarationText, contract_csv: contractText, source_name: 'declaration-2026-10.csv' },
53
+ exec,
54
+ )
55
+ const audit = await tools['progress.audit'].execute({ batch_id: ingest.batch_id }, exec)
56
+ const exported = await tools['progress.export'].execute(
57
+ { batch_id: ingest.batch_id, filename: 'progress-audit-2026-10.csv' },
58
+ exec,
59
+ )
60
+ const csvText = await readFile(exported.path, 'utf8')
61
+
62
+ return {
63
+ _note:
64
+ 'Real tool output. The export path is normalised to exports/<file>.csv (the run directory is a temp dir); everything else is verbatim. Amounts are integer cents.',
65
+ sample: {
66
+ declaration: { path: DECLARATION, bytes: Buffer.byteLength(declarationText), sha256: sha256(declarationText) },
67
+ contract: { path: CONTRACT, bytes: Buffer.byteLength(contractText), sha256: sha256(contractText) },
68
+ },
69
+ ingest,
70
+ audit,
71
+ export: {
72
+ path: `exports/${path.basename(exported.path)}`,
73
+ sha256: exported.sha256,
74
+ rows: exported.rows,
75
+ bytes: exported.bytes,
76
+ items: exported.items,
77
+ issues: exported.issues,
78
+ },
79
+ worksheet: {
80
+ bom: csvText.charCodeAt(0) === 0xfeff,
81
+ text: csvText.replace(/^\uFEFF/, ''),
82
+ },
83
+ }
84
+ } finally {
85
+ await rm(tempDir, { recursive: true, force: true })
86
+ }
87
+ }
88
+
89
+ function printSummary(result) {
90
+ const { audit, export: exported, worksheet } = result
91
+ const summary = audit.summary
92
+ console.log('dsh-progress-payment quickstart - synthetic progress declaration (not customer data)')
93
+ console.log(`declaration: ${result.sample.declaration.path} (${summary.rows} rows / ${summary.items} items)`)
94
+ console.log(`contract baseline: ${summary.contract_items} items; batch ${audit.batch_id}`)
95
+ console.log(`period amount: ${(summary.period_amount_cents / 100).toFixed(2)} CNY (declared ${(summary.declared_period_amount_cents / 100).toFixed(2)})`)
96
+ console.log(`cumulative: ${(summary.cumulative_amount_cents / 100).toFixed(2)} CNY / contract ${(summary.contract_amount_cents / 100).toFixed(2)} = ${summary.cumulative_ratio_pct}%`)
97
+ console.log(`issues: ${summary.issues} (over qty ${summary.over_qty}, price mismatch ${summary.price_mismatch}, duplicate ${summary.duplicate_items})`)
98
+ for (const issue of audit.issues) console.log(` row ${issue.row} ${issue.item_code} ${issue.code} ${issue.message.split('(')[0]}`)
99
+ console.log(`worksheet: ${exported.path} ${exported.rows} rows, ${exported.bytes} bytes, sha256 ${exported.sha256.slice(0, 12)}...`)
100
+ console.log(`worksheet columns: ${worksheet.text.split('\n')[0]}`)
101
+ }
102
+
103
+ const result = await run()
104
+
105
+ if (mode === 'json') {
106
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`)
107
+ } else if (mode === 'check') {
108
+ const expected = JSON.parse(await readFile(expectedPath, 'utf8'))
109
+ assert.deepEqual(result, expected)
110
+ printSummary(result)
111
+ console.log('golden samples/quickstart/expected/result.json matches')
112
+ console.log('quickstart ok')
113
+ } else {
114
+ printSummary(result)
115
+ console.log('run with --check to compare against expected/result.json')
116
+ }
@@ -0,0 +1,21 @@
1
+ [
2
+ {
3
+ "path": "docs/assets/quickstart.png",
4
+ "kind": "quickstart",
5
+ "alt": "dsh-progress-payment quickstart terminal output",
6
+ "caption": "Real command: node samples/quickstart/run.mjs --check — a synthetic 7-row / 6-item declaration against a 6-item contract baseline yields 50,763.60 CNY for the period, 84.62% cumulative, 3 blocking issues (over quantity, price mismatch, duplicate item) and an 8-row review worksheet. Rendered from the captured terminal output.",
7
+ "command": "node samples/quickstart/run.mjs --check",
8
+ "run_at": "2026-11-02T15:05:00Z",
9
+ "output_sha256": "bdaa9e845c43bab3e29b0e48dddfb801af505e6e552ffc3b12351f59c12feff5",
10
+ "output_path": "samples/quickstart/expected/result.json",
11
+ "log": "docs/assets/quickstart.log",
12
+ "log_sha256": "582cc7f92d0a8ca7d7ee6030e5d1607b6c3609d0f55dd745f5296b9fd99f6710",
13
+ "image_sha256": "beeda8ec806af9221faf8f253cff5191232f0580fa6a6012112ee48f09ba8854"
14
+ },
15
+ {
16
+ "path": "docs/assets/dsh-progress-payment-flow.svg",
17
+ "kind": "flow",
18
+ "alt": "dsh-progress-payment workflow diagram",
19
+ "caption": "Pipeline diagram: local declaration CSV + contract baseline to integer-cent audit to local worksheet. Schematic, not test evidence."
20
+ }
21
+ ]