feat: doc-writing-standard v1.7.0(首次纳入版本控制)
全流程(六阶段):0-A 八类资料登记表 → 0-B 三张清单(涉及/不涉及/待确认) → 0-C 模板骨架与逐小节饱满度分档 → 0-D 骨架核对 + 公开渠道补全 → 0-E 来源三元组 → 分批成文 → 人工审校 → 交付前一致性门禁 正文写作铁律 7.1–7.5: - 7.1 来源分级 A/B/C(事实 / 编制口径 / 合理推演) - 7.2 用语正反对照表(禁用「详见第 X 章」「按行业通行做法」「与附件 X 口径一致」等) - 7.3 扩写两方向(向前找证据 / 向后找影响),不横向注水 - 7.4 饱满度四档:D 一句话 ≤50 字 / C 交代 ≥100 字 / B 论证 ≥200 字 / A 清单(不看字数) - 7.4.1 三问定档流程、7.4.2 模板小节标题 → 档位速查表、7.4.3《饱满度分档表》为阶段 0-C 强制产出物 - 7.5 成文自检清单(按档位判字数达标) 配套文件: - references/review-failure-cases.md:梓潼初设 6 例真实评审失败 + docx 落地 6 条技术红线 + 交付前自查清单 - scripts/md2docx.py:md → 宋体(四处字体全设)/ 小四 / 首行缩进 2 字符 / 1.5 倍行距 docx 其他:第十三节阶段产物落盘规范(目录树 + 命名 + 留痕纪律)、第十四节评审高频扣分点库。
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
|
||||||
|
# 编辑器 / 系统
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# 转换产物(md2docx 的临时输出)
|
||||||
|
*.docx
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
---
|
||||||
|
name: doc-writing-standard
|
||||||
|
description: 方案类文档通用写作规范(全流程、跨项目复用)。资料盘点 → 意图识别 → 模板化骨架 → 资料核对与公开渠道补全 → 血肉来源标注 → 成文(正文写作铁律:来源分级、零交叉引用)→ 人工审校 → 一致性门禁。黄线:无依据不推断。适用于建设/服务/运维类政务可研、初设、需求论证、项目建议书、投标方案等。含模板小节饱满度分档识别(一句话档 / ≥100 字 / ≥200 字 / 清单档)。
|
||||||
|
version: 1.7.0
|
||||||
|
author: Jony
|
||||||
|
updated: 2026-09-11
|
||||||
|
usage: 编写或修订任何"多章节、有数据口径、需过评审"的正式文档时加载;用户要求扩写/丰富/写饱满某章节时;写作前必须完成阶段0;按文档类型加载骨架模板;成文按排版规范与成文铁律输出
|
||||||
|
---
|
||||||
|
|
||||||
|
# 方案类文档写作规范(通用版)
|
||||||
|
|
||||||
|
## 文件索引
|
||||||
|
|
||||||
|
| 文件 | 职责 | 何时读 |
|
||||||
|
|---|---|---|
|
||||||
|
| `SKILL.md` | 本文件:全流程、黄线、成文铁律(主体,必读) | 每次加载技能时 |
|
||||||
|
| `references/review-failure-cases.md` | 评审高频扣分点与真实失败案例库 | 交付前自查、被评审抓住后回填 |
|
||||||
|
| `scripts/md2docx.py` | md → 宋体/小四/首行缩进 2 字符/1.5 倍行距 docx 转换脚本 | 需要出打印稿时 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 〇、设计原则与黄线
|
||||||
|
|
||||||
|
**方法与项目分离**:本技能只存可复用的通用方法;项目专属信息(单位名、文号、数字、案例)一律存放在项目资料中,写作时通过"来源三元组"挂接(见第五节),不固化在技能与正文中。
|
||||||
|
|
||||||
|
**黄线条款(红线,优先级最高)**:
|
||||||
|
|
||||||
|
1. 无来源依据的内容,禁止推断写入;找不到出处 → 待确认清单,确认前只写占位。
|
||||||
|
2. 数字必须有出处,无法溯源的数字不得出现在正文。
|
||||||
|
3. 口径矛盾必须问,不得擅自取舍。
|
||||||
|
4. "不涉及"必须有依据(模板规则或资料/需求方确认)。
|
||||||
|
5. 待确认项合并成一次结构化问答(问题+选项+建议默认值),未决项以【待确认:编号】占位。
|
||||||
|
6. 引用外部资料必须留痕(URL/文号/访问日期),缺一不得引用。
|
||||||
|
|
||||||
|
## 一、流程总则(六阶段,顺序不可跳)
|
||||||
|
|
||||||
|
阶段 0(写作前强制):
|
||||||
|
|
||||||
|
- 0-A 基础资料盘点(八类登记表 + 动态项清单)
|
||||||
|
- 0-B 意图识别(三张清单:涉及/不涉及/待确认)
|
||||||
|
- 0-C 模板选择与骨架确定(含**逐小节饱满度分档**,产出《饱满度分档表》)
|
||||||
|
- 0-D 骨架与资料核对 + 公开渠道补全
|
||||||
|
- 0-E "血肉"来源标注完善
|
||||||
|
|
||||||
|
随后:v0.1 骨架 → v0.2 细化提纲 → 分批成文(按第七节成文铁律)→ 人工审校 → 一致性门禁。
|
||||||
|
|
||||||
|
> 各阶段产出物的落盘位置与命名见【十三、阶段产物落盘规范】。
|
||||||
|
|
||||||
|
## 二、阶段 0-A / 0-B
|
||||||
|
|
||||||
|
### 0-A 八类资料登记表
|
||||||
|
|
||||||
|
逐项登记:有无 / 来源文件 / 关键数据;缺失 → 【待补】。
|
||||||
|
|
||||||
|
项目名称 → 背景(单位概况/定位/投资资金/工期)→ 政策(国家/省/市/县四级:名称+文号+关键条款)→ 现状(设施底数/系统能力/网络/安全/运维,含存量数字)→ 痛点与需求 → 建设/服务内容 → 目标(总体/分层/量化绩效)→ 备注(模板/提纲/同类参考/预算清单/会议纪要/批复)。
|
||||||
|
|
||||||
|
### 动态项清单(逐项目必须重新确认,禁止沿用上一项目)
|
||||||
|
|
||||||
|
编制单位与人员(模板封面页及正文 1.3):一般由建设单位(委托单位)+ 咨询设计单位(编制单位,盖章)构成,并落实负责人/审核/审定/核校/编写人员;有的项目由建设单位自行编制,按实际判断。
|
||||||
|
|
||||||
|
同类动态项:项目名称是否含标段/分期、资金来源构成、工期起算方式、主管单位名称(以当地机构为准)。
|
||||||
|
|
||||||
|
### 0-B 三张清单
|
||||||
|
|
||||||
|
1. 涉及清单(核心 / 需写 / 简写 + 素材出处 + 篇幅预算)。
|
||||||
|
2. 不涉及清单:带(*)的条目 → 不列、序号顺延;未带(*)的条目 → 保留并写"本项目不涉及此项";每条能回答"凭什么不涉及"。
|
||||||
|
3. 待确认清单:资料缺失 / 口径冲突 / 敏感表述,每条含问题、选项、建议默认值、影响章节。
|
||||||
|
|
||||||
|
三张清单经需求方确认后才进骨架。
|
||||||
|
|
||||||
|
## 三、阶段 0-C:模板选择与骨架确定
|
||||||
|
|
||||||
|
### 适用范围
|
||||||
|
|
||||||
|
政务信息化项目(建设类/服务类/运维类按内容形态区分)的可研、初设、需求论证、项目建议书、投标方案;主管单位以当地机构为准(常见为数据局类部门),审批、承诺函、验收对接均面向主管单位。
|
||||||
|
|
||||||
|
### 内容形态分类
|
||||||
|
|
||||||
|
| 内容形态 | 典型文档 | 骨架重心 | 意图识别侧重 | 数据纪律侧重 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 建设类(工程/购置) | 可研/初设/需求论证 | 按甲方模板全章节 | 逐节核对取舍((*)规则) | 概算明细可复算 |
|
||||||
|
| 服务类(购买服务) | 可研/服务方案/投标 | 服务内容/SLA/人员/工具/考核 | 服务颗粒度与频次时效 | 人月法或混合计量 |
|
||||||
|
| 运维类 | 运维方案/投标 | 运维内容/SLA/流程/考核/应急 | 服务项与考核表一一对应 | 人月法或系统年 |
|
||||||
|
|
||||||
|
### 模板优先级
|
||||||
|
|
||||||
|
甲方给定模板 > 同类已批复范本 > 内置典型骨架。
|
||||||
|
|
||||||
|
## 四、阶段 0-D / 0-E
|
||||||
|
|
||||||
|
### 0-D 骨架与资料核对 + 公开渠道补全
|
||||||
|
|
||||||
|
骨架逐节点与资料核对,标"有料/缺料";缺料且属公开事实的(政策原文、建设单位概况、标准规范),经建设单位官网或搜索引擎补全,先把骨架准备为 md 工作稿;留痕(来源+日期+置信度:官方文件 > 官方网站 > 权威媒体);项目内部数据不得用网络资料替代;检索不到 → 待确认清单。
|
||||||
|
|
||||||
|
### 0-E 来源三元组
|
||||||
|
|
||||||
|
(素材:项目资料:文件名/章节 | 公开来源:URL+日期 | 待确认:编号)
|
||||||
|
|
||||||
|
无一元支撑的节点不得进入 v0.2。
|
||||||
|
|
||||||
|
## 五、结构规范
|
||||||
|
|
||||||
|
1. 结论先行(金字塔原理):每节第一句=核心结论。
|
||||||
|
2. 三段式正文:结论段 → 依据段(数据/标准/表格)→ 图表位;描述公式=对象+动作+数量/频次+交付物。
|
||||||
|
3. 标题一般到三级;图表位显式标注;锚点图先行。
|
||||||
|
|
||||||
|
## 六、排版规范(成文输出统一执行)
|
||||||
|
|
||||||
|
正文字体:宋体,小四(12pt),中西文统一宋体(w:ascii / w:hAnsi / w:eastAsia / w:cs 四处全设)。标题:宋体加粗,字号按甲方模板。正文段落:首行缩进 2 字符。行间距:1.5 倍。页面:A4,页边距按甲方模板。禁止混用等线/Calibri/Consolas 等西文字体。
|
||||||
|
|
||||||
|
python-docx 统一设置函数(四属性全设:w:ascii/w:hAnsi/w:eastAsia/w:cs → 宋体;首行缩进 Pt(24);行距 1.5)配 "md → 宋体 docx" 转换脚本用于打印成稿:**脚本实体见 `scripts/md2docx.py`**,调用方式:
|
||||||
|
|
||||||
|
```
|
||||||
|
set PYTHONUTF8=1
|
||||||
|
python scripts/md2docx.py 输入.md 输出.docx
|
||||||
|
```
|
||||||
|
|
||||||
|
docx 技术红线:Windows 下 python 脚本写 .py 文件执行;XML 插入锚点不能以 `<w:p ...>` 开头结尾夹住插入点,应以 `</w:p>` 结尾;设 PYTHONUTF8=1。
|
||||||
|
|
||||||
|
## 七、成文铁律(正文写作操作规范)
|
||||||
|
|
||||||
|
骨架【结论】只是论点。成文 = 将每个结论节点转换为"论点+论据+论证链"的可交付正文;本章为通用操作规范,逐条执行、逐条可判定。
|
||||||
|
|
||||||
|
### 7.1 来源分级标注(任何论断落笔前先定级)
|
||||||
|
|
||||||
|
| 来源级 | 判定标准 | 正文写法 | 禁止 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| A 事实 | 有勘察记录/政策原文/已确认数据支撑 | 直接陈述,可含数字 | 无 |
|
||||||
|
| B 编制口径 | 骨架阶段或会议确认的约定 | 直接陈述 | 包装成"经勘察发现" |
|
||||||
|
| C 合理推演 | 由 A/B 按业务逻辑衍生 | 只做定性描述,不出现数字 | 编造数量与百分比 |
|
||||||
|
|
||||||
|
配套动作:文末附《编写依据对照自检表》(正式排版时不列入正文),逐条记录:论断 → 来源级 → 出处 → 有效性核查结论。引用的标准必须为现行有效版本,被代替/废止的必须更正。
|
||||||
|
|
||||||
|
### 7.2 用语正反对照表(出现左列写法立即替换)
|
||||||
|
|
||||||
|
| 禁用写法 | 原因 | 替代写法 |
|
||||||
|
|---|---|---|
|
||||||
|
| "详见第 X 章 / 对应 X.X 节" | 交叉引用易错且扰乱排版 | 删除;对应关系写入自检表 |
|
||||||
|
| "按行业通行做法 / 对照要求" | 无真实现行出处即为推断 | 锚定项目已确认口径,或注明真实文号 |
|
||||||
|
| "与附件 X 口径一致" | 指向句冗余 | 删除;口径一致性在自检表维护 |
|
||||||
|
| 推演内容出现数字 | C 级不得量化 | 改定性描述,或补充 A 级数据来源 |
|
||||||
|
| 连续形容词无细节 | 论证链断裂 | 回骨架补论据(按 7.3) |
|
||||||
|
|
||||||
|
### 7.3 扩写操作流程(收到"写饱满/丰富"指令时按序执行)
|
||||||
|
|
||||||
|
1. 向前找证据:将资料中与该结论相关的细节、条款、已确认数据装入论证,颗粒度到具体对象/位置/环节;
|
||||||
|
2. 向后找影响:写明"不解决的后果"与"解决后的改变";
|
||||||
|
3. 按 7.4 确定本节饱满度档位;
|
||||||
|
4. 完成后逐项过 7.5 自检清单。
|
||||||
|
|
||||||
|
### 7.4 饱满度分档:先识别,再落笔
|
||||||
|
|
||||||
|
**四档定义**(字数下限为硬约束,括号内为典型区间)
|
||||||
|
|
||||||
|
| 档位 | 字数下限 | 判定含义 | 写作形态 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **D 一句话档** | ≤50 字 | 只需声明一个事实或结论 | 一句话 + 依据(括注) |
|
||||||
|
| **C 交代档** | **≥100 字**(典型 100–200) | 需把"是什么/现在怎样"交代清楚 | 一段陈述:对象 + 关键事实 + 边界 |
|
||||||
|
| **B 论证档** | **≥200 字**(典型 300–600) | 需证明"凭什么" | 结论段 + 多层论据(A 级数据/条款)+ 影响分析 |
|
||||||
|
| **A 清单档** | 不看字数 | 需把明细列全 | 表格/清单,考核条目完备性与每行依据 |
|
||||||
|
|
||||||
|
档位与章节职能的对应关系:论证型 → B,交代型 → C,声明/占位型 → D,清单/表格型 → A。
|
||||||
|
|
||||||
|
#### 7.4.1 对模板逐小节识别的流程(阶段 0-C 执行,四步)
|
||||||
|
|
||||||
|
**第 0 步 · 锁定判定单元**:以甲方模板的**最小小节**(一般三级标题)为单元,**不是章**。同一章内不同小节可属不同档。
|
||||||
|
|
||||||
|
**第 1 步 · 三问定档(核心判据,按序问)**
|
||||||
|
|
||||||
|
| # | 问题 | 答"是" | 答"否" |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Q1 | 评审会不会追问"凭什么"? | → **B 论证档** | 继续 Q2 |
|
||||||
|
| Q2 | 有需要摆开的事实/数字/条款/明细吗? | 明细成列 → **A 清单档**;仅几个关键事实 → **C 交代档** | 继续 Q3 |
|
||||||
|
| Q3 | 删掉这一节,全文逻辑会断吗? | → **C 交代档** | → **D 一句话档** |
|
||||||
|
|
||||||
|
**第 2 步 · 关键词兜底**:Q1–Q3 拿不准时,对照 7.4.2 表定档。
|
||||||
|
|
||||||
|
**第 3 步 · 落表留痕**:逐个登记 `小节号 | 模板原文标题 | 档位 | 字数下限 | 判定依据(Q几 / 关键词表)`。
|
||||||
|
|
||||||
|
**第 4 步 · 抽检校验**:随机抽 3 个小节各试写 50 字——若"一句话就写完了"却定了 B 档,或"50 字明显不够"却定了 D 档,说明判据用错,回 Q1 重判。
|
||||||
|
|
||||||
|
#### 7.4.2 模板小节标题 → 档位速查表
|
||||||
|
|
||||||
|
适用于政务可研/初设/需求论证/项目建议书/运维方案/投标方案的常见小节。
|
||||||
|
|
||||||
|
| 模板小节标题特征 | 档位 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| 项目名称、建设地点、建设周期/工期、招标方式、资金来源构成(单值)、主管单位、联系人 | **D** | 单值事实,一句话即完整 |
|
||||||
|
| 本项目不涉及项、XX 不适用/暂不建设说明 | **D** | 一句话 + 依据(模板规则或需求方确认) |
|
||||||
|
| 建设单位概况、项目背景、现状概述、建设目标(总述)、组织机构、培训与管理概述、运维范围概述 | **C** | 交代清楚"是什么/现在怎样" |
|
||||||
|
| 必要性、需求分析、可行性论证、技术路线比选、方案论证、效益分析、风险与对策、性能指标论证、投资估算编制依据、运维服务必要性、SLA 设定依据、考核机制设计依据 | **B** | 必须回答"凭什么",≥200 字 |
|
||||||
|
| 编制依据、政策依据 | **A** | 列文件名称 + 文号 + 关键条款 |
|
||||||
|
| 概算/预算明细、设备清单、服务一览表、人员配置表、考核表、指标表、进度计划、培训计划表 | **A** | 考核条目完整与每行计价依据 |
|
||||||
|
| 技术实现方案、系统架构、功能设计 | **B + A** | 文字论证 ≥200 字,配置项另出清单/表 |
|
||||||
|
|
||||||
|
**标题含糊时的处理规则(按序适用)**
|
||||||
|
|
||||||
|
1. 模板带括号提示或子标题 → 按子标题定档;
|
||||||
|
2. 该节结论会被下游章节引用 → 至少 C 档;
|
||||||
|
3. 该节是本项目核心卖点(必要性 / 方案 / 效益 / 运维内容 / SLA)→ B 档;
|
||||||
|
4. 仍判不准 → 先按 C 档写,交付前按第十节门禁复核调整。
|
||||||
|
|
||||||
|
#### 7.4.3 《饱满度分档表》是阶段 0 的强制产出物
|
||||||
|
|
||||||
|
- 阶段 **0-C**(模板选择与骨架确定)时产出 `0-C-饱满度分档表.md`,与骨架一并交需求方确认;
|
||||||
|
- **未出分档表不得进入 v0.2 细化提纲**;
|
||||||
|
- 表结构(模板):
|
||||||
|
|
||||||
|
| 小节号 | 模板原文标题 | 档位 | 字数下限 | 判定依据 | 实际字数 | 是否达标 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 3.4 | 项目必要性 | B | ≥200 | Q1 是 | | |
|
||||||
|
| 3.4.1 | 建设地点 | D | ≤50 | 关键词表:单值事实 | | |
|
||||||
|
| 5.2.3 | 设备清单 | A | — | Q2 明细成列 | | |
|
||||||
|
|
||||||
|
- 成文时按表执行;交付前门禁复核"实际字数是否达标、实际档位是否与分档表一致"。
|
||||||
|
|
||||||
|
### 7.5 成文自检清单(每节完成即逐项打勾)
|
||||||
|
|
||||||
|
- [ ] 回答了"是什么 → 凭什么 → 有什么影响"三问
|
||||||
|
- [ ] 每个论断已定来源级(A/B/C),与自检表一致
|
||||||
|
- [ ] 无 7.2 表中禁用写法
|
||||||
|
- [ ] 无交叉引用
|
||||||
|
- [ ] 无未经出处的数字
|
||||||
|
- [ ] 本节档位与《饱满度分档表》一致,且字数达标(D ≤50 / C ≥100 / B ≥200 / A 条目完整)
|
||||||
|
- [ ] 引用标准均为现行有效版本
|
||||||
|
|
||||||
|
## 八、数据与口径纪律
|
||||||
|
|
||||||
|
1. 数据台账(单一真源),正文只引用台账。
|
||||||
|
2. 口径同步:改一处同步全部引用处,跨文件一致。
|
||||||
|
3. 动词口径:"提升/新增" → "维持/保持":现状已达标的只能写"维持"。
|
||||||
|
4. 禁用词门禁:废弃口径列禁用清单,交付前全文检索归零。
|
||||||
|
5. 金额纪律:单位全文统一、合计写大写、每行写计价依据、分项表与服务内容条目一一对应。
|
||||||
|
|
||||||
|
## 九、人工审校(成文后必经,AI 不替代)
|
||||||
|
|
||||||
|
AI 产出后交人工审校:数据与台账逐项核对;口径与敏感表述确认;格式与签章;逻辑通读。通过才定稿。
|
||||||
|
|
||||||
|
## 十、交付前一致性门禁
|
||||||
|
|
||||||
|
三问(钱可复算?数可溯源?重不重复?)+ 禁用词归零 + 待确认清单状态更新 + 序号图表连续无空号 + 产出后主动验证(数字核对/引用清零/口径一致性检索,不等需求方指出)。
|
||||||
|
|
||||||
|
## 十一、执行纪律
|
||||||
|
|
||||||
|
长内容分批写入并写后验证;读取最小化;文档版本化(v0.1 → v0.2 → v1.0);技能迭代 +0.0.1/+0.1 并登记;md 格式自检——标题统一 `##`/`###`、不用加粗伪标题、标题与表格前后保留空行、交付前渲染预览确认。
|
||||||
|
|
||||||
|
## 十二、版本线
|
||||||
|
|
||||||
|
v1.3.x 政务口径/排版/动态项 → v1.4.0 并入正文写作铁律 → v1.5.0 方法与项目分离 → v1.5.1 修正 Markdown 结构 → v1.5.2 第七节重构为表格式操作规范 → v1.6.0 修复符号丢失(→ / 复选框),新增第十三节落盘规范、第十四节扣分点库,补 `scripts/md2docx.py` 脚本实体 → **v1.7.0 解决"模板小节无法定档"缺口:7.4 重构为四档(D 一句话 / C ≥100 / B ≥200 / A 清单)+ 7.4.1 三问定档流程 + 7.4.2 标题关键词速查表 + 7.4.3《饱满度分档表》升为阶段 0-C 强制产出物,7.5 自检项同步改为按档位判字数**。
|
||||||
|
|
||||||
|
## 十三、阶段产物落盘规范
|
||||||
|
|
||||||
|
**总则**:每阶段产物必须落盘,口头一致不算完成。`{项目}` 为项目根目录,结构固定如下:
|
||||||
|
|
||||||
|
```
|
||||||
|
{项目}/
|
||||||
|
├─ 00-source/ 阶段0 输入资料(甲方模板/提纲/会议纪要/批复/预算清单)
|
||||||
|
├─ 01-inventory/
|
||||||
|
│ ├─ 0-A-资料登记表.md 八类登记表 + 动态项清单
|
||||||
|
│ ├─ 0-B-三张清单.md 涉及/不涉及/待确认
|
||||||
|
│ ├─ 0-C-骨架-v0.1.md 模板选择结果与骨架
|
||||||
|
│ └─ 0-C-饱满度分档表.md 逐小节档位/字数下限/判定依据(见 7.4.3)
|
||||||
|
├─ 02-draft/
|
||||||
|
│ ├─ 0-D-骨架核对与补全.md 有料/缺料标注 + 公开渠道留痕
|
||||||
|
│ ├─ 0-E-来源三元组.md 节点 → 三元组
|
||||||
|
│ ├─ v0.2-细化提纲.md
|
||||||
|
│ └─ v1.0-正文.md 分批成文的工作稿
|
||||||
|
├─ 03-docx/ md → 宋体 docx 打印稿(scripts/md2docx.py 产出)
|
||||||
|
├─ 04-review/
|
||||||
|
│ ├─ 编写依据对照自检表.md 论断 → 来源级 → 出处 → 有效性核查
|
||||||
|
│ └─ 一致性门禁-检查记录.md 三问 + 禁用词归零 + 待确认状态
|
||||||
|
└─ 05-final/ 定稿与签章版
|
||||||
|
```
|
||||||
|
|
||||||
|
**命名规则**
|
||||||
|
|
||||||
|
- 阶段编号前缀(`0-A-`/`0-B-`)与技能小节号一一对应,便于回溯;
|
||||||
|
- 版本号写在文件名尾部(`v0.1`/`v0.2`/`v1.0`),**不覆盖写**,保留全部历史版本;
|
||||||
|
- 待确认项以 `【待确认:编号】` 内联在正文,同时登记进 `0-B-三张清单.md`;闭环后更新状态(未决/已决/作废)。
|
||||||
|
|
||||||
|
**留痕纪律**
|
||||||
|
|
||||||
|
- 公开来源必须记 URL + 访问日期 + 置信度(官方文件 > 官方网站 > 权威媒体);
|
||||||
|
- 项目内部数据不得用网络资料替代,缺失即进待确认清单。
|
||||||
|
|
||||||
|
## 十四、评审高频扣分点库
|
||||||
|
|
||||||
|
完整失败案例与原文出处见 `references/review-failure-cases.md`。**每次评审被抓后,先更新该文件,再回填本表。**
|
||||||
|
|
||||||
|
| # | 扣分点 | 触发写法 | 纠正动作 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | 来源级标注缺失 | 把编制口径写成"经勘察发现" | 回 7.1 定级,改写法 |
|
||||||
|
| 2 | 无出处修饰语 | "对照等保要求""按行业通行做法" | 找真实现行出处,找不到就删 |
|
||||||
|
| 3 | 交叉引用重复/错误 | "对应 5.2.3、5.2.2、5.3.2、5.2.2" | 全文清零,对应关系改入自检表 |
|
||||||
|
| 4 | 冗余指向句 | "与附件三口径一致" | 删除 |
|
||||||
|
| 5 | 引用标准已废止 | GB/T 28181-2016 | 联网核查,改现行版(2022) |
|
||||||
|
| 6 | 推演内容带数字 | C 级论断出现百分比 | 改定性描述,或补 A 级来源 |
|
||||||
|
| 7 | 章节注水 | 声明型章节硬撑篇幅 | 按 7.4 表降档 |
|
||||||
|
| 8 | 口径不统一 | 同一数字在不同章节取值不同 | 回数据台账,全文同步 |
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# 评审高频扣分点与真实失败案例库
|
||||||
|
|
||||||
|
> 本文件是 `doc-writing-standard` 的配套参考。**每次评审被抓后先更新本文件,再回填 SKILL.md 第十四节的汇总表。**
|
||||||
|
> 更新时间:2026-09-11 · 维护:Jony
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、真实失败案例(全部在项目中被评审/需求方当场抓住)
|
||||||
|
|
||||||
|
### 案例 1:来源级标注缺失(梓潼法院安防初设 · 3.4(3))
|
||||||
|
|
||||||
|
- **原文写法**:「无主动监测告警」
|
||||||
|
- **问题**:未标性质。看似勘察发现,实为编制口径。需求方追问"这话从哪来的",无法当场回答。
|
||||||
|
- **定性**:B 级(编制口径)被写成了 A 级(事实)。
|
||||||
|
- **纠正**:回到 7.1 定级,正文改为可溯源的表述或标注编制口径;自检表登记出处。
|
||||||
|
|
||||||
|
### 案例 2:无出处修饰语(梓潼初设 · 3.6)
|
||||||
|
|
||||||
|
- **原文写法**:「对照等级保护基本要求」
|
||||||
|
- **问题**:引用"等级保护基本要求"却给不出具体标准号与版本,属于无真实出处的推断;评审一问即破。
|
||||||
|
- **纠正**:找到真实现行标准出处(写明标准号+年份)再引用;找不到就删除,改为锚定项目自身已确认口径。
|
||||||
|
|
||||||
|
### 案例 3:交叉引用重复错误(梓潼初设 · 全文)
|
||||||
|
|
||||||
|
- **原文写法**:「对应 5.2.3、5.2.2、5.3.2、5.2.2」
|
||||||
|
- **问题**:5.2.2 重复出现;章节号还会随排版变动而失效,交叉引用必然出错。
|
||||||
|
- **纠正**:全文检索「详见第」「对应」并清零;章节间对应关系只在《编写依据对照自检表》维护,正文自成一体。
|
||||||
|
|
||||||
|
### 案例 4:冗余指向句(梓潼初设 · 结论段)
|
||||||
|
|
||||||
|
- **原文写法**:「与附件三口径一致」
|
||||||
|
- **问题**:需求方判为"多余"。口径对应关系属于编写层信息,不该进正文。
|
||||||
|
- **纠正**:删除。口径一致性在自检表维护。
|
||||||
|
|
||||||
|
### 案例 5:引用标准已废止(梓潼初设 · 引用清单)
|
||||||
|
|
||||||
|
- **原文写法**:`GB/T 28181-2016`
|
||||||
|
- **问题**:该标准已被 2022 版代替,编制时未察觉。
|
||||||
|
- **纠正**:引用标准一律联网核查现行有效性;被代替/废止的必须更正为现行版本并记录核查日期。
|
||||||
|
|
||||||
|
### 案例 6:章节注水(梓潼初设 · 声明型章节)
|
||||||
|
|
||||||
|
- **表现**:声明型/占位型章节(如"本项目不涉及此项")被硬撑成整段篇幅。
|
||||||
|
- **问题**:饱满度与章节职能不匹配,读起来"虚"。
|
||||||
|
- **纠正**:按 7.4 表降档——声明型一句话+依据即可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、docx 落地技术红线(卫健委运维方案项目实战)
|
||||||
|
|
||||||
|
转 Word 阶段踩过的坑,与内容无关但会直接导致交付失败:
|
||||||
|
|
||||||
|
| # | 红线 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | 非 ASCII 符号经有损编码会**直接丢失** | 曾出现全文 `→`、`☐` 被吞掉只剩双空格(本文档 v1.5.2 即受害),落地前必须逐字符核验 |
|
||||||
|
| 2 | Windows 下 python 脚本一律写 `.py` 文件执行 | 内联 `-c` 易踩引号/转义地狱 |
|
||||||
|
| 3 | XML 插入锚点不能以 `<w:p ...>` 开头结尾夹住插入点 | 会把内容插进段落内部产生非法嵌套 `<w:p>`;锚点应以 `</w:p>` 结尾 |
|
||||||
|
| 4 | `PYTHONUTF8=1` | 不设会出现编码相关的诡异报错 |
|
||||||
|
| 5 | 字体四处全设 | `w:ascii` / `w:hAnsi` / `w:eastAsia` / `w:cs`,只设 `font.name` 会回落成等线/Calibri |
|
||||||
|
| 6 | 首行缩进用 `Pt(24)` | 小四 12pt × 2 字符;不要用字符数 API,跨版本不稳 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、扣分点自查速查(交付前逐项过)
|
||||||
|
|
||||||
|
- [ ] 每个论断都能回答"这话从哪来的"(A/B/C 已定级)
|
||||||
|
- [ ] 无「详见第 X 章」「对应 X.X 节」「与附件 X 口径一致」
|
||||||
|
- [ ] 无「按行业通行做法」「对照 XX 要求」这类无出处修饰语
|
||||||
|
- [ ] 引用标准均为现行有效版本(已联网核查,记核查日期)
|
||||||
|
- [ ] C 级推演内容不含数字
|
||||||
|
- [ ] 同一数字在不同章节取值一致(回数据台账核对)
|
||||||
|
- [ ] 声明型章节没有注水
|
||||||
|
- [ ] 正文文件无符号丢失(`→` / `☐` 等非 ASCII 符号在位)
|
||||||
|
- [ ] 待确认清单状态已更新(未决 / 已决 / 作废)
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""md2docx.py — 方案类文档 Markdown → Word(宋体 / 小四 / 首行缩进 2 字符 / 1.5 倍行距)
|
||||||
|
|
||||||
|
用法(Windows,务必先设 UTF-8):
|
||||||
|
set PYTHONUTF8=1
|
||||||
|
python scripts/md2docx.py 输入.md 输出.docx
|
||||||
|
|
||||||
|
依赖:
|
||||||
|
pip install python-docx
|
||||||
|
|
||||||
|
说明:
|
||||||
|
只负责排版落地,不改动内容。
|
||||||
|
支持: 标题(#~####)、正文段落、管道表格、无序/有序列表、- [ ] 复选框、**加粗**、代码块。
|
||||||
|
复杂合并单元格、图片、公式请在 Word 中人工微调。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from docx import Document
|
||||||
|
from docx.enum.table import WD_TABLE_ALIGNMENT
|
||||||
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||||
|
from docx.oxml.ns import qn
|
||||||
|
from docx.shared import Cm, Pt
|
||||||
|
|
||||||
|
# ==================== 可按甲方模板调整的参数 ====================
|
||||||
|
FONT_NAME = '宋体' # 中西文统一宋体
|
||||||
|
BODY_SIZE = Pt(12) # 小四 = 12pt
|
||||||
|
FIRST_LINE_INDENT = Pt(24) # 首行缩进 2 字符(2 x 12pt)
|
||||||
|
LINE_SPACING = 1.5 # 行间距 1.5 倍
|
||||||
|
HEADING_SIZES = {1: Pt(16), 2: Pt(15), 3: Pt(14), 4: Pt(12)}
|
||||||
|
HEADING_ALIGN_CENTER = {1} # 一级标题居中
|
||||||
|
TABLE_FONT_SIZE = Pt(12)
|
||||||
|
TABLE_HEADER_BOLD = True
|
||||||
|
CODE_FONT_SIZE = Pt(10.5)
|
||||||
|
PAGE_WIDTH, PAGE_HEIGHT = Cm(21), Cm(29.7) # A4
|
||||||
|
MARGIN_TB, MARGIN_LR = Cm(2.54), Cm(3.17)
|
||||||
|
# ================================================================
|
||||||
|
|
||||||
|
CHECKBOX = {False: '\u2610', True: '\u2611'} # ☐ / ☑
|
||||||
|
|
||||||
|
|
||||||
|
def set_run_font(run, size=None, bold=None):
|
||||||
|
"""四处字体全设,避免 Word 回落到等线 / Calibri 造成字体不统一。"""
|
||||||
|
run.font.name = FONT_NAME
|
||||||
|
rpr = run._element.get_or_add_rPr()
|
||||||
|
rfonts = rpr.find(qn('w:rFonts'))
|
||||||
|
if rfonts is None:
|
||||||
|
rfonts = rpr.makeelement(qn('w:rFonts'), {})
|
||||||
|
rpr.append(rfonts)
|
||||||
|
rfonts.set(qn('w:ascii'), FONT_NAME)
|
||||||
|
rfonts.set(qn('w:hAnsi'), FONT_NAME)
|
||||||
|
rfonts.set(qn('w:eastAsia'), FONT_NAME)
|
||||||
|
rfonts.set(qn('w:cs'), FONT_NAME)
|
||||||
|
if size is not None:
|
||||||
|
run.font.size = size
|
||||||
|
if bold is not None:
|
||||||
|
run.font.bold = bold
|
||||||
|
|
||||||
|
|
||||||
|
def add_runs(paragraph, text, size, bold=False):
|
||||||
|
"""把 **加粗** 解析成多个 run。"""
|
||||||
|
for piece in re.split(r'(\*\*.+?\*\*)', text):
|
||||||
|
if not piece:
|
||||||
|
continue
|
||||||
|
if piece.startswith('**') and piece.endswith('**') and len(piece) > 4:
|
||||||
|
set_run_font(paragraph.add_run(piece[2:-2]), size, True)
|
||||||
|
else:
|
||||||
|
set_run_font(paragraph.add_run(piece), size, bold)
|
||||||
|
|
||||||
|
|
||||||
|
def add_body(doc, text):
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
pf = p.paragraph_format
|
||||||
|
pf.first_line_indent = FIRST_LINE_INDENT
|
||||||
|
pf.line_spacing = LINE_SPACING
|
||||||
|
add_runs(p, text, BODY_SIZE)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def add_heading(doc, text, level):
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
pf = p.paragraph_format
|
||||||
|
pf.line_spacing = LINE_SPACING
|
||||||
|
pf.space_before = Pt(6)
|
||||||
|
pf.space_after = Pt(6)
|
||||||
|
if level in HEADING_ALIGN_CENTER:
|
||||||
|
pf.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||||
|
add_runs(p, text, HEADING_SIZES.get(level, BODY_SIZE), True)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def add_list_item(doc, text, prefix='\u2022 '):
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
pf = p.paragraph_format
|
||||||
|
pf.left_indent = FIRST_LINE_INDENT
|
||||||
|
pf.line_spacing = LINE_SPACING
|
||||||
|
add_runs(p, prefix + text, BODY_SIZE)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def is_table_sep(line):
|
||||||
|
s = line.strip()
|
||||||
|
return bool(s) and set(s) <= set('|-: ') and '-' in s
|
||||||
|
|
||||||
|
|
||||||
|
def split_row(line):
|
||||||
|
s = line.strip()
|
||||||
|
if s.startswith('|'):
|
||||||
|
s = s[1:]
|
||||||
|
if s.endswith('|'):
|
||||||
|
s = s[:-1]
|
||||||
|
return [c.strip() for c in s.split('|')]
|
||||||
|
|
||||||
|
|
||||||
|
def add_table(doc, rows):
|
||||||
|
cols = max(len(r) for r in rows)
|
||||||
|
table = doc.add_table(rows=0, cols=cols)
|
||||||
|
table.style = 'Table Grid'
|
||||||
|
table.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||||
|
for i, row in enumerate(rows):
|
||||||
|
cells = table.add_row().cells
|
||||||
|
for j in range(cols):
|
||||||
|
text = row[j] if j < len(row) else ''
|
||||||
|
para = cells[j].paragraphs[0]
|
||||||
|
para.paragraph_format.line_spacing = LINE_SPACING
|
||||||
|
add_runs(para, text, TABLE_FONT_SIZE, bold=(i == 0 and TABLE_HEADER_BOLD))
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_links(text):
|
||||||
|
text = re.sub(r'!\[([^\]]*)\]\([^)]*\)', r'\1', text) # 图片 -> alt 文本
|
||||||
|
text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1(\2)', text) # 链接 -> 文本(URL)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def setup_document():
|
||||||
|
doc = Document()
|
||||||
|
style = doc.styles['Normal']
|
||||||
|
style.font.name = FONT_NAME
|
||||||
|
style.font.size = BODY_SIZE
|
||||||
|
try:
|
||||||
|
style.element.get_or_add_rPr().get_or_add_rFonts().set(qn('w:eastAsia'), FONT_NAME)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
sec = doc.sections[0]
|
||||||
|
sec.page_width, sec.page_height = PAGE_WIDTH, PAGE_HEIGHT
|
||||||
|
sec.top_margin = sec.bottom_margin = MARGIN_TB
|
||||||
|
sec.left_margin = sec.right_margin = MARGIN_LR
|
||||||
|
return doc
|
||||||
|
|
||||||
|
|
||||||
|
def convert(md_path, docx_path):
|
||||||
|
with open(md_path, encoding='utf-8') as f:
|
||||||
|
lines = f.read().split('\n')
|
||||||
|
|
||||||
|
# 跳过 YAML frontmatter(技能元数据不进正文)
|
||||||
|
start = 0
|
||||||
|
if lines and lines[0].strip() == '---':
|
||||||
|
for k in range(1, len(lines)):
|
||||||
|
if lines[k].strip() == '---':
|
||||||
|
start = k + 1
|
||||||
|
break
|
||||||
|
|
||||||
|
doc = setup_document()
|
||||||
|
i, in_code = start, False
|
||||||
|
|
||||||
|
while i < len(lines):
|
||||||
|
line = lines[i].rstrip()
|
||||||
|
stripped = line.strip()
|
||||||
|
|
||||||
|
# 代码块
|
||||||
|
if stripped.startswith('```'):
|
||||||
|
in_code = not in_code
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
if in_code:
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
p.paragraph_format.line_spacing = 1.0
|
||||||
|
p.paragraph_format.left_indent = FIRST_LINE_INDENT
|
||||||
|
add_runs(p, line, CODE_FONT_SIZE)
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not stripped:
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 标题
|
||||||
|
m = re.match(r'^(#{1,6})\s+(.*)$', stripped)
|
||||||
|
if m:
|
||||||
|
add_heading(doc, m.group(2).strip(), len(m.group(1)))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 表格
|
||||||
|
if '|' in stripped and i + 1 < len(lines) and is_table_sep(lines[i + 1]):
|
||||||
|
rows = []
|
||||||
|
while i < len(lines) and '|' in lines[i]:
|
||||||
|
if not is_table_sep(lines[i]):
|
||||||
|
rows.append(split_row(lines[i]))
|
||||||
|
i += 1
|
||||||
|
if rows:
|
||||||
|
add_table(doc, rows)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 分隔线
|
||||||
|
if re.match(r'^([-*_]\s*){3,}$', stripped):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 复选框(必须早于普通列表判断)
|
||||||
|
m = re.match(r'^[-*+]\s+\[([ xX])\]\s*(.*)$', stripped)
|
||||||
|
if m:
|
||||||
|
add_list_item(doc, normalize_links(m.group(2)),
|
||||||
|
prefix=CHECKBOX[m.group(1).lower() == 'x'] + ' ')
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 无序列表
|
||||||
|
m = re.match(r'^[-*+]\s+(.*)$', stripped)
|
||||||
|
if m:
|
||||||
|
add_list_item(doc, normalize_links(m.group(1)))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 有序列表
|
||||||
|
m = re.match(r'^(\d+)[.)]\s+(.*)$', stripped)
|
||||||
|
if m:
|
||||||
|
add_list_item(doc, normalize_links(m.group(2)), prefix=m.group(1) + '. ')
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 引用
|
||||||
|
if stripped.startswith('>'):
|
||||||
|
add_body(doc, normalize_links(stripped.lstrip('>').strip()))
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 普通正文
|
||||||
|
add_body(doc, normalize_links(stripped))
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
doc.save(docx_path)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
md_path, docx_path = sys.argv[1], sys.argv[2]
|
||||||
|
if not os.path.isfile(md_path):
|
||||||
|
print('输入文件不存在: %s' % md_path)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
out_dir = os.path.dirname(os.path.abspath(docx_path))
|
||||||
|
if out_dir and not os.path.isdir(out_dir):
|
||||||
|
os.makedirs(out_dir)
|
||||||
|
|
||||||
|
convert(md_path, docx_path)
|
||||||
|
print('已生成: %s' % docx_path)
|
||||||
|
print('字体=%s 正文=%s 首行缩进=%s 行距=%s' %
|
||||||
|
(FONT_NAME, BODY_SIZE.pt, FIRST_LINE_INDENT.pt, LINE_SPACING))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user