dsh-nsfc-form-check 0.2.10 → 0.2.11
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/README-es.md +38 -2
- package/README-hi.md +38 -2
- package/README-pt.md +38 -2
- package/README-zh.md +51 -21
- package/README.md +45 -7
- package/lib/index.d.mts +9 -15
- package/lib/index.mjs +15 -22
- package/package.json +5 -5
package/README-es.md
CHANGED
|
@@ -8,6 +8,7 @@ dsh plugin --profile <name> add dsh-nsfc-form-check
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
[](https://dsh.market/)
|
|
11
|
+
[](https://dshfind.com/en/plugins/PerryLink/dsh-nsfc-form-check?ref=badge)
|
|
11
12
|
|
|
12
13
|
`dsh-nsfc-form-check` lee una solicitud al NSFC —sus líneas de texto, las propiedades electrónicas del documento y el listado de términos de identidad de la propia institución— y contrasta ese material con un paquete de reglas versionado: si hay un listado configurado, en qué líneas del cuerpo y dentro de qué rango de líneas configurado aparecen los términos de solicitante, institución y director que usted configuró, qué llevan las propiedades de título, autor, empresa y última modificación, si el material cabe en el límite de extensión que fijó el despliegue, si están presentes los elementos de revisión formal y la declaración de solicitud repetida que usted configuró, si el nombre del director está cumplimentado como exigen las guías anuales, y si aparece algún término clasificado o sensible configurado. Cada hallazgo nombra la cláusula de la que procede e indica si esa cláusula es un requisito directo, un principio o una configuración local, y toda comprobación que no pudo ejecutarse figura en `skipped` con su motivo.
|
|
13
14
|
|
|
@@ -20,14 +21,45 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
20
21
|
|
|
21
22
|
## Cómo se ve la salida
|
|
22
23
|
|
|
23
|
-

|
|
25
|
+
|
|
26
|
+
*Resumen del flujo: documento → reglas → hallazgos. Los ejemplos siguientes usan la superficie de comandos real.*
|
|
24
27
|
|
|
25
|
-

|
|
26
28
|
|
|
27
29
|
Salida real de este plugin sobre su propio fixture de prueba `NF-009` — no es un montaje. El paquete de reglas no inventa citas, así que cada hallazgo nombra la cláusula aplicada y advierte que su texto no se obtuvo.
|
|
28
30
|
|
|
29
31
|
## Qué responde
|
|
30
32
|
|
|
33
|
+
### Ejemplos
|
|
34
|
+
|
|
35
|
+
La tabla siguiente es el conjunto de ejemplos: la primera fila es el caso detallado y las demás son casos breves.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#### Salida detallada
|
|
39
|
+
|
|
40
|
+
**Herramienta** `nsfc_form_check`
|
|
41
|
+
|
|
42
|
+
**Entrada**
|
|
43
|
+
|
|
44
|
+
~~~json
|
|
45
|
+
{"text":"申请代码:H0301\n项目名称:某信号通路在疾病进展中的作用机制研究","metadata":{},"roster":{"authorNames":[],"institutionNames":[],"advisorNames":[],"allowList":[]}}
|
|
46
|
+
~~~
|
|
47
|
+
|
|
48
|
+
**Salida**
|
|
49
|
+
|
|
50
|
+
~~~json
|
|
51
|
+
{
|
|
52
|
+
"id": "dsh-nsfc-form-check.NF-001.811c9dc5",
|
|
53
|
+
"ruleId": "NF-001",
|
|
54
|
+
"severity": "warn",
|
|
55
|
+
"locator": {},
|
|
56
|
+
"found": "未配置任何可核验的身份词(申请人姓名、依托单位名称、导师姓名均为空)",
|
|
57
|
+
"expected": "匿名检查需要名单才能执行;未配置时其余匿名相关检查只能逐条报为未执行"
|
|
58
|
+
}
|
|
59
|
+
~~~
|
|
60
|
+
|
|
61
|
+
*Observado en `dsh-nsfc-form-check/tests/fixtures/NF-001/NF-001-unsafe.json`*
|
|
62
|
+
|
|
31
63
|
| Usted pregunta | Qué responde |
|
|
32
64
|
|---|---|
|
|
33
65
|
| Nadie rellenó el listado de nombres de solicitantes. ¿La revisión de identidad pasa sin más? | No. `NF-001` es lo primero que se informa cuando `authorNames`, `institutionNames` y `advisorNames` están vacíos, y cada comprobación de identidad que necesita esos términos figura en `skipped` con su motivo. Una lista de hallazgos vacía nunca significa que no hubiera nada mal: lea `NF-001` y las entradas de `skipped` antes de concluir nada. |
|
|
@@ -126,6 +158,10 @@ node ../scripts/sync-shared.mjs dsh-nsfc-form-check
|
|
|
126
158
|
|
|
127
159
|
El último comando copia el kit compartido de `../_shared` a `src/shared/`; vuelva a ejecutarlo tras cada cambio compartido.
|
|
128
160
|
|
|
161
|
+
## PerryLink DSH Plugin Family
|
|
162
|
+
|
|
163
|
+
Full family index: [choose a checker by material](https://perrylink.github.io/zh/checkers/choose/) and [all plugins](https://github.com/PerryLink). This repository is one of them.
|
|
164
|
+
|
|
129
165
|
## License
|
|
130
166
|
|
|
131
167
|
[Apache License 2.0](LICENSE) © 2026 dsh-nsfc-form-check contributors.
|
package/README-hi.md
CHANGED
|
@@ -8,6 +8,7 @@ dsh plugin --profile <name> add dsh-nsfc-form-check
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
[](https://dsh.market/)
|
|
11
|
+
[](https://dshfind.com/en/plugins/PerryLink/dsh-nsfc-form-check?ref=badge)
|
|
11
12
|
|
|
12
13
|
`dsh-nsfc-form-check` एक NSFC आवेदन — उसकी मुख्य पंक्तियाँ, इलेक्ट्रॉनिक दस्तावेज़-गुण, और संस्था की अपनी पहचान-शब्द सूची — पढ़ता है और उस सामग्री की जाँच एक संस्करणबद्ध नियम-पैक से करता है: क्या कोई सूची कॉन्फ़िगर है, कॉन्फ़िगर किए गए आवेदक, संस्था और पर्यवेक्षक नाम मुख्य पाठ में तथा निर्धारित पंक्ति-सीमा में कहाँ आते हैं, शीर्षक, लेखक, कंपनी और अंतिम-संशोधन गुणों में क्या दर्ज है, सामग्री उपयोगकर्ता द्वारा तय लंबाई-सीमा के भीतर है या नहीं, कॉन्फ़िगर किए गए औपचारिक जाँच-मद और दोहरा-आवेदन प्रकटीकरण मौजूद हैं या नहीं, पर्यवेक्षक का नाम वार्षिक दिशानिर्देश के अनुसार भरा गया है या नहीं, और कोई कॉन्फ़िगर किया गया गोप्य या संवेदनशील शब्द आता है या नहीं। प्रत्येक निष्कर्ष उस धारा का नाम देता है जिससे वह आया, और बताता है कि वह धारा सीधा प्रावधान है, सिद्धांत है या स्थानीय कॉन्फ़िगरेशन; और जो जाँच नहीं चल सकी वह `skipped` में कारण सहित दर्ज होती है।
|
|
13
14
|
|
|
@@ -20,14 +21,45 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
20
21
|
|
|
21
22
|
## आउटपुट कैसा दिखता है
|
|
22
23
|
|
|
23
|
-

|
|
25
|
+
|
|
26
|
+
*कार्यप्रवाह: दस्तावेज़ → नियम → निष्कर्ष। नीचे के उदाहरण वास्तविक कमांड सतह का उपयोग करते हैं।*
|
|
24
27
|
|
|
25
|
-

|
|
26
28
|
|
|
27
29
|
इस प्लगइन का अपने ही `NF-009` टेस्ट फ़िक्स्चर पर वास्तविक आउटपुट — कोई नकली चित्र नहीं। नियम-पैक उद्धरण नहीं गढ़ता, इसलिए हर निष्कर्ष लागू किए गए खंड का नाम और यह भी बताता है कि उसका मूल पाठ इस बार प्राप्त नहीं हुआ।
|
|
28
30
|
|
|
29
31
|
## यह किन सवालों का जवाब देता है
|
|
30
32
|
|
|
33
|
+
### उदाहरण
|
|
34
|
+
|
|
35
|
+
नीचे दी गई तालिका उदाहरण-समुच्चय है: पहली पंक्ति विस्तृत केस है, बाकी संक्षिप्त केस हैं।
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#### विस्तृत आउटपुट
|
|
39
|
+
|
|
40
|
+
**उपकरण** `nsfc_form_check`
|
|
41
|
+
|
|
42
|
+
**इनपुट**
|
|
43
|
+
|
|
44
|
+
~~~json
|
|
45
|
+
{"text":"申请代码:H0301\n项目名称:某信号通路在疾病进展中的作用机制研究","metadata":{},"roster":{"authorNames":[],"institutionNames":[],"advisorNames":[],"allowList":[]}}
|
|
46
|
+
~~~
|
|
47
|
+
|
|
48
|
+
**आउटपुट**
|
|
49
|
+
|
|
50
|
+
~~~json
|
|
51
|
+
{
|
|
52
|
+
"id": "dsh-nsfc-form-check.NF-001.811c9dc5",
|
|
53
|
+
"ruleId": "NF-001",
|
|
54
|
+
"severity": "warn",
|
|
55
|
+
"locator": {},
|
|
56
|
+
"found": "未配置任何可核验的身份词(申请人姓名、依托单位名称、导师姓名均为空)",
|
|
57
|
+
"expected": "匿名检查需要名单才能执行;未配置时其余匿名相关检查只能逐条报为未执行"
|
|
58
|
+
}
|
|
59
|
+
~~~
|
|
60
|
+
|
|
61
|
+
*स्रोत `dsh-nsfc-form-check/tests/fixtures/NF-001/NF-001-unsafe.json`*
|
|
62
|
+
|
|
31
63
|
| आपका सवाल | इसका जवाब |
|
|
32
64
|
|---|---|
|
|
33
65
|
| आवेदक नाम की सूची किसी ने नहीं भरी। तो पहचान की जाँच चुपचाप पास हो जाती है? | नहीं। जब `authorNames`, `institutionNames` और `advisorNames` तीनों खाली हों तो सबसे पहले `NF-001` दर्ज होता है, और जिन पहचान-जाँचों को ये शब्द चाहिए वे सब कारण सहित `skipped` में दर्ज होती हैं। इसलिए निष्कर्ष-सूची खाली होने का अर्थ कभी "कुछ गड़बड़ नहीं" नहीं होता — कोई निष्कर्ष निकालने से पहले `NF-001` और `skipped` की प्रविष्टियाँ देखें। |
|
|
@@ -126,6 +158,10 @@ node ../scripts/sync-shared.mjs dsh-nsfc-form-check
|
|
|
126
158
|
|
|
127
159
|
अंतिम कमांड `../_shared` का साझा किट `src/shared/` में कॉपी करता है; हर साझा बदलाव के बाद इसे दोबारा चलाएँ।
|
|
128
160
|
|
|
161
|
+
## PerryLink DSH Plugin Family
|
|
162
|
+
|
|
163
|
+
Full family index: [choose a checker by material](https://perrylink.github.io/zh/checkers/choose/) and [all plugins](https://github.com/PerryLink). This repository is one of them.
|
|
164
|
+
|
|
129
165
|
## License
|
|
130
166
|
|
|
131
167
|
[Apache License 2.0](LICENSE) © 2026 dsh-nsfc-form-check contributors.
|
package/README-pt.md
CHANGED
|
@@ -8,6 +8,7 @@ dsh plugin --profile <name> add dsh-nsfc-form-check
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
[](https://dsh.market/)
|
|
11
|
+
[](https://dshfind.com/en/plugins/PerryLink/dsh-nsfc-form-check?ref=badge)
|
|
11
12
|
|
|
12
13
|
`dsh-nsfc-form-check` lê uma candidatura ao NSFC —as suas linhas de texto, as propriedades eletrónicas do documento e a lista de termos de identidade da própria instituição— e confronta esse material com um pacote de regras versionado: se existe uma lista configurada, em que linhas do corpo e dentro de que intervalo de linhas configurado aparecem os termos de requerente, instituição e orientador que configurou, o que consta nas propriedades de título, autor, empresa e última modificação, se o material cabe no limite de extensão fixado pela instalação, se estão presentes os itens de revisão formal e a declaração de candidatura repetida que configurou, se o nome do orientador está preenchido como exigem as orientações anuais, e se aparece algum termo classificado ou sensível configurado. Cada constatação nomeia a cláusula de onde vem e indica se essa cláusula é um requisito direto, um princípio ou uma configuração local, e toda a verificação que não pôde ser executada consta em `skipped` com o seu motivo.
|
|
13
14
|
|
|
@@ -20,14 +21,45 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
20
21
|
|
|
21
22
|
## Como é a saída
|
|
22
23
|
|
|
23
|
-

|
|
25
|
+
|
|
26
|
+
*Visão geral do fluxo: documento → regras → achados. Os exemplos abaixo usam a superfície real de comandos.*
|
|
24
27
|
|
|
25
|
-

|
|
26
28
|
|
|
27
29
|
Saída real deste plugin sobre o seu próprio fixture de teste `NF-009` — não é uma simulação. O pacote de regras não inventa citações, por isso cada achado nomeia a cláusula aplicada e avisa que o seu texto não foi obtido.
|
|
28
30
|
|
|
29
31
|
## O que ele responde
|
|
30
32
|
|
|
33
|
+
### Exemplos
|
|
34
|
+
|
|
35
|
+
A tabela abaixo é o conjunto de exemplos: a primeira linha é o caso detalhado e as demais são casos curtos.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#### Saída detalhada
|
|
39
|
+
|
|
40
|
+
**Ferramenta** `nsfc_form_check`
|
|
41
|
+
|
|
42
|
+
**Entrada**
|
|
43
|
+
|
|
44
|
+
~~~json
|
|
45
|
+
{"text":"申请代码:H0301\n项目名称:某信号通路在疾病进展中的作用机制研究","metadata":{},"roster":{"authorNames":[],"institutionNames":[],"advisorNames":[],"allowList":[]}}
|
|
46
|
+
~~~
|
|
47
|
+
|
|
48
|
+
**Saída**
|
|
49
|
+
|
|
50
|
+
~~~json
|
|
51
|
+
{
|
|
52
|
+
"id": "dsh-nsfc-form-check.NF-001.811c9dc5",
|
|
53
|
+
"ruleId": "NF-001",
|
|
54
|
+
"severity": "warn",
|
|
55
|
+
"locator": {},
|
|
56
|
+
"found": "未配置任何可核验的身份词(申请人姓名、依托单位名称、导师姓名均为空)",
|
|
57
|
+
"expected": "匿名检查需要名单才能执行;未配置时其余匿名相关检查只能逐条报为未执行"
|
|
58
|
+
}
|
|
59
|
+
~~~
|
|
60
|
+
|
|
61
|
+
*Observado em `dsh-nsfc-form-check/tests/fixtures/NF-001/NF-001-unsafe.json`*
|
|
62
|
+
|
|
31
63
|
| Você pergunta | O que ele responde |
|
|
32
64
|
|---|---|
|
|
33
65
|
| Ninguém preencheu a lista de nomes de requerentes. A verificação de identidade passa sem mais? | Não. `NF-001` é a primeira coisa reportada quando `authorNames`, `institutionNames` e `advisorNames` estão vazios, e cada verificação de identidade que precisa desses termos consta em `skipped` com o seu motivo. Uma lista de constatações vazia nunca significa que nada estava errado — leia `NF-001` e as entradas de `skipped` antes de tirar qualquer conclusão. |
|
|
@@ -126,6 +158,10 @@ node ../scripts/sync-shared.mjs dsh-nsfc-form-check
|
|
|
126
158
|
|
|
127
159
|
O último comando copia o kit compartilhado de `../_shared` para `src/shared/`; execute-o novamente após cada alteração compartilhada.
|
|
128
160
|
|
|
161
|
+
## PerryLink DSH Plugin Family
|
|
162
|
+
|
|
163
|
+
Full family index: [choose a checker by material](https://perrylink.github.io/zh/checkers/choose/) and [all plugins](https://github.com/PerryLink). This repository is one of them.
|
|
164
|
+
|
|
129
165
|
## License
|
|
130
166
|
|
|
131
167
|
[Apache License 2.0](LICENSE) © 2026 dsh-nsfc-form-check contributors.
|
package/README-zh.md
CHANGED
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
|
|
4
4
|
|
|
5
|
+
<!-- topblock:v1 -->
|
|
6
|
+
> **这是什么** 国自然申请书形式审查。输出一份「哪一行、哪一栏、差什么」的清单。
|
|
7
|
+
> **给谁用** 科研管理、基金申报辅助;不用懂命令行。
|
|
8
|
+
> **你交什么** 这项核对用到的原始材料(表格、清单或文书);不改原件。Excel 可先转成 JSON/YAML,对话里也能代转。
|
|
9
|
+
> **它不做什么** 不判合规、不认定责任、不替代审核人;只列材料内部能逐条指认的差异。
|
|
10
|
+
> **怎么开始** 在 WorkBuddy / 扣子搜「职业文档核对全集」(总包,本检查是其中一项;上架以商城为准);或命令行:
|
|
11
|
+
> `dsh plugin --profile <name> add dsh-nsfc-form-check`
|
|
12
|
+
<!-- /topblock:v1 -->
|
|
13
|
+
|
|
5
14
|
[](https://dsh.market/)
|
|
15
|
+
[](https://dshfind.com/en/plugins/PerryLink/dsh-nsfc-form-check?ref=badge)
|
|
6
16
|
|
|
7
17
|
`dsh-nsfc-form-check` 读取一份国家自然科学基金申请书——正文行、电子文档属性,以及本机构自己配置的身份词名单——按版本化规则库核对:名单是否已配置,配置的申请人、依托单位与导师姓名在正文中及指定行范围内的出现位置,标题、作者、单位、「最后修改者」四个文档属性各写了什么,材料是否超出使用方配置的长度限额,配置的形式审查项与重复申请披露说明是否齐备,导师姓名是否已按当年指南要求如实填写,以及是否出现配置的涉密或敏感词。每一条发现都写出它所依据的条款,并标明该条款是直接规定、原则推论还是本机构配置;每一项无法执行的检查都以 `skipped` 连同原因列出。
|
|
8
18
|
|
|
@@ -15,14 +25,45 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
15
25
|
|
|
16
26
|
## 实际输出长什么样
|
|
17
27
|
|
|
18
|
-

|
|
29
|
+
|
|
30
|
+
*工作流概览:文档 → 规则包 → 核对结果。下面的示例使用实际命令面。*
|
|
19
31
|
|
|
20
|
-

|
|
21
32
|
|
|
22
33
|
本插件对自己 `NF-009` 测试夹具的**真实输出**,不是示意图。规则库不伪造引文,因此每条发现都会同时写明所引条款,以及该条款原文本次未取得。
|
|
23
34
|
|
|
24
35
|
## 它回答什么问题
|
|
25
36
|
|
|
37
|
+
### 示例
|
|
38
|
+
|
|
39
|
+
下表是示例集:第一行是详细走查,其余行是简短案例。
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
#### 详细输出
|
|
43
|
+
|
|
44
|
+
**工具** `nsfc_form_check`
|
|
45
|
+
|
|
46
|
+
**输入**
|
|
47
|
+
|
|
48
|
+
~~~json
|
|
49
|
+
{"text":"申请代码:H0301\n项目名称:某信号通路在疾病进展中的作用机制研究","metadata":{},"roster":{"authorNames":[],"institutionNames":[],"advisorNames":[],"allowList":[]}}
|
|
50
|
+
~~~
|
|
51
|
+
|
|
52
|
+
**输出**
|
|
53
|
+
|
|
54
|
+
~~~json
|
|
55
|
+
{
|
|
56
|
+
"id": "dsh-nsfc-form-check.NF-001.811c9dc5",
|
|
57
|
+
"ruleId": "NF-001",
|
|
58
|
+
"severity": "warn",
|
|
59
|
+
"locator": {},
|
|
60
|
+
"found": "未配置任何可核验的身份词(申请人姓名、依托单位名称、导师姓名均为空)",
|
|
61
|
+
"expected": "匿名检查需要名单才能执行;未配置时其余匿名相关检查只能逐条报为未执行"
|
|
62
|
+
}
|
|
63
|
+
~~~
|
|
64
|
+
|
|
65
|
+
*来源 `dsh-nsfc-form-check/tests/fixtures/NF-001/NF-001-unsafe.json`*
|
|
66
|
+
|
|
26
67
|
| 你会问 | 它怎么答 |
|
|
27
68
|
|---|---|
|
|
28
69
|
| 申请人姓名名单没填,匿名检查是不是就直接通过了? | 不是。`authorNames`、`institutionNames`、`advisorNames` 三项都为空时,最先报出的就是 `NF-001`,其余需要名单的匿名检查逐条以 `skipped` 连同原因列出。所以发现列表为空永远不等于没有问题——下结论前先看 `NF-001` 与 `skipped` 条目。 |
|
|
@@ -39,28 +80,13 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
39
80
|
| 《国家自然科学基金条例》 | 国务院令第796号 | NF-001, NF-002, NF-003, NF-004, NF-005, NF-006, NF-007, NF-008, NF-009, NF-010, NF-011, NF-012, NF-013, NF-014, NF-015 |
|
|
40
81
|
| 《2026 年度国家自然科学基金项目指南·申请规定》 | 2026 年度(逐年更新) | NF-014, NF-015 |
|
|
41
82
|
|
|
42
|
-
|
|
43
|
-
reports the identity clues it finds, alongside the length and form-review items a deployment
|
|
44
|
-
configures. It is not `dsh-rulefile-check` (which audits the legality of a regulatory document), not
|
|
45
|
-
`dsh-policy-brief-draft` (which drafts a policy explainer), and not `dsh-review-reply-check` (which
|
|
46
|
-
tracks reviewer comments). It reads one proposal and reports literal matches against cited clauses.
|
|
83
|
+
**边界(中文译文,以英文原文为准):** 本插件核对**国家自然科学基金申请书的文本与电子文档属性**,并报出它发现的身份线索,以及部署方配置的篇幅与形式审查项。它不是 `dsh-rulefile-check`(后者审查规范性文件的合法性),不是 `dsh-policy-brief-draft`(后者起草政策解读),也不是 `dsh-review-reply-check`(后者跟踪评审意见)。它读取一份申请书,并报出与所引条款之间的字面匹配。
|
|
47
84
|
|
|
48
|
-
> ### ⚠️
|
|
85
|
+
> ### ⚠️ 在使用匿名性检查之前,请先读这一段(以英文原文为准)
|
|
49
86
|
>
|
|
50
|
-
>
|
|
51
|
-
> from appearing in an NSFC proposal.** Three independent texts were read in full for this plugin —
|
|
52
|
-
> 《国家自然科学基金条例》(国务院令第796号), the 2026 年度《项目指南·申请规定》, and the 2019 年度
|
|
53
|
-
> guidelines — and none contains 匿名, 盲审, 活页, or any "must not appear" wording about identity.
|
|
54
|
-
> The regulation does not contain the word 匿名 at all. Its **avoidance** clause (第二十条) requires a
|
|
55
|
-
> reviewer from the applicant's own legal entity to recuse, which presupposes that the system knows
|
|
56
|
-
> the applicant's institution — the opposite of an anonymous process.
|
|
87
|
+
> **目前没有任何国家规定禁止申请人的姓名、单位或导师出现在国家自然科学基金申请书中。** 为编写本插件,完整阅读了三份独立文本——《国家自然科学基金条例》(国务院令第796号)、2026 年度《项目指南·申请规定》以及 2019 年度指南——其中没有任何一份包含 匿名、盲审、活页,或任何关于身份的「不得出现」表述。该条例中根本没有「匿名」一词。其**回避**条款(第二十条)要求来自申请人同一法人单位的评审专家回避,这恰恰以系统知晓申请人所在单位为前提——与匿名流程正好相反。
|
|
57
88
|
>
|
|
58
|
-
>
|
|
59
|
-
> a human to weigh**, labelled 身份线索词 and never phrased as a violation. The plugin is useful for a
|
|
60
|
-
> research-office self-check, and it is **wrong to use it as a compliance gate**. Two rules go further
|
|
61
|
-
> and cite the guidance verbatim: `NF-014` checks that the advisor's name **is** filled in, because the
|
|
62
|
-
> yearly guidelines require it, and `NF-015` checks 涉密与敏感信息, which is the one "must not appear"
|
|
63
|
-
> requirement that really exists — and its object is classified information, not identity.
|
|
89
|
+
> 因此,本插件就姓名或单位作出的每一项发现,都只是**供人自行权衡的技术性观察**,标记为 身份线索词,从不表述为违规。本插件可用于科研管理部门的自查,但**把它当作合规门槛来用是错误的**。有两条规则更进一步,逐字引用了指南:`NF-014` 核对导师姓名**已**填写,因为年度指南有此要求;`NF-015` 核对 涉密与敏感信息,这是真正存在的唯一一项「不得出现」要求——而它的对象是涉密信息,不是身份。
|
|
64
90
|
|
|
65
91
|
## Compatibility
|
|
66
92
|
|
|
@@ -121,6 +147,10 @@ node ../scripts/sync-shared.mjs dsh-nsfc-form-check
|
|
|
121
147
|
|
|
122
148
|
第 4 项把 `../_shared` 的共享件同步进 `src/shared/`;每次改动共享件后都要重跑。
|
|
123
149
|
|
|
150
|
+
## PerryLink DSH Plugin Family
|
|
151
|
+
|
|
152
|
+
完整清单(62 个核查器 + 通用插件)见 [按材料选核查器](https://perrylink.github.io/zh/checkers/choose/);本仓只是其中一个。
|
|
153
|
+
|
|
124
154
|
## License
|
|
125
155
|
|
|
126
156
|
[Apache License 2.0](LICENSE) © 2026 dsh-nsfc-form-check contributors.
|
package/README.md
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
<!-- topblock:v1 -->
|
|
6
|
+
> **What it is** — NSFC proposal form review and identity-clue prompting against the institution's own roster. It returns a list of what is inconsistent, where, and what to fix.
|
|
7
|
+
> **Who it is for** — research administrators; no command line required.
|
|
8
|
+
> **What you give it** — the source material the check works on (a table, register or document); the original is never modified. Excel can be converted to JSON/YAML first, in chat if the platform supports it.
|
|
9
|
+
> **What it does not do** — no compliance verdict, no liability finding, no replacement for the reviewer; differences only.
|
|
10
|
+
> **How to start** — search "Professional Document Check Suite" in WorkBuddy / Coze (the full set; this check is one part of it; availability as listed); or:
|
|
11
|
+
> `dsh plugin --profile <name> add dsh-nsfc-form-check`
|
|
12
|
+
<!-- /topblock:v1 -->
|
|
9
13
|
|
|
10
14
|
[](https://dsh.market/)
|
|
15
|
+
[](https://dshfind.com/en/plugins/PerryLink/dsh-nsfc-form-check?ref=badge)
|
|
11
16
|
|
|
12
17
|
`dsh-nsfc-form-check` reads one NSFC proposal — its body lines, its electronic document properties, and the institution's own roster of identity terms — and checks that material against a versioned rule pack: whether a roster is configured at all, where the configured applicant, institution and advisor terms occur in the body and inside a configured line range, what the title, author, company and last-modified-by properties carry, whether the material fits the length limit the deployment set, whether the configured form-review items and duplicate-application disclosure are present, whether the advisor's name has been filled in as the yearly guidelines require, and whether any configured classified or sensitive term appears. Every finding names the clause it came from, states whether that clause is a direct requirement, a principle or a local configuration, and every check that could not run is listed in `skipped` with its reason.
|
|
13
18
|
|
|
@@ -20,14 +25,43 @@ dsh --profile <name> --dump-config | grep 'dsh-nsfc-form-check'
|
|
|
20
25
|
|
|
21
26
|
## What it looks like
|
|
22
27
|
|
|
23
|
-

|
|
29
|
+
|
|
30
|
+
*Workflow overview: document → rule pack → findings. The examples below use the real command surface.*
|
|
24
31
|
|
|
25
|
-

|
|
26
32
|
|
|
27
|
-
Real output from this plugin over its own `NF-009` 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.
|
|
28
33
|
|
|
29
34
|
## What it answers
|
|
30
35
|
|
|
36
|
+
### Examples
|
|
37
|
+
|
|
38
|
+
The table below is the example set: the first row is the detailed walkthrough, the remaining rows are short cases.
|
|
39
|
+
|
|
40
|
+
#### Detailed output
|
|
41
|
+
|
|
42
|
+
**Tool** `nsfc_form_check`
|
|
43
|
+
|
|
44
|
+
**Input**
|
|
45
|
+
|
|
46
|
+
~~~json
|
|
47
|
+
{"text":"申请代码:H0301\n项目名称:某信号通路在疾病进展中的作用机制研究","metadata":{},"roster":{"authorNames":[],"institutionNames":[],"advisorNames":[],"allowList":[]}}
|
|
48
|
+
~~~
|
|
49
|
+
|
|
50
|
+
**Output**
|
|
51
|
+
|
|
52
|
+
~~~json
|
|
53
|
+
{
|
|
54
|
+
"id": "dsh-nsfc-form-check.NF-001.811c9dc5",
|
|
55
|
+
"ruleId": "NF-001",
|
|
56
|
+
"severity": "warn",
|
|
57
|
+
"locator": {},
|
|
58
|
+
"found": "未配置任何可核验的身份词(申请人姓名、依托单位名称、导师姓名均为空)",
|
|
59
|
+
"expected": "匿名检查需要名单才能执行;未配置时其余匿名相关检查只能逐条报为未执行"
|
|
60
|
+
}
|
|
61
|
+
~~~
|
|
62
|
+
|
|
63
|
+
*Observed from `dsh-nsfc-form-check/tests/fixtures/NF-001/NF-001-unsafe.json`*
|
|
64
|
+
|
|
31
65
|
| You ask | What it answers |
|
|
32
66
|
|---|---|
|
|
33
67
|
| Nobody filled in the applicant name list. Does the identity checking just pass? | No. `NF-001` is the first thing reported when `authorNames`, `institutionNames` and `advisorNames` are all empty, and every identity check that needs those terms reports itself in `skipped` with its reason. An empty finding list therefore never means nothing was wrong — read `NF-001` and the `skipped` entries before drawing any conclusion. |
|
|
@@ -209,6 +243,10 @@ node ../scripts/sync-shared.mjs dsh-nsfc-form-check # refresh src/shared from
|
|
|
209
243
|
`tests/docx-fixture.ts` builds real `.docx` packages in memory (a genuine ZIP with deflated entries),
|
|
210
244
|
so the docx path is exercised end to end while the fixtures stay reviewable JSON.
|
|
211
245
|
|
|
246
|
+
## PerryLink DSH Plugin Family
|
|
247
|
+
|
|
248
|
+
Full family index: [choose a checker by material](https://perrylink.github.io/zh/checkers/choose/) and [all plugins](https://github.com/PerryLink). This repository is one of them.
|
|
249
|
+
|
|
212
250
|
## License
|
|
213
251
|
|
|
214
252
|
[Apache License 2.0](LICENSE) © 2026 dsh-nsfc-form-check contributors.
|
package/lib/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Schema from "@deepseek-ai/schemastery";
|
|
2
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
-
//#region src/config.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Every tunable lives here so an operator can change behaviour from
|
|
6
5
|
* `cordis.yml` without editing code (the family's "no hard-coded tunables"
|
|
@@ -11,7 +10,7 @@ import { Context } from "@deepseek-ai/cordis";
|
|
|
11
10
|
* deployment's own configuration because the list is institution-specific and,
|
|
12
11
|
* unlike a rule pack, should not travel with the package.
|
|
13
12
|
*/
|
|
14
|
-
interface Config {
|
|
13
|
+
export interface Config {
|
|
15
14
|
/** Rule-pack path relative to the plugin package root. */
|
|
16
15
|
rulesFile: string;
|
|
17
16
|
/** Rule ids disabled for this deployment. */
|
|
@@ -31,9 +30,7 @@ interface Config {
|
|
|
31
30
|
/** Tool timeout budget in milliseconds. */
|
|
32
31
|
timeoutMs: number;
|
|
33
32
|
}
|
|
34
|
-
declare const Config: Schema<Config>;
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/check.d.ts
|
|
33
|
+
export declare const Config: Schema<Config>;
|
|
37
34
|
/** The institution's own roster of identity terms. */
|
|
38
35
|
interface Roster {
|
|
39
36
|
/** Applicant names. */
|
|
@@ -45,12 +42,10 @@ interface Roster {
|
|
|
45
42
|
/** Terms to ignore even when they match, for example a common surname. */
|
|
46
43
|
allowList: string[];
|
|
47
44
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
declare const name = "dsh-nsfc-form-check";
|
|
51
|
-
declare const inject: string[];
|
|
45
|
+
export declare const name = "dsh-nsfc-form-check";
|
|
46
|
+
export declare const inject: string[];
|
|
52
47
|
/** Tool id exposed to the model, and the row id in `cordis.patch.yml`. */
|
|
53
|
-
declare const TOOL_NAME = "nsfc_form_check";
|
|
48
|
+
export declare const TOOL_NAME = "nsfc_form_check";
|
|
54
49
|
/**
|
|
55
50
|
* Locate a package-owned file such as the rule pack.
|
|
56
51
|
*
|
|
@@ -62,9 +57,9 @@ declare const TOOL_NAME = "nsfc_form_check";
|
|
|
62
57
|
* @returns the resolved absolute path.
|
|
63
58
|
* @throws Error naming every location tried, when the file is absent.
|
|
64
59
|
*/
|
|
65
|
-
declare function resolvePackageFile(relative: string): string;
|
|
60
|
+
export declare function resolvePackageFile(relative: string): string;
|
|
66
61
|
/** Build the roster from configuration plus any per-call additions. */
|
|
67
|
-
declare function rosterFrom(config: Config, extra?: Partial<Roster>): Roster;
|
|
62
|
+
export declare function rosterFrom(config: Config, extra?: Partial<Roster>): Roster;
|
|
68
63
|
/**
|
|
69
64
|
* Register the proposal form and anonymity checker.
|
|
70
65
|
*
|
|
@@ -75,6 +70,5 @@ declare function rosterFrom(config: Config, extra?: Partial<Roster>): Roster;
|
|
|
75
70
|
* @param ctx - plugin context, with `tools` already available.
|
|
76
71
|
* @param config - validated configuration.
|
|
77
72
|
*/
|
|
78
|
-
declare function apply(ctx: Context, config: Config): () => void;
|
|
79
|
-
|
|
80
|
-
export { Config, TOOL_NAME, apply, inject, name, resolvePackageFile, rosterFrom };
|
|
73
|
+
export declare function apply(ctx: Context, config: Config): () => void;
|
|
74
|
+
export {};
|
package/lib/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { dirname, isAbsolute, resolve } from "node:path";
|
|
|
4
4
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
5
|
import Schema from "@deepseek-ai/schemastery";
|
|
6
6
|
import { inflateRawSync } from "node:zlib";
|
|
7
|
-
|
|
7
|
+
// src/config.ts
|
|
8
8
|
const Config = Schema.object({
|
|
9
9
|
rulesFile: Schema.string().default("rules/nsfc-form-check.yaml").description("规则库文件路径(相对插件包根目录)。替换该文件即可切换规则集版本。"),
|
|
10
10
|
disabledRules: Schema.array(Schema.string()).default([]).description("要停用的规则 id 列表;停用的规则会出现在报告的 skipped 中。"),
|
|
@@ -16,8 +16,7 @@ const Config = Schema.object({
|
|
|
16
16
|
allowList: Schema.array(Schema.string()).default([]).description("命中也不报的例外词,例如常见姓氏或学科常用词。"),
|
|
17
17
|
timeoutMs: Schema.number().default(12e4).description("工具协作式超时预算(毫秒)。")
|
|
18
18
|
});
|
|
19
|
-
|
|
20
|
-
//#region src/shared/rules.ts
|
|
19
|
+
// src/shared/rules.ts
|
|
21
20
|
/**
|
|
22
21
|
* Compose the one-line `basis` string rendered into reports.
|
|
23
22
|
* @param basis - the rule's normative basis.
|
|
@@ -47,8 +46,7 @@ function disabledAsSkipped(ruleset, disabledIds, reason) {
|
|
|
47
46
|
reason
|
|
48
47
|
}));
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
//#region src/shared/yaml.ts
|
|
49
|
+
// src/shared/yaml.ts
|
|
52
50
|
/**
|
|
53
51
|
* Minimal, dependency-free YAML reader for rule packs and check material.
|
|
54
52
|
*
|
|
@@ -401,6 +399,10 @@ var Reader = class {
|
|
|
401
399
|
if (!isSequenceItem(line.text)) break;
|
|
402
400
|
this.index += 1;
|
|
403
401
|
const rest = line.text === "-" ? "" : line.text.slice(2).trim();
|
|
402
|
+
if (rest.startsWith("{") || rest.startsWith("[")) {
|
|
403
|
+
items.push(parseScalar(rest, line.num));
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
404
406
|
if ((rest === "" ? -1 : findKeySeparator(rest)) >= 0) {
|
|
405
407
|
items.push(this.readMapping(indent + 2, {
|
|
406
408
|
text: rest,
|
|
@@ -480,8 +482,7 @@ function requireString(source, key, where) {
|
|
|
480
482
|
if (typeof value !== "string" || value.trim() === "") throw new YamlSubsetError(`${where}: missing required string field "${key}"`);
|
|
481
483
|
return value;
|
|
482
484
|
}
|
|
483
|
-
|
|
484
|
-
//#region src/shared/ruleset.ts
|
|
485
|
+
// src/shared/ruleset.ts
|
|
485
486
|
/**
|
|
486
487
|
* Rule-pack loading and validation.
|
|
487
488
|
*
|
|
@@ -611,8 +612,7 @@ function paramStrings(rule, key, fallback) {
|
|
|
611
612
|
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new YamlSubsetError(`rule ${rule.id}: params.${key} must be a list of strings`);
|
|
612
613
|
return value;
|
|
613
614
|
}
|
|
614
|
-
|
|
615
|
-
//#region src/shared/report.ts
|
|
615
|
+
// src/shared/report.ts
|
|
616
616
|
/** Locator fields that participate in the stable issue id, in fixed order. */
|
|
617
617
|
const LOCATOR_ID_KEYS = [
|
|
618
618
|
"file",
|
|
@@ -688,8 +688,7 @@ function sortValue(value) {
|
|
|
688
688
|
}
|
|
689
689
|
return target;
|
|
690
690
|
}
|
|
691
|
-
|
|
692
|
-
//#region src/check.ts
|
|
691
|
+
// src/check.ts
|
|
693
692
|
/**
|
|
694
693
|
* Pure check core: `(input, ruleset, options) => Report`.
|
|
695
694
|
*
|
|
@@ -1085,8 +1084,7 @@ function runCheck(input, ruleset, options) {
|
|
|
1085
1084
|
skipped
|
|
1086
1085
|
});
|
|
1087
1086
|
}
|
|
1088
|
-
|
|
1089
|
-
//#region src/parse.ts
|
|
1087
|
+
// src/parse.ts
|
|
1090
1088
|
/**
|
|
1091
1089
|
* Extract readable text from the formats a proposal actually arrives in.
|
|
1092
1090
|
*
|
|
@@ -1292,12 +1290,10 @@ function parseMaterial(source) {
|
|
|
1292
1290
|
warnings
|
|
1293
1291
|
};
|
|
1294
1292
|
}
|
|
1295
|
-
|
|
1296
|
-
//#region src/shared/wording.ts
|
|
1293
|
+
// src/shared/wording.ts
|
|
1297
1294
|
/** Footer appended to every rendered report. */
|
|
1298
1295
|
const DISCLAIMER = "免责声明:本报告由程序按声明的规则集自动生成,仅列出与所引条款之间的字面差异,供人工复核线索使用;不构成对任何事实、行为或文件的定性意见,也不替代主管人员、评审专家或监管机构的判断。规则集的时效性与适用范围以引用文件的最新有效版本为准。";
|
|
1299
|
-
|
|
1300
|
-
//#region src/view.ts
|
|
1296
|
+
// src/view.ts
|
|
1301
1297
|
/**
|
|
1302
1298
|
* Model-facing projection of a {@link Report}.
|
|
1303
1299
|
*
|
|
@@ -1377,8 +1373,7 @@ function buildView(report) {
|
|
|
1377
1373
|
reportJson: canonicalJson(report)
|
|
1378
1374
|
};
|
|
1379
1375
|
}
|
|
1380
|
-
|
|
1381
|
-
//#region src/shared/memo.ts
|
|
1376
|
+
// src/shared/memo.ts
|
|
1382
1377
|
/**
|
|
1383
1378
|
* Memoized loading of package-owned rule packs.
|
|
1384
1379
|
*
|
|
@@ -1401,8 +1396,7 @@ function loadRulesetFile(path) {
|
|
|
1401
1396
|
pending.catch(() => cache.delete(path));
|
|
1402
1397
|
return pending;
|
|
1403
1398
|
}
|
|
1404
|
-
|
|
1405
|
-
//#region src/index.ts
|
|
1399
|
+
// src/index.ts
|
|
1406
1400
|
const name = "dsh-nsfc-form-check";
|
|
1407
1401
|
const inject = ["tools"];
|
|
1408
1402
|
/** Tool id exposed to the model, and the row id in `cordis.patch.yml`. */
|
|
@@ -1592,5 +1586,4 @@ function apply(ctx, config) {
|
|
|
1592
1586
|
}
|
|
1593
1587
|
}));
|
|
1594
1588
|
}
|
|
1595
|
-
//#endregion
|
|
1596
1589
|
export { Config, TOOL_NAME, apply, inject, name, resolvePackageFile, rosterFrom };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-nsfc-form-check",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "国家自然科学基金申请书形式审查与匿名化提示(依据《国家自然科学基金条例》与申请人导入的当年指南,仅提示差异,不作出定性结论)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.mjs",
|
|
@@ -78,14 +78,14 @@
|
|
|
78
78
|
"@deepseek-ai/schemastery": "^3.18.2"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@deepseek-ai/cordis": "4.0.5
|
|
82
|
-
"@deepseek-ai/dsh-package-manifest": "0.2.1-rc.
|
|
81
|
+
"@deepseek-ai/cordis": "4.0.5",
|
|
82
|
+
"@deepseek-ai/dsh-package-manifest": "0.2.1-rc.3",
|
|
83
83
|
"@deepseek-ai/dsh-tools": "0.2.1-rc.2",
|
|
84
|
-
"@deepseek-ai/schemastery": "3.18.5
|
|
84
|
+
"@deepseek-ai/schemastery": "3.18.5",
|
|
85
85
|
"@types/node": "^22.20.1",
|
|
86
86
|
"vitest": "^3.2.7",
|
|
87
87
|
"@deepseek-ai/dsh-working-directory": "0.2.1-rc.2",
|
|
88
|
-
"tsdown": "^0.
|
|
88
|
+
"tsdown": "^0.23.1",
|
|
89
89
|
"typescript": "^5.9.3"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {}
|