dsh-research-report 0.2.0 → 0.3.0
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/CHANGELOG.md +10 -0
- package/README.es.md +15 -0
- package/README.hi.md +15 -0
- package/README.md +16 -0
- package/README.pt.md +15 -0
- package/README.zh.md +15 -0
- package/lib/cli.js +103 -0
- package/lib/index.js +6 -594
- package/lib/types/cli.d.ts +14 -0
- package/lib/types/cli.d.ts.map +1 -0
- package/lib/types/cli.js +102 -0
- package/lib/types/cli.js.map +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -1
- package/lib/types/index.js.map +1 -1
- package/lib/types/verify-sealed.d.ts +60 -0
- package/lib/types/verify-sealed.d.ts.map +1 -1
- package/lib/types/verify-sealed.js +107 -0
- package/lib/types/verify-sealed.js.map +1 -1
- package/lib/types/version.d.ts +1 -1
- package/lib/types/version.js +1 -1
- package/lib/verify-sealed-CMJp1f_v.js +711 -0
- package/package.json +4 -1
- package/src/cli.ts +121 -0
- package/src/index.ts +2 -2
- package/src/verify-sealed.ts +157 -0
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-08-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Standalone verifier CLI with SARIF/JSON output for offline citation verification.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Exclude the self-executing verifier CLI entry from coverage (CI).
|
|
17
|
+
|
|
8
18
|
## [0.2.0] - 2026-08-23
|
|
9
19
|
|
|
10
20
|
### Added
|
package/README.es.md
CHANGED
|
@@ -118,6 +118,21 @@ Todos los ajustes son campos `Config` de Schemastery; los valores inválidos fal
|
|
|
118
118
|
- **Los profiles por defecto no montan proveedor de fetch** — el `dsh-base` distribuido monta solo búsqueda, así que la captura de URLs falla ruidosamente (`WEB_UNAVAILABLE`/`WEB_PROVIDER_UNAVAILABLE`) hasta configurar un proveedor de fetch; el `gather` basado en búsqueda lista las fuentes no capturadas en la lista de brechas.
|
|
119
119
|
- **Ámbito de un solo workspace** — las raíces de libro e informes se resuelven contra el directorio de trabajo del harness al montar; los despliegues multi-workspace deben configurar raíces absolutas por profile.
|
|
120
120
|
|
|
121
|
+
## Verifier CLI
|
|
122
|
+
|
|
123
|
+
El binario independiente `dsh-research-verify` (empaquetado como `lib/cli.js`, sin imports de `@deepseek-ai`) audita cualquier directorio de informe sellado sin montar el plugin:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `--report <dir>` — directorio sellado (`manifest.json` + `report.md` + diarios de auditoría).
|
|
130
|
+
- `--seal <sha256>` — hash de sello esperado para comparar con el hash del manifest recalculado; omitido = solo se informa el valor, sin comparar.
|
|
131
|
+
- `--ledger <dir>` — raíz del libro de evidencias (`objects/<sha256>` + `index.jsonl`) para re-verificar claims a nivel de bytes; omitido = los re-checks de claims se omiten honestamente.
|
|
132
|
+
- `--format` — `json` (por defecto) o `sarif` (SARIF 2.1.0).
|
|
133
|
+
|
|
134
|
+
Recalcula el hash de sello, el hash de `report.md` y los hashes de los diarios, re-ejecuta la verificación byte-level + integridad por claim, y sale con código no nulo si alguna comprobación falla. `verifySealedReport` / `buildVerificationReport` / `renderSarif` / `renderVerificationJson` se exportan del paquete para uso como librería.
|
|
135
|
+
|
|
121
136
|
## Development
|
|
122
137
|
|
|
123
138
|
```sh
|
package/README.hi.md
CHANGED
|
@@ -118,6 +118,21 @@ dsh plugin --profile demo remove dsh-research-report # अनइंस्ट
|
|
|
118
118
|
- **डिफ़ॉल्ट profile में fetch provider नहीं** — shipped `dsh-base` केवल search माउंट करता है, इसलिए fetch provider कॉन्फ़िगर होने तक URL कैप्चर ठोंककर विफल होता है (`WEB_UNAVAILABLE`/`WEB_PROVIDER_UNAVAILABLE`); search-आधारित `gather` अकैप्चर स्रोतों को गैप-सूची में डालता है।
|
|
119
119
|
- **एकल-workspace दायरा** — बही-खाता व रिपोर्ट रूट माउंट पर harness वर्किंग डायरेक्टरी के सापेक्ष resolve होते हैं; बहु-workspace डिप्लॉयमेंट को प्रति-profile निरपेक्ष रूट कॉन्फ़िगर करने चाहिए।
|
|
120
120
|
|
|
121
|
+
## Verifier CLI
|
|
122
|
+
|
|
123
|
+
स्वतंत्र `dsh-research-verify` बाइनरी (`lib/cli.js` के रूप में बंडल, कोई `@deepseek-ai` import नहीं) प्लगिन माउंट किए बिना किसी भी सील्ड रिपोर्ट निर्देशिका का ऑडिट करता है:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `--report <dir>` — सील्ड रिपोर्ट निर्देशिका (`manifest.json` + `report.md` + ऑडिट जर्नल)।
|
|
130
|
+
- `--seal <sha256>` — पुनः गणित manifest हैश से तुलना हेतु अपेक्षित सील हैश; छोड़ने पर केवल मान बताया जाता है, तुलना नहीं।
|
|
131
|
+
- `--ledger <dir>` — एविडेंस लेजर रूट (`objects/<sha256>` + `index.jsonl`) दावों की बाइट-स्तरीय पुनः जाँच हेतु; छोड़ने पर दावों की पुनः जाँच ईमानदारी से छोड़ दी जाती है।
|
|
132
|
+
- `--format` — `json` (डिफ़ॉल्ट) या `sarif` (SARIF 2.1.0)।
|
|
133
|
+
|
|
134
|
+
यह सील हैश, `report.md` हैश और ऑडिट जर्नल हैश की पुनः गणना करता है, प्रत्येक दावे की बाइट-स्तरीय + अखंडता जाँच दोहराता है, और कोई भी जाँच विफल होने पर गैर-शून्य कोड से बाहर निकलता है। `verifySealedReport` / `buildVerificationReport` / `renderSarif` / `renderVerificationJson` पैकेज से लाइब्रेरी उपयोग हेतु निर्यात किए जाते हैं।
|
|
135
|
+
|
|
121
136
|
## Development
|
|
122
137
|
|
|
123
138
|
```sh
|
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
- **Falsification ledger** — every contradicted or disproven claim is recorded in `disconfirmation.jsonl` (claim + evidence references + reason) and listed in the report's `证伪记录` appendix.
|
|
41
41
|
- **Negative knowledge** — a disproven claim is remembered by its content hash (`disproofs.jsonl`); the same text re-reported against unchanged evidence is forced back to `disproven` and only re-verifies once the evidence changes.
|
|
42
42
|
- **Read-only verifier loop** — after sealing, a deterministic `verifySealedReport` fallback (zero network, zero model) recomputes the seal and audit hashes and re-checks every claim, writing the machine check to `verifier-note.md`; when `ctx.jobs` is mounted a read-only verifier job is also spawned (the model review is an enhancement, never a replacement).
|
|
43
|
+
- **Standalone verifier CLI** — `dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]` recomputes the seal hash + per-claim re-checks from the sealed directory alone and prints a JSON envelope or a SARIF 2.1.0 document (see [Verifier CLI](#verifier-cli)).
|
|
43
44
|
- **Session-anchored evidence** — `evidence_add` accepts an optional `sessionRef` (`sessionId` + `eventRange`, validated loud); the anchor is stored, rendered in Appendix B, and registered in the manifest and `verification.jsonl`. Session-anchored evidence verifies honestly as `unverified` (`会话锚定证据需人工回查会话日志`).
|
|
44
45
|
- **Honest gaps** — unverified, insufficient, contradicted, and disproven claims keep a visible `[未核实]` / `[证据不足]` / `[与证据矛盾]` / `[已证伪]` marker in the report body and are listed in Appendix A. Nothing is silently passed.
|
|
45
46
|
- **No deep-research loop** — retrieval orchestration is deliberately reused: `ctx.web` for search/fetch, `ctx.jobs` for long runs. Planning and synthesis stay with the model (or an upstream plugin).
|
|
@@ -119,6 +120,21 @@ All tunables are Schemastery `Config` fields; invalid values fail the profile lo
|
|
|
119
120
|
- **Default profiles mount no fetch provider** — the shipped `dsh-base` mounts search only, so URL capture fails loud (`WEB_UNAVAILABLE`/`WEB_PROVIDER_UNAVAILABLE`) until a fetch provider is configured; search-based `gather` lists uncaptured sources in the gap list.
|
|
120
121
|
- **Single-workspace scope** — ledger and report roots resolve against the harness working directory at mount; multi-workspace deployments should configure absolute roots per profile.
|
|
121
122
|
|
|
123
|
+
## Verifier CLI
|
|
124
|
+
|
|
125
|
+
The standalone `dsh-research-verify` binary (bundled as `lib/cli.js`, zero `@deepseek-ai` imports) audits any sealed report directory without mounting the plugin:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- `--report <dir>` — the sealed report directory (`manifest.json` + `report.md` + the audit journals).
|
|
132
|
+
- `--seal <sha256>` — the expected seal hash to compare the recomputed manifest hash against. Omitted = the recomputed hash is reported without comparison.
|
|
133
|
+
- `--ledger <dir>` — the evidence ledger root (`objects/<sha256>` + `index.jsonl`) enabling per-claim byte-level re-checks. Omitted = claim re-checks are skipped honestly.
|
|
134
|
+
- `--format` — `json` (default) or `sarif` (SARIF 2.1.0).
|
|
135
|
+
|
|
136
|
+
It recomputes the seal hash (SHA-256 of `manifest.json`), the `report.md` hash, and the audit-journal hashes, re-runs the byte-level + integrity check for every claim, and exits non-zero when any performed check fails. The same `verifySealedReport` / `buildVerificationReport` / `renderSarif` / `renderVerificationJson` functions are exported from the package for library use.
|
|
137
|
+
|
|
122
138
|
## Development
|
|
123
139
|
|
|
124
140
|
```sh
|
package/README.pt.md
CHANGED
|
@@ -118,6 +118,21 @@ Todos os ajustes são campos `Config` de Schemastery; valores inválidos falham
|
|
|
118
118
|
- **Profiles por omissão não montam provider de fetch** — o `dsh-base` distribuído monta apenas pesquisa, por isso a captura de URLs falha ruidosamente (`WEB_UNAVAILABLE`/`WEB_PROVIDER_UNAVAILABLE`) até configurar um provider de fetch; o `gather` baseado em pesquisa lista as fontes não capturadas na lista de lacunas.
|
|
119
119
|
- **Âmbito de um só workspace** — as raízes de livro e relatórios resolvem contra o diretório de trabalho do harness no mount; deployments multi-workspace devem configurar raízes absolutas por profile.
|
|
120
120
|
|
|
121
|
+
## Verifier CLI
|
|
122
|
+
|
|
123
|
+
O binário independente `dsh-research-verify` (empacotado como `lib/cli.js`, sem imports de `@deepseek-ai`) audita qualquer diretório de relatório selado sem montar o plugin:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `--report <dir>` — diretório selado (`manifest.json` + `report.md` + diários de auditoria).
|
|
130
|
+
- `--seal <sha256>` — hash de selo esperado para comparar com o hash do manifest recalculado; omitido = apenas o valor é informado, sem comparação.
|
|
131
|
+
- `--ledger <dir>` — raiz do ledger de evidências (`objects/<sha256>` + `index.jsonl`) para re-verificar claims byte a byte; omitido = os re-checks de claims são omitidos honestamente.
|
|
132
|
+
- `--format` — `json` (padrão) ou `sarif` (SARIF 2.1.0).
|
|
133
|
+
|
|
134
|
+
Recalcula o hash de selo, o hash de `report.md` e os hashes dos diários, re-executa a verificação byte-level + integridade por claim, e sai com código não nulo se alguma checagem falhar. `verifySealedReport` / `buildVerificationReport` / `renderSarif` / `renderVerificationJson` são exportados do pacote para uso como biblioteca.
|
|
135
|
+
|
|
121
136
|
## Development
|
|
122
137
|
|
|
123
138
|
```sh
|
package/README.zh.md
CHANGED
|
@@ -118,6 +118,21 @@ dsh plugin --profile demo remove dsh-research-report # 卸载
|
|
|
118
118
|
- **默认 profile 不挂载 fetch provider**——官方 `dsh-base` 只挂搜索,所以配置 fetch provider 之前 URL 抓取会响亮失败(`WEB_UNAVAILABLE`/`WEB_PROVIDER_UNAVAILABLE`);基于搜索的 `gather` 会把未捕获的来源列入缺口清单。
|
|
119
119
|
- **单 workspace 作用域**——账本与报告根目录在挂载时相对 harness 工作目录解析;多 workspace 部署应在各 profile 配置绝对路径。
|
|
120
120
|
|
|
121
|
+
## Verifier CLI
|
|
122
|
+
|
|
123
|
+
独立的 `dsh-research-verify` 二进制(打包为 `lib/cli.js`,零 `@deepseek-ai` 导入)无需挂载插件即可审计任意密封报告目录:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- `--report <dir>`:密封报告目录(`manifest.json` + `report.md` + 审计日志)。
|
|
130
|
+
- `--seal <sha256>`:期望的 seal 哈希,用于与重算的 manifest 哈希比对;缺省则只报告重算值、不比对。
|
|
131
|
+
- `--ledger <dir>`:证据账本根目录(`objects/<sha256>` + `index.jsonl`),用于逐 claim 字节级复检;缺省则如实跳过 claim 复检。
|
|
132
|
+
- `--format`:`json`(默认)或 `sarif`(SARIF 2.1.0)。
|
|
133
|
+
|
|
134
|
+
它重算 seal 哈希(`manifest.json` 的 SHA-256)、`report.md` 哈希与审计日志哈希,逐 claim 重跑字节级 + 完整性检查,任一已执行检查失败则以非零码退出。`verifySealedReport` / `buildVerificationReport` / `renderSarif` / `renderVerificationJson` 亦从包导出供库调用。
|
|
135
|
+
|
|
121
136
|
## Development
|
|
122
137
|
|
|
123
138
|
```sh
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { _ as sha256Of, a as renderSarif, o as renderVerificationJson, r as buildVerificationReport, s as verifySealedReport } from "./verify-sealed-CMJp1f_v.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
//#region src/cli.ts
|
|
5
|
+
/**
|
|
6
|
+
* Standalone sealed-report verifier CLI. One command recomputes the seal hash
|
|
7
|
+
* (SHA-256 of manifest.json), the report hash, and the audit-journal hashes,
|
|
8
|
+
* re-runs the byte-level + integrity claim check against the evidence ledger,
|
|
9
|
+
* and prints a SARIF 2.1.0 or JSON report. Zero network, zero model, zero
|
|
10
|
+
* @deepseek-ai imports — this entry bundles to a self-contained binary.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-research-report/cli
|
|
16
|
+
*/
|
|
17
|
+
/** Print usage and exit non-zero. */
|
|
18
|
+
function usage(message) {
|
|
19
|
+
if (message !== void 0) console.error(`dsh-research-verify: ${message}`);
|
|
20
|
+
console.error("Usage: dsh-research-verify --report <dir> [--seal <sha256>] [--ledger <dir>] [--format json|sarif]");
|
|
21
|
+
console.error(" --report <dir> Sealed report directory (holds manifest.json + report.md).");
|
|
22
|
+
console.error(" --seal <sha256> Expected seal hash to compare the recomputed manifest hash against.");
|
|
23
|
+
console.error(" --ledger <dir> Evidence ledger root (objects/<sha256> + index.jsonl) for claim re-checks.");
|
|
24
|
+
console.error(" --format <fmt> Output format: json (default) or sarif.");
|
|
25
|
+
process.exit(message === void 0 ? 0 : 2);
|
|
26
|
+
}
|
|
27
|
+
/** Parse argv into {@link CliArgs}. */
|
|
28
|
+
function parseArgs(argv) {
|
|
29
|
+
const args = {
|
|
30
|
+
reportDir: "",
|
|
31
|
+
seal: null,
|
|
32
|
+
ledger: null,
|
|
33
|
+
format: "json"
|
|
34
|
+
};
|
|
35
|
+
for (let index = 0; index < argv.length; index++) {
|
|
36
|
+
const token = argv[index];
|
|
37
|
+
switch (token) {
|
|
38
|
+
case "--help":
|
|
39
|
+
case "-h":
|
|
40
|
+
usage();
|
|
41
|
+
break;
|
|
42
|
+
case "--report":
|
|
43
|
+
args.reportDir = argv[++index] ?? "";
|
|
44
|
+
break;
|
|
45
|
+
case "--seal":
|
|
46
|
+
args.seal = argv[++index] ?? null;
|
|
47
|
+
break;
|
|
48
|
+
case "--ledger":
|
|
49
|
+
args.ledger = argv[++index] ?? null;
|
|
50
|
+
break;
|
|
51
|
+
case "--format":
|
|
52
|
+
args.format = argv[++index] === "sarif" ? "sarif" : "json";
|
|
53
|
+
break;
|
|
54
|
+
default: usage(`unknown argument ${token}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (args.reportDir === "") usage("--report is required");
|
|
58
|
+
return args;
|
|
59
|
+
}
|
|
60
|
+
/** Read one evidence snapshot from a ledger root by its manifest evidence record. */
|
|
61
|
+
async function readLedgerEvidence(ledgerRoot, record) {
|
|
62
|
+
let content;
|
|
63
|
+
try {
|
|
64
|
+
content = await readFile(path.join(ledgerRoot, "objects", record.sha256), "utf8");
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error.code === "ENOENT") return {
|
|
67
|
+
content: "",
|
|
68
|
+
integrity: "missing"
|
|
69
|
+
};
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
content,
|
|
74
|
+
integrity: sha256Of(content) === record.sha256 ? "ok" : "tampered"
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** The standalone verifier entry point. */
|
|
78
|
+
async function main(argv) {
|
|
79
|
+
const args = parseArgs(argv);
|
|
80
|
+
const manifestText = await readFile(path.join(args.reportDir, "manifest.json"), "utf8");
|
|
81
|
+
const manifest = JSON.parse(manifestText);
|
|
82
|
+
const sealHash = sha256Of(manifestText);
|
|
83
|
+
const evidenceById = new Map((Array.isArray(manifest.evidence) ? manifest.evidence : []).map((record) => [record.id, record]));
|
|
84
|
+
const claimRecheck = args.ledger === null ? "skipped-no-ledger" : "rechecked";
|
|
85
|
+
const result = await verifySealedReport(args.reportDir, args.seal ?? sealHash, {
|
|
86
|
+
readFile: (file) => readFile(file, "utf8"),
|
|
87
|
+
readEvidenceContent: async (id) => {
|
|
88
|
+
if (args.ledger === null) return void 0;
|
|
89
|
+
const record = evidenceById.get(id);
|
|
90
|
+
if (record === void 0) return void 0;
|
|
91
|
+
return readLedgerEvidence(args.ledger, record);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const report = buildVerificationReport(result, args.reportDir, args.seal, claimRecheck);
|
|
95
|
+
process.stdout.write(args.format === "sarif" ? renderSarif(report) : renderVerificationJson(report));
|
|
96
|
+
if (!report.ok) process.exitCode = 1;
|
|
97
|
+
}
|
|
98
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
99
|
+
console.error(`dsh-research-verify: ${error instanceof Error ? error.message : String(error)}`);
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
});
|
|
102
|
+
//#endregion
|
|
103
|
+
export {};
|