feat: Phase 2 complete — 13 Phases of COBOL type classification and test benchmark

P0.6: gcov infrastructure
P1: extract_structure output expansion (11 new feature fields)
P2: Confusion group rule engine (8 pairs + contradiction + backtrack)
P3: 4-factor confidence calculation + quality gate update
P4: 33+2 COBOL program type test samples (22 files, 7 categories)
P5: parametrized/ test data generation engine
P6: japanese_data.py lookup tables
P7-10: Type-specific test suites (~159 parametrized tests)
P11: Full classification pipeline (classify_program) + orchestrator integration
P12: Documentation (module-interfaces, test-plan v3.0, coverage-matrix)

Architecture decisions:
- classification_pipeline/ merged to hina/pipeline/
- parametrized/ as independent module
- japanese_data.py as root-level file
- hina/__all__ only exports classify_program()

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
hangshuo652
2026-06-19 23:51:55 +08:00
parent 63b5284715
commit bc1d56d1a4
129 changed files with 19378 additions and 261 deletions
+1239
View File
@@ -0,0 +1,1239 @@
# COBOL 迁移验证平台 第二阶段设计书
> 版本: v2.0 | 日期: 2026-06-19
> 基于: cobol-test-benchmark.md 的 33+2 程序类型分类体系
> 范围: 12 个 Phase,从类型判定引擎完善到完整测试基准实现
---
## 目录
1. [设计总则](#1-设计总则)
2. [Phase 1: extract_structure 输出扩展](#2-phase-1-extract_structure-输出扩展)
3. [Phase 2: 混淆组判定规则引擎](#3-phase-2-混淆组判定规则引擎)
4. [Phase 3: 确信度 4 因子计算](#4-phase-3-确信度-4-因子计算)
5. [Phase 4: 33+2 种程序类型 COBOL 测试样本](#5-phase-4-332-种程序类型-cobol-测试样本)
6. [Phase 5: 参数化测试数据生成引擎](#6-phase-5-参数化测试数据生成引擎)
7. [Phase 6: 日文测试数据生成查找表](#7-phase-6-日文测试数据生成查找表)
8. [Phase 7-10: 类型别测试套件](#8-phase-7-10-类型别测试套件)
9. [Phase 11: 完整类型判定管道](#9-phase-11-完整类型判定管道)
10. [Phase 12: 文档更新](#10-phase-12-文档更新)
11. [依赖关系与分工矩阵](#11-依赖关系与分工矩阵)
12. [接口变更一览](#12-接口变更一览)
13. [COBOL 覆盖率测试体系](#13-cobol-覆盖率测试体系)
14. [架构审核决议汇总](#14-架构审核决议汇总)
---
## 1. 设计总则
### 1.1 新增 Phase 0.6: gcov 基础设施
> 在 Phase 1 之前完成,为所有类型测试提供 gcov 能力。
> 负责: F | 工作量: 3h
为覆盖率测试体系提供可自动化运行的基础设施。Phase 7-10 中所有 gcov 测试的前置条件。
| 步骤 | 内容 | 工作量 |
|:-----|:-----|:------|
| 1 | `cobc --coverage` 环境验证自动化 | 0.5h |
| 2 | `collect_gcov()` 路径修复(含中文目录兼容)| 1h |
| 3 | `Config` 追加 gcov_enabled / gcov_work_dir / gcov_threshold | 0.5h |
| 4 | `test_gcov_basic.py` — gcov 全链路验证测试 | 1h |
**验收**: cobc --coverage 编译 → 运行 → .gcda 生成 → collect_gcov() line_rate > 0
```python
# config/__init__.py — Config 新增字段
gcov_enabled: bool = False
gcov_work_dir: str = ".gcov_output"
gcov_threshold: float = 0.5
```
### 1.3 分层原则
```
Layer 1: data/ — 所有模块共享的数据契约
Layer 2: 核心引擎 — cobol_testgen/ config/ jcl/ quality/ report/ preprocessor/
Layer 3: 业务引擎 — hina/ agents/ comparator/ runners/
Layer 4: 管道集成 — orchestrator/ web/
依赖方向: Layer 1 ← Layer 2 ← Layer 3 ← Layer 4
禁止逆向依赖。
```
### 1.4 模块通信规则
- 所有模块间通信通过 `data/` 层的数据类进行
- 每个模块的公开 API 由 `__init__.py``__all__` 定义
- 禁止钻入模块内部(如 `from cobol_testgen.coverage import ...`
- 详见 `CONTRIBUTING.md`
### 1.5 最终模块布局(经架构审核确认)
```
项目根目录/
├── cobol_testgen/ ← COBOL 解析引擎 (P1扩展)
├── hina/
│ ├── rule_engine/ ← 混淆组规则引擎 (P2)
│ ├── confidence.py ← 确信度 4 因子计算 (P3)
│ └── pipeline/ ← 完整类型判定管道 (P11)
├── parametrized/ ← 独立模块!参数化测试数据生成引擎 (P5)
│ ├── __init__.py
│ ├── matching.py
│ ├── division.py
│ └── common.py
├── japanese_data.py ← 独立文件!日文测试数据查找表 (P6)
├── test-data/cobol/ ← 新增 33+2 种 COBOL 样本 (P4)
├── tests/
│ └── parametrized/ ← 类型别测试套件 (P7-10)
└── docs/ ← 文档更新 (P12)
重要决策:
✅ classification_pipeline/ → 合并到 hina/pipeline/
✅ parametrized/ → 独立模块(项目根目录)
✅ japanese_data.py → 独立文件(项目根目录)
```
---
## 2. Phase 1: extract_structure 输出扩展
### 2.1 目的
当前 `extract_structure()` 输出的结构特征不足以判定 33+2 种程序类型。需要增加以下字段。
### 2.2 新增输出字段
`cobol_testgen/__init__.py``extract_structure()` 返回字典中追加:
```python
# 新增字段(原有字段不变)
{
# ── 文件相关 ──
"select_files": { # SELECT 语句列表
"INFILE": {"assign_to": "INPUT.DAT", "organization": "SEQUENTIAL"},
"OUTFILE": {"assign_to": "OUTPUT.DAT", "organization": "SEQUENTIAL"},
},
"open_directions_detail": { # OPEN 方向详情
"INFILE": "INPUT",
"OUTFILE": "OUTPUT",
"WORKFILE": "I-O",
},
# ── DIVIDE 语句检测 ──
"has_divide": False, # 是否有 DIVIDE 语句
"divide_constants": [], # DIVIDE 的被除数列表: [50, 25, 100]
# ── INSPECT/STRING 语句检测 ──
"has_inspect": False, # 是否有 INSPECT 语句
"has_string": False, # 是否有 STRING 语句
# ── PERFORM 模式分类 ──
"perform_patterns": [ # 每个 PERFORM 的模式
{"type": "inline", "target": None, "condition": None}, # inline / paragraph / thru / varying / times
{"type": "varying", "target": "WS-I", "condition": "WS-I > 100"},
{"type": "times", "times": 50},
{"type": "until", "condition": "WS-A > 5"},
{"type": "thru", "target": "PARA-A", "thru": "PARA-C"},
],
# ── 主循环定位(含 READ 语句的 PERFORM 块)──
"main_loop": { # 主循环信息(None=无循环)
"type": "perform_until", # perform_until / perform_varying / read_loop
"read_file": "INFILE", # 在该循环中 READ 的文件
"has_at_end": True, # 是否有 AT END 处理
"at_end_action": "MOVE 'Y' TO WS-EOF", # AT END 处理内容
},
# ── IF 分支类型统计 ──
"if_types": {
"total": 3, # IF 总数
"comparison": 2, # 比较型 (>, <, >=, <=)
"equality": 1, # 等值型 (=)
"compound": 1, # 复合型 (AND/OR)
"nested_depth": 2, # 最大嵌套深度
},
# ── 变量命名模式检测 ──
"variable_patterns": {
"has_prev_key": True, # WS-PREV-* 模式变量
"has_accumulator": True, # WS-*CNT / WS-*SUM 模式变量
"has_error_field": False, # WS-ERR* / WS-MSG* 模式变量
"has_key_field": True, # WS-*KEY 模式变量
"prev_key_fields": ["WS-PREV-KEY"], # 具体的前键值字段名
"accumulator_fields": ["WS-REC-CNT"], # 具体的累加器字段名
},
# ── OPEN 模式 ──
"open_pattern": "sequential", # sequential / reopen(OPEN→CLOSE→再OPEN)
}
```
### 2.3 实现位置
| 新增特征 | 实现文件 | 实现方法 |
|:---------|:---------|:---------|
| SELECT 文件详情 | `read.py``parse_file_control()` 扩展 | 追加 organization 字段 |
| DIVIDE/INSPECT/STRING | `core.py` `_BrParser` | 添加 IF 语句解析 |
| PERFORM 模式分类 | `core.py` `_BrParser` | BrPerform 属性已存在 |
| 主循环定位 | `core.py` 新函数 `locate_main_loop()` | 搜索含 READ 的 PERFORM 块 |
| IF 类型统计 | `core.py` 新函数 `stat_if_types()` | 遍历 BrIf 的 condition |
| 变量命名模式 | `core.py` 新函数 `detect_variable_patterns()` | 正则匹配字段名 |
| OPEN 模式 | `read.py` 新函数 `detect_open_pattern()` | 检查 OPEN→CLOSE→OPEN |
### 2.4 接口变更
```python
# cobol_testgen/__init__.py — __all__ 不变
# extract_structure() 签名不变,返回字典追加新字段
# 现有调用者不受影响(dict.get() 返回 None 获得默认值)
```
---
## 3. Phase 2: 混淆组判定规则引擎
### 3.1 新模块 `hina/rule_engine/`
创建独立子模块,与现有的 `classifier.py` 互补:
```
hina/
├── __init__.py # 导出 rule_engine 的 API
├── classifier.py # 现有(不变)
├── rule_engine/ # 新增
│ ├── __init__.py
│ ├── confusion_groups.py # 8 混淆组的规则实现
│ ├── contradiction.py # 矛盾检测
│ └── backtrack.py # 回溯机制
```
### 3.2 8 混淆组规则
```python
# hina/rule_engine/confusion_groups.py
def resolve_confusion_pair(features: dict, pair_name: str) -> dict:
"""解决一对混淆组,返回判定结果。
参数:
features — extract_structure() 输出的结构特征
pair_name — 混淆对名称:
"matching_vs_keybreak"
"dedup_vs_nodedup"
"validation_vs_keybreak"
"csv_merge_vs_split"
"simple_vs_two_stage"
"pure_vs_mixed"
"division_50_25_100"
"mn_output_mode"
返回:
{"resolved_type": str, "confidence": float, "evidence": list}
"""
# 规则实现示例 ── "matching_vs_keybreak"
def _matching_vs_keybreak(features: dict) -> dict:
"""匹配 vs key切
判定逻辑:
1. SELECT 文件数 < 2 → 排除匹配 → key切
2. IF 类型统计中 3 路 IF(comparison) 占比 > 50% → 匹配
3. 2 路 IF(equality) 为主 + WS-PREV-KEY 存在 → key切
4. 有累加器(WS-*CNT) + WS-PREV-KEY + 2 路 IF → key切
5. 输入文件 ≥ 2 + 3 路 IF → 匹配
6. 无法确定 → 回退到 conflict_score
"""
file_count = len(features.get("select_files", {}))
if_types = features.get("if_types", {})
var_patterns = features.get("variable_patterns", {})
evidence = []
if file_count >= 2:
evidence.append("file_count>=2 → possible matching")
comp_ratio = if_types.get("comparison", 0) / max(if_types.get("total", 1), 1)
if comp_ratio > 0.5:
evidence.append("comparison IF ratio > 50% → matching signature")
if var_patterns.get("has_prev_key") and var_patterns.get("has_accumulator"):
evidence.append("WS-PREV-KEY + accumulator → keybreak signature")
# 综合判断
matching_score = sum(1 for e in evidence if "matching" in e)
keybreak_score = sum(1 for e in evidence if "keybreak" in e)
if matching_score > keybreak_score:
return {"resolved_type": "マッチング", "confidence": 0.7 + matching_score * 0.1,
"evidence": evidence}
elif keybreak_score > matching_score:
return {"resolved_type": "キーブレイク", "confidence": 0.7 + keybreak_score * 0.1,
"evidence": evidence}
else:
return {"resolved_type": "unknown", "confidence": 0.5, "evidence": evidence}
```
### 3.3 矛盾检测
```python
# hina/rule_engine/contradiction.py
# 7 个矛盾对
CONTRADICTION_PAIRS = [
("matching_vs_keybreak", {
"type_a": "マッチング",
"type_b": "キーブレイク",
"rule": lambda f: f.get("variable_patterns", {}).get("has_prev_key"),
"tiebreaker": "file_count", # file_count ≥ 2 → matching wins
}),
("dedup_vs_nodedup", {
"type_a": "項目チェック(重複含む)",
"type_b": "項目チェック(重複含まず)",
"rule": lambda f: f.get("variable_patterns", {}).get("has_prev_key"),
"tiebreaker": "prev_key_exists", # WS-PREV-KEY → 含重复 wins
}),
("validation_vs_keybreak", {
"type_a": "項目チェック",
"type_b": "キーブレイク",
"rule": lambda f: f.get("variable_patterns", {}).get("has_error_field"),
"tiebreaker": "has_error_field", # WS-ERR* → 校验 wins; WS-*CNT → key切 wins
}),
# ... 其余 4 个
]
def detect_contradictions(features: dict, candidates: list[str]) -> list[dict]:
"""检测候选类型中的矛盾对,返回矛盾列表。"""
def resolve_contradiction(features: dict, contradiction: dict) -> str:
"""使用 tiebreaker 规则解决单个矛盾。"""
```
### 3.4 回溯机制
```python
# hina/rule_engine/backtrack.py
class BacktrackResolver:
"""当混淆组判定进入死胡同时,回溯到 extract_structure 重新提取特征。"""
def __init__(self, structure_extractor: callable):
self.extract = structure_extractor
self.max_rounds = 3
def resolve(self, cobol_source: str, initial_features: dict) -> dict:
"""多轮判定。每轮检测矛盾→回溯→重新提取→重新判定。"""
features = initial_features
for round_num in range(self.max_rounds):
# Step 1: 检测矛盾
contradictions = detect_contradictions(features, candidates)
if not contradictions:
# 无矛盾,返回最终结果
return self._finalize(features)
# Step 2: 解析矛盾
for c in contradictions:
resolution = resolve_contradiction(features, c)
# Step 3: 如果需要更多信息,回溯重新提取
if self._needs_backtrack(contradictions):
refined_source = self._refine_extraction(cobol_source, contradictions)
features = self.extract(refined_source)
return self._finalize_with_warning(features)
```
### 3.5 接口变更
```python
# hina/__init__.py — __all__ 追加
"resolve_confusion_pair", # (features, pair_name) → dict
"detect_contradictions", # (features, candidates) → list[dict]
"BacktrackResolver", # class — 多轮判定
```
---
## 4. Phase 3: 确信度 4 因子计算
### 4.1 新函数
`hina/classifier.py` 中新增确信度计算函数,或者创建 `hina/confidence.py`
```python
# hina/confidence.py — 新增文件
def compute_confidence_v2(
keyword_result: dict, # detect_keyword() 的输出
structure_features: dict, # extract_structure() 的输出
contradictions: list[dict], # contradiction.detect_contradictions() 的输出
resolution: dict # confusion_groups 的输出
) -> dict:
"""四因子确信度计算。
公式:
confidence = base × context_factor × consistency_factor × structure_factor
参数:
keyword_result — {matches: [(category, confidence, keyword)], ...}
structure_features — extract_structure 输出的完整字典
contradictions — 矛盾列表
resolution — 混淆组解决结果
返回:
{
"confidence": float, # 最终确信度 (0~1)
"base": float, # 基础确信度
"context_factor": float, # 上下文因子
"consistency_factor": float, # 一致性因子
"structure_factor": float, # 结构一致性因子
"judgment": str, # "auto" / "review" / "manual" / "impossible"
"needs_review": bool,
}
"""
```
### 4.2 因子定义
```
基础确信度:
L1 关键字规则对应的基准确信度 (0.70~0.99)
DB操作=0.95, SORT=0.95, CALL=0.90, 编辑输出=0.80, ...
上下文因子:
关键字匹配数 ≥ 3 → 1.0
关键字匹配数 = 2 → 0.95
关键字匹配数 = 1 → 0.90
需要上下文确认 → 0.50
一致性因子:
无矛盾 → 1.0
有矛盾已解决 → 0.90
有矛盾未解决 → 0.80
多重矛盾 (≥3) → 0.50
结构一致性因子:
结构完全匹配 (5/5 特征一致) → 1.0
部分一致 (3-4/5) → 0.7
少量一致 (1-2/5) → 0.5
无法确定 → 0.3
综合判定:
≥ 90% → 自动判定 ("auto")
70-89% → 自动判定 + 建议 Review ("review")
50-69% → Agent 提案 + 人工确认 ("manual")
< 50% → 判定不可,全部人工 ("impossible")
```
### 4.3 接口变更
```python
# hina/__init__.py — __all__ 追加
"compute_confidence_v2", # 四因子确信度计算
"compute_confidence", # 已有函数保持不动(旧版调用者不受影响)
```
### 4.4 质量门禁公式更新(gcov 集成)
Phase 0.6 完成后,`hina/gate.py` 的评分公式改为双模式:
```
当前(gcov 未启用):
quality_score = branch_rate×0.5 + paragraph_rate×0.5 + confidence×0.4
新增 quality_score_v2gcov 启用时):
quality_score_v2 = static_cov×0.3 + gcov_cov×0.4 + confidence×0.3
```
- 静态覆盖率 30% — 快速参考,验证数据生成完整性
- gcov 动态覆盖率 **40%** — 权重最高,代表真实执行结果
- HINA 确信度 30%
**新增文件**: `coverage/compare_coverage.py` — 对比静态与 gcov 覆盖率,定位虚假覆盖
```python
def compare_coverage(program_name: str) -> dict:
"""返回 {static, dynamic, gap, misleading_branches}"""
```
---
## 5. Phase 4: 33+2 种程序类型 COBOL 测试样本
### 5.1 目录结构
```
test-data/cobol/ # 已有 HINA001~101 保留
├── HINA001.cbl # 已有
├── ...
├── HINA101.cbl # 已有
├── category_matching/ # 匹配系 (10种)
│ ├── MT01_1TO1.cbl
│ ├── MT02_1TON.cbl
│ ├── MT03_NTO1.cbl
│ ├── MT16_TWO_STAGE_1TO1.cbl
│ ├── MT17_TWO_STAGE_NTO1.cbl
│ ├── MT18_MN_TO_M.cbl
│ ├── MT19_MN_TO_N.cbl
│ ├── MT20_MN_TO_MXN.cbl
│ ├── MT32_MIXED_SAME_KEY.cbl
│ └── MT33_MIXED_DIFF_KEY.cbl
├── category_sort/ # SORT/ MERGE (2种)
│ ├── ST01_SORT.cbl
│ └── ST02_MERGE.cbl
├── category_division/ # 分割系 (3种)
│ ├── DV01_DIVIDE_50.cbl
│ ├── DV02_DIVIDE_25.cbl
│ └── DV03_DIVIDE_100.cbl
├── category_validation/ # 校验 (1种,补充)
│ ├── VL01_CHECK_WITH_DUP.cbl
│ └── VL02_CHECK_NO_DUP.cbl
├── category_csv/ # 文件转换 (3种)
│ ├── CV01_CSV_NO_NEWLINE.cbl
│ ├── CV02_CSV_WITH_NEWLINE.cbl
│ └── CV03_ASCII_EBCDIC.cbl
├── category_cics/ # online (1种)
│ └── CI01_CICS.cbl
└── category_db/ # DB操作 (1种,补充)
└── DB01_SELECT_UPDATE.cbl
```
### 5.2 样本规范
每个 COBOL 测试样本必须:
1. **可编译** — 用 `cobc -x -std=ibm-strict` 编译通过
2. **10-50 行** — 足够表达类型特征,不要过大
3. **包含关键特征** — 每种类型独有的关键字和结构模式
4. **有注释** — 开头的星号注释说明类型编号和名称
5. **HEADER 注释**:
```cobol
* ==== TYPE: MT01 マッチング(1:1) ====
* 特征: 2 输入文件 SELECT, IF KEY = 比较, 3路 IF, 无累加器
* BRANCHES: 4 (2 IFs), DECISIONS: 2
* SELECT COUNT: 2, OPEN COUNT: 2
```
### 5.3 实现顺序
按依赖关系分 3 批创建:
```
第一批 (Phase 4a): 匹配系 10 种 + SORT/MERGE 2 种
依赖: 这 12 个样本是 Phase 7-8 测试的基础
第二批 (Phase 4b): 分割系 3 种 + 校验 2 种 + 文件转换 3 种
依赖: 这 8 个样本是 Phase 7 测试的基础
第三批 (Phase 4c): CICS 1 种 + DB 1 种
依赖: 需要模拟器环境,可先做代码样本,延迟测试
```
---
## 6. Phase 5: 参数化测试数据生成引擎
### 6.1 独立模块 `parametrized/`(项目根目录)
```
项目根目录/
├── parametrized/ ← 独立!不是 cobol_testgen 的子模块
│ ├── __init__.py
│ ├── matching.py # 匹配系数据生成
│ ├── sort.py # SORT 数据生成
│ ├── division.py # 分割系数据生成
│ ├── validation.py # 校验系数据生成
│ ├── csv_conversion.py # CSV→FB 数据生成
│ └── common.py # 通用工具
依赖方向:
parametrized/ → cobol_testgen (需要 PIC 解析算边界值)
parametrized/ → data/ (构造 Field/TestCase 对象)
cobol_testgen → parametrized ❌ 禁止
```
**理由**parametrized/ 的输入是数值参数(记录数、匹配率、不平衡比),不是 COBOL 源码。放在 cobol_testgen/ 下会使 COBOL 解析引擎依赖测试工具。独立模块保持分层干净。
### 6.2 类型专属参数化
```python
# cobol_testgen/parametrized/matching.py
def generate_matching_data(
matching_type: str, # "1:1" / "1:N" / "N:1"
record_count_r01: int,
record_count_r02: int,
key_match_ratio: float = 1.0, # 匹配率(用于剩余件测试)
imbalance_ratio: float = 1.0, # 不平衡比
) -> tuple[list[dict], list[dict]]:
"""生成匹配系测试数据。
返回:
(主文件记录列表, 从件记录列表)
文件间通过 KEY 字段关联。
"""
def generate_keybreak_data(
group_count: int, # key 组数
records_per_group: int, # 每组件数
sum_type: str = "accumulate", # "accumulate" / "aggregate" / "mark"
) -> list[dict]:
"""生成 key 切测试数据。
返回:
按 KEY 分组的数据,组间 KEY 值变化触发中断。
"""
# cobol_testgen/parametrized/division.py
def generate_division_data(
division_type: int, # 50 / 25 / 100
record_count: int, # 总件数(整数倍/余数/不足)
) -> list[list[dict]]:
"""生成分割系测试数据。
返回:
按分割文件分组的记录列表:
[[文件1的记录], [文件2的记录], ...]
文件数 = ceil(record_count / division_type)
"""
```
### 6.3 通用数据生成工具
```python
# cobol_testgen/parametrized/common.py
def generate_zero_byte_file(path: str):
"""生成 0 字节空文件(VSAM 空 cluster 或顺序 0 字节)。"""
def generate_status_35_scenario(path: str):
"""STATUS 35 场景:不生成文件,让 OPEN 找不到 DD。"""
def generate_minimal_records(fields: list[Field]) -> list[dict]:
"""各文件生成 1 条正常记录。"""
def generate_boundary_values(field: Field) -> dict:
"""从 PIC 解析 S9(7)V99 → 生成 max/min/溢出值。"""
def generate_sorted_records(fields: list[Field], record_count: int) -> list[dict]:
"""按 ASCENDING/DESCENDING KEY 生成已排序序列。"""
def generate_duplicate_keys(records: list[dict], key_field: str) -> list[dict]:
"""同键值追加 ≥2 件。"""
```
### 6.4 接口变更
```python
# cobol_testgen/__init__.py — __all__ 追加(parametrized 是独立模块,非子包)
from parametrized import (
generate_matching_data, # 匹配系数据
generate_keybreak_data, # key切数据
generate_division_data, # 分割系数据
generate_zero_byte_file, # 空文件
generate_boundary_values, # 边界值
)
```
---
## 7. Phase 6: 日文测试数据生成查找表
### 7.1 新文件 `japanese_data.py`(项目根目录,独立文件)
```python
# japanese_data.py
# ── 查找表 ──
FULLWIDTH_KATAKANA = "アイウエオカキクケコサシスセソタチツテト..."
FULLWIDTH_HIRAGANA = "あいうえおかきくけこさしすせそたちつてと..."
FULLWIDTH_DIGITS = "0123456789"
FULLWIDTH_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
HALFWIDTH_KATAKANA = "アイウエオカキクケコサシスセソタチツテト..."
SJIS_5C_PROBLEM = ["", "", ""] # Shift-JIS 第2字节 0x5C
SJIS_7C_PROBLEM = ["", ""] # Shift-JIS 第2字节 0x7C
WAREKI_BOUNDARIES = [
# (元号, 西历开始年, 和历开始, 西历最后日, 和历最后日)
("令和", 2019, "R010501", None, None),
("平成", 1989, "H010108", "2019/04/30", "H310430"),
("昭和", 1926, "S611231", "1989/01/07", "S640107"),
("大正", 1912, "T011231", "1926/12/25", "T151225"),
("明治", 1868, "M451229", "1912/01/29", "M450129"),
]
# ── 生成函数 ──
def generate_fullwidth_text(field: Field) -> str:
"""PIC N 字段 → 全角文字填充。"""
def generate_halfwidth_katakana(field: Field) -> str:
"""PIC X 字段 → 半角假名填充。"""
def generate_sjis_5c_problem(field: Field) -> str:
"""生成含 5C 问题文字的字符串。"""
def generate_sjis_7c_problem(field: Field) -> str:
"""生成含 7C 问题文字的字符串。"""
def generate_wareki_date(wareki_type: str) -> str:
"""生成和历日期字符串。"""
def generate_wareki_boundary(era: str) -> tuple[str, str]:
"""生成指定元号的边界日期对(末日 → 初日)。"""
def generate_encoding_test_data(
from_encoding: str,
to_encoding: str,
) -> tuple[bytes, bytes]:
"""生成编码转换测试数据(EBCDIC→SJIS→UTF-8 三段)。"""
def select_data_type(field: Field) -> str:
"""选择数据类型: PIC N → 日文 / PIC 9 → 数值 / PIC X → 半角"""
```
### 7.2 接口变更
```python
# cobol_testgen/__init__.py — __all__ 追加
"generate_fullwidth_text",
"generate_halfwidth_katakana",
"generate_wareki_date",
```
---
## 8. Phase 7-10: 类型别测试套件
### 8.1 测试文件清单
```
tests/
├── parametrized/
│ ├── test_matching.py # 匹配系 ~15 测试 (Phase 7)
│ ├── test_division.py # 分割系 ~9 测试 (Phase 7)
│ ├── test_csv_conversion.py # 文件转换 ~8 测试 (Phase 7)
│ ├── test_sort_merge.py # SORT/MERGE ~16 测试 (Phase 8)
│ ├── test_call_search.py # CALL/SEARCH ~20 测试 (Phase 8)
│ ├── test_crosscutting.py # 横跨功能 ~70 测试 (Phase 9)
│ └── test_japanese.py # 日文处理 ~31 测试 (Phase 10)
```
### 8.2 测试模板
```python
# tests/parametrized/test_matching.py
"""匹配系深度测试 — 基于 cobol-test-benchmark.md Type 01-03, 16-20, 32-33"""
import pytest
from cobol_testgen.parametrized import generate_matching_data
@pytest.mark.parametrize("r01,r02,match_ratio", [
(10, 10, 1.0), # MT-N001: 1:1 完全匹配
(1, 100, 0.0), # MT-N009: 1:N 极端不平衡
(100, 1, 0.0), # MT-N010: N:1 极端不平衡
])
def test_matching_basic(r01, r02, match_ratio):
"""MT-N001~003: 1:1 / 1:N / N:1 基本匹配"""
main_recs, sub_recs = generate_matching_data(
matching_type="1:1",
record_count_r01=r01,
record_count_r02=r02,
key_match_ratio=match_ratio,
)
assert len(main_recs) == r01
assert len(sub_recs) == r02
```
### 8.3 Phase 7 测试矩阵
| 测试文件 | 覆盖内容 | 测试项数 | 对应文档 |
|:---------|:---------|:--------:|:---------|
| `test_matching.py` | 1:1/1:N/N:1 + 不平衡 + 键重复 + 未排序 + 高级匹配 | 20 | MT-N001~012, AM-N001~008 |
| `test_division.py` | 50/25/100 分割 + 余数 + 不足 + OPEN失败 + 命名 | 9 | S-N001~007, S-A001~002 |
| `test_csv_conversion.py` | 无换行/有换行/引用符/空項目/超长 | 8 | CF-N001~006, CF-A001~002 |
### 8.4 Phase 8 测试矩阵
| 测试文件 | 覆盖内容 | 测试项数 | 对应文档 |
|:---------|:---------|:--------:|:---------|
| `test_sort_merge.py` | SORT升/降/多键/稳定/INPUT/OUTPUT PROCESS + MERGE | 16 | SR-N001~010, MR-N001~003 |
| `test_call_search.py` | CALL字面量/动态/USING/IS INITIAL/嵌套 + SEARCH ALL | 20 | C-N001~009, T-N001~007 |
### 8.5 Phase 9 测试矩阵 (横跨功能)
| 测试文件 | 覆盖内容 | 测试项数 | 对应文档 |
|:---------|:---------|:--------:|:---------|
| `test_crosscutting.py` | 可变长入出力(11) + 循环处理(10) + 数值精度(12) + 日期(18) + 排他(4) + RERUN(4) + 性能(4) | 63 | VL/LP/NP/D/EX/RR/PV |
### 8.6 Phase 10 测试矩阵 (日文)
| 测试文件 | 覆盖内容 | 测试项数 | 对应文档 |
|:---------|:---------|:--------:|:---------|
| `test_japanese.py` | PIC N全角(5) + 半角假名(5) + 外字(6) + 5C/7C(4) + 编码转换(8) + 全角空格(3) | 31 | J-N/K/G/D/X/S |
---
## 9. Phase 11: 完整类型判定管道
### 9.1 新模块 `hina/pipeline/`
```
hina/
├── rule_engine/ # 混淆组规则 (P2)
├── confidence.py # 确信度计算 (P3)
├── pipeline/ # 完整类型判定管道 (合并自 classification_pipeline/)
│ ├── __init__.py
│ └── pipeline.py # 管道编排
```
### 9.2 管道流程
```python
# hina/pipeline/pipeline.py
def classify_program(cobol_source: str) -> dict:
"""完整程序类型判定管道。
流程:
1. 并行执行:
a. 关键字识别 (detect_keyword) — 11 类 L1 关键字
b. 结构提取 (extract_structure) — 全部特征
2. 关键字确信度 ≥ 90% → 直接输出类型
DB操作/SORT/MERGE/online 等高确信度独占类型)
3. 关键字 50-89% → 进入混淆组判定
a. 结构解析 (PERFORM模式/主循环/IF分支)
b. 8 混淆组规则引擎
c. 4 因子确信度计算
d. 矛盾检测 → 有矛盾则回溯
4. 关键字 < 50% → Agent 辅助判定
a. classify_with_llm() 调用
b. LLM 返回建议类型
c. 规则引擎验证 LLM 结果
5. 输出最终判定 JSON
"""
```
### 9.3 输出格式
```python
{
"program_name": "HINA005",
"category": "condition_heavy", # 混淆组
"subtype": "simple_if", # 具体类型
"type_code": "05", # 33+2 中的编号
"method": "keyword", # keyword / rule_engine / agent
# ── 确信度详情 ──
"confidence": 0.92,
"confidence_detail": {
"base": 0.95,
"context_factor": 1.0,
"consistency_factor": 0.9,
"structure_factor": 1.0,
},
# ── 判定依据 ──
"evidence": [
"EXEC SQL → DB操作 (keyword, 95%)",
"SELECT count=1, OPEN count=1",
"IF branches=2, decisions=1",
"No contradictions detected",
],
# ── 是否需要 Review ──
"needs_review": False,
# ── 测试策略建议 ──
"testing_strategy": {
"required_tests": 5,
"coverage_target": "branch",
"supplement_strategy": "incremental",
},
}
```
### 9.4 集成到 orchestrator
```python
# orchestrator.py — 替换现有的 HINA 分类步骤
def run_pipeline(cfg: Config, ...) -> VerificationRun:
# ... 现有代码 ...
# ── 类型判定(替换现有 HINA 步骤) ──
from hina/pipeline import classify_program
classification = classify_program(cobol_src_text)
vr.hina_type = classification["category"]
vr.hina_confidence = classification["confidence"]
vr.debug["classification"] = classification
# 如果确信度 < 50%,标记为人工处理
if classification["confidence"] < 0.5 and classification["needs_review"]:
vr.quality_warn = f"类型判定确信度过低({classification['confidence']:.0%}),建议人工确认"
# ... 后续代码不变 ...
```
---
## 10. Phase 12: 文档更新
### 10.1 更新文件
| 文件 | 更新内容 |
|:-----|:---------|
| `docs/module-interfaces.md` | 追加 hina/pipeline 模块接口;追加 parametrized 子模块接口;更新 hina 模块接口(rule_engine, confidence_v2 |
| `docs/test-plan.md` → v3.0 | 追加 33+2 程序类型覆盖行;追加类型别测试矩阵;追加横跨功能测试行;追加日文测试行;更新总测试数预期(412 → 600+) |
| `docs/cobol-coverage-matrix.md` | 追加程序类型覆盖行;追加测试基准覆盖行;更新覆盖率目标 |
### 10.2 测试计划 v3.0 更新内容
```markdown
## 测试预期(更新版)
| 维度 | v2.0 | v3.0 追加 | v3.0 总计 |
|:-----|:----:|:---------:|:---------:|
| L0 单元测试 | 280 | +50 (参数化引擎) | 330 |
| L1 类型测试 | 0 | +80 (Phase 7-8) | 80 |
| 横跨功能测试 | 0 | +70 (Phase 9) | 70 |
| 日文测试 | 0 | +31 (Phase 10) | 31 |
| 非功能测试 | 6 | +10 | 16 |
| 已有回归 | 112 | — | 112 |
| **总计** | **412** | **+241** | **~653** |
```
---
## 11. 依赖关系与分工矩阵
### 11.1 Phase 依赖图
```
Phase 1 (特征提取) ──→ Phase 2 (规则引擎) ──→ Phase 3 (确信度)
│ │ │
│ └────────┬───────────────┘
│ │
│ ▼
│ Phase 11 (hina/pipeline)
│ │
▼ ▼
Phase 5 (parametrized/) Phase 4 (COBOL样本)
│ │
└────────┬──────────────────┘
Phase 7-10 (测试套件)
Phase 12 (文档)
```
### 11.2 并行执行阶段
```
可以完全并行:
Phase 1 (A) + Phase 4 (C) + Phase 5 (A) + Phase 6 (B)
Phase 2 (D) + Phase 4b (C)
Phase 7-8 (F/G) + Phase 9 (F/G) + Phase 10 (B)
测试执行阶段 (所有人可并行写自己的测试)
需要串行:
Phase 1 → Phase 2 → Phase 3 → Phase 11 (D 负责全链路)
Phase 4 → Phase 7-8 (需要样本才能测试)
Phase 5 → Phase 7-10 (需要参数化引擎才能生成测试数据)
```
### 11.3 分工矩阵
| 开发者 | Phase | 模块 | 工作量 |
|:-------|:------|:-----|:-------|
| **A** | 1, 5 | cobol_testgen 扩展 + parametrized | 3 天 |
| **B** | 6, 10, 12 | japanese_data + 日文测试 + 文档 | 2 天 |
| **C** | 4, 7 | 33+2 COBOL 样本 + 匹配/分割测试 | 3 天 |
| **D** | 2, 3, 11 | rule_engine + confidence + pipeline | 4 天 |
| **E** | 6, 10 | japanese_data + 日文测试、LLM 提示词优化 | 2 天 |
| **F** | 8, 9 | SORT/MERGE/CALL/SEARCH + 横跨功能 | 3 天 |
| **G** | 0.6, 8 | gcov 基础设施 + SORT/MERGE/SEARCH 测试 | 3 天 |
| **H** | 4c, 11 集成 | CICS/DB 样本 + orchestrator 集成 | 2 天 |
### 11.4 总工时估算
| Phase | 内容 | 人日 |
|:------|:-----|:----:|
| P1 | extract_structure 扩展 | 1.5 |
| P2 | 混淆组规则引擎 | 2.0 |
| P3 | 确信度 4 因子 | 1.0 |
| P4 | 33+2 COBOL 样本 | 2.0 |
| P5 | 参数化数据生成 | 2.0 |
| P6 | 日文数据生成 | 1.0 |
| P7 | 匹配/分割/CSV 测试 | 1.5 |
| P8 | SORT/MERGE/CALL/SEARCH 测试 | 1.5 |
| P9 | 横跨功能测试 | 2.5 |
| P10 | 日文测试 | 1.5 |
| P11 | 类型判定管道 | 2.0 |
| P12 | 文档 | 1.0 |
| | **总计** | **~19.5 人日** |
---
## 12. 接口变更一览
### 12.1 向后兼容(现有代码不受影响)
| 变更 | 类型 | 说明 |
|:-----|:-----|:------|
| `extract_structure()` 返回追加字段 | ✅ 兼容 | 现有调用用 `dict.get()`,新字段不出现时返回 None |
| `compute_confidence()` 保留 | ✅ 兼容 | 新增 `compute_confidence_v2()` 并行存在 |
| `orchestrator.py` 导入路径修改 | ✅ 兼容 | 已改为模块顶层导入 |
| `__init__.py``__all__` | ✅ 兼容 | 只是显式声明已有接口 |
### 12.2 非兼容(需同步更新调用者)
| 变更 | 类型 | 如何处理 |
|:-----|:-----|:---------|
| `hina/__init__.py` 新增 `__all__` | ⚠️ 通知 | 仅影响 `from hina import *` 用户(无此类代码)|
| `cobol_testgen/__init__.py` 新增 `__all__` | ⚠️ 通知 | 仅影响 `from cobol_testgen import *` 用户(无此类代码)|
| `orchestrator.py` 导入从 `from x.y import z` 改为 `from x import z` | ⚠️ 通知 | 已在本次修改中同步更新 |
### 12.3 新增公开 API 汇总
```python
# parametrized/ __all__(新增独立模块):
"generate_matching_data" # Phase 5
"generate_keybreak_data" # Phase 5
"generate_division_data" # Phase 5
"generate_boundary_values" # Phase 5
# japanese_data.py(新增独立文件):
from japanese_data import generate_fullwidth_text, generate_halfwidth_katakana, generate_wareki_date
# hina __all__ 追加:
"resolve_confusion_pair" # Phase 2
"detect_contradictions" # Phase 2
"BacktrackResolver" # Phase 2
"compute_confidence_v2" # Phase 3
"classify_program" # Phase 11 — hina.pipeline.pipeline.classify_program
```
---
## 附录:快速开始指南
### 对于 Acobol_testgen 扩展)
```bash
# 1. 扩展 read.py — 添加 SELECT organization 和 OPEN 模式检测
# 2. 扩展 core.py — 添加 DIVIDE/INSPECT/STRING 检测、PERFORM 分类、IF 统计、变量模式、主循环
# 3. 更新 __init__.py __all__
```
### 对于 D(规则引擎 + 确信度 + 管道)
```bash
# 1. 创建 hina/rule_engine/ — 8 混淆组规则(独立命名函数)
# 2. 创建 hina/confidence.py — 四因子计算
# 3. 创建 hina/pipeline/ — 完整管道编排
# 4. 修改 orchestrator.py — 替换 HINA 分类步骤
```
### 对于 CCOBOL 样本 + 测试)
```bash
# 1. 创建 test-data/cobol/category_matching/ — 10 个匹配系样本
# 2. 创建 test-data/cobol/category_sort/ — SORT/MERGE 样本
# 3. 创建 tests/parametrized/test_matching.py
# 4. 驱动测试: python -m pytest tests/parametrized/test_matching.py
```
### 对于 B(日文处理 + 文档)
```bash
# 1. 创建 japanese_data.py(项目根目录)— 查找表 + 生成函数
# 2. 创建 tests/parametrized/test_japanese.py
# 3. 更新 docs/module-interfaces.md
# 4. 更新 docs/test-plan.md → v3.0
```
---
## 13. COBOL 覆盖率测试体系 — 与各 Phase 的集成
> 覆盖率测试不是独立章节,而是贯穿多个 Phase 的基础设施。
> 已在 Phase 1.1Phase 0.6)中新增 gcov 基础设施。
> 以下列出覆盖率的其他部分的分布位置:
| 覆盖率内容 | 所在 Phase | 说明 |
|:-----------|:----------|:------|
| gcov 基础设施(环境验证 + collect_gcov 修复 + Config 字段 + 全链路测试)| **Phase 0.6** (1.1节) | F 负责,3h |
| 质量门禁公式更新(quality_score_v2+ 静态 vs 动态对比报告 | **Phase 3** (4.4节) | 新增 gcov 权重 40% |
| 各类型 gcov 验证测试(约 15 个) | **Phase 7-10** | 每个类型群至少 1 条 gcov 测试 |
| orchestrator gcov_enabled 集成 | **Phase 11** (9.5节) | 连接 Config → orchestrator → gate.py |
### 13.1 覆盖率目标
**模块覆盖率(pytest --cov:**
| 模块 | 目标 |
|:-----|:----:|
| cobol_testgen/* | ≥ 90% |
| hina/* | ≥ 85% |
| comparator/* | ≥ 85% |
| runners/* | ≥ 70% |
| orchestrator.py | ≥ 85% |
**程序覆盖率(gcov 验证,各类型群最低 line_rate):**
| 类型群 | 门槛 | 理由 |
|:-------|:----:|:------|
| 条件分支(IF/EVALUATE) | ≥ 70% | 分支密集,应高覆盖 |
| 匹配系 | ≥ 60% | 至少覆盖关键 IF 分支 |
| SEARCH ALL | ≥ 60% | 命中/未命中均需覆盖 |
| CALL | ≥ 60% | 主程序 + 子程序 |
| SORT | ≥ 50% | 大量 I/O,代码行不多 |
| 分割系 | ≥ 50% | 文件操作密集 |
| 编辑输出 | ≥ 50% | WRITE 语句需要实际输出 |
**静态 vs 动态差距**: 同类差距 ≤ 30%(超过说明静态分析不可靠)
> 门槛说明:基于 HINA 现有 10 个程序的 gcov 预测数据。
> 纯逻辑程序(IF/EVALUATE)可达 70%+I/O 密集程序(SORT/分割)约 50%。
> 上线后根据实测数据调整。
---
## 14. 架构审核决议汇总
> 来源: `/plan-eng-review` | 日期: 2026-06-19
### 14.1 审核决策
| 分类 | 决策 | 方案 | 结果 |
|:-----|:-----|:-----|:-----|
| 架构 | classification_pipeline/ 归属 | 合并到 hina/pipeline/ | ✅ 采纳 |
| 架构 | parametrized/ 归属 | 独立模块(项目根目录) | ✅ 采纳 |
| 架构 | japanese_data.py 归属 | 独立文件(项目根目录) | ✅ 采纳 |
| 架构 | orchestrator 过渡 | 并行开发,一次性替换 | ✅ 采纳 |
| 架构 | COBOL 样本兼容 | 不可编译类型用注释模拟关键字 | ✅ 采纳 |
| 代码质量 | 矛盾判定规则 | 独立命名函数取代 lambda | ✅ 采纳 |
| 测试 | 新模块单元测试 | 每个 Phase 包含自身测试 | ✅ 采纳 |
| 性能 | 回溯机制 | 加 30s 超时降级 | ✅ 采纳 |
### 14.2 NOT in Scope
| 项目 | 理由 |
|:-----|:------|
| CICS/DB 真实环境集成测试 | 需要大型机模拟器 |
| PySpark 完整管道验证 | Java 兼容性问题 |
| 多语言国际化(除日文外) | 33+2 类型未要求 |
| CI/CD 性能基准自动化 | 不属于 12 个 Phase |
### 14.3 实现任务
- [ ] **T1 (P1, human: ~2h)** — 扩展 extract_structure 新增 8 类特征
- [ ] **T2 (P2, human: ~3h)** — hina/rule_engine/ 8 混淆组(独立函数)
- [ ] **T3 (P3, human: ~1.5h)** — hina/confidence.py 4 因子确信度
- [ ] **T4 (P4, human: ~2.5h)** — test-data/cobol/ 33+2 样本
- [ ] **T5 (P5, human: ~2.5h)** — parametrized/ 数据生成引擎
- [ ] **T6 (P6, human: ~1h)** — japanese_data.py 日文查找表
- [ ] **T7 (P7-10, human: ~6h)** — 类型别测试套件 (~241 测试)
- [ ] **T8 (P11, human: ~2.5h)** — hina/pipeline/ 完整管道 + orchestrator 集成
- [ ] **T9 (P12, human: ~1h)** — 文档更新
### 14.4 总测试预期
```
现有: 428 测试
新增: ~60 (新模块自身单元测试)
新增: ~241 (类型别测试套件 P7-10)
总计: ~729 测试
```
### 14.5 并行策略
```
Lane A: P1 (cobol_testgen 扩展) → 独立
Lane B: P4 (COBOL 样本) → 独立,需先完成
Lane C: P5 (parametrized/) → 需要 cobol_testgen 的 PIC 解析
Lane D: P6 (japanese_data) → 独立
Lane E: P2 (rule_engine) → 需要 P1 的特征
└── P3 (confidence) → 需要 P2
└── P11 (pipeline) → 需要 P2+P3
Lane F: P7-10 (测试套件) → 需要 P4+P5+P6
└── P12 (文档) → 最后
启动顺序:
第 1 批 (并行): Lane A + Lane B + Lane D
第 2 批: Lane C (P1 完成 + 已有 data/) + Lane E (P1 完成)
第 3 批: Lane F (P4+P5+P6 完成)
最后: P12
```
---
## 15. 验收标准
> 所有 Phase 完成后,用以下标准验证是否达标。
| 编号 | 验收项 | 验证方法 | 关联 Phase |
|:-----|:-------|:---------|:-----------|
### 15.1 功能验收
| A01 | extract_structure() 返回包含全部 8 个新增字段 | pytest tests/cobol_testgen/ 全部通过 | P1 |
| A02 | 8 个混淆组规则各有 ≥ 2 个测试 | pytest tests/hina/ 覆盖 | P2 |
| A03 | 4 因子确信度的 4 个判定阈值各 ≥ 1 个测试 | pytest tests/hina/ 覆盖 | P3 |
| A04 | 33+2 个 COBOL 样本全部在 test-data/cobol/ 下 | ls test-data/cobol/category_*/ 共 35+ 文件 | P4 |
| A05 | parametrized/ 各生成函数有测试覆盖主要参数组合 | pytest tests/parametrized/ 全部通过 | P5 |
| A06 | japanese_data.py 生成函数返回正确格式 | pytest tests/parametrized/test_japanese.py | P6 |
| A07 | 类型测试套件 ≥ 200 个测试 | pytest --collect-only | P7-10 |
| A08 | hina/pipeline/ 的 3 条判定路径各有测试覆盖 | pytest tests/hina/ 模拟三种路径 | P11 |
| A09 | gcov 全链路验证测试通过 | pytest tests/test_gcov_basic.py | P0.6 |
| A10 | 质量门禁 gcov 模式下 quality_score_v2 工作 | pytest tests/hina/test_gate.py 覆盖 | P3 |
### 15.2 覆盖率验收
| 验收项 | 目标 | 验证方法 |
|:-------|:----:|:---------|
| 模块覆盖率(pytest --cov| ≥ 68% | pytest --cov=. |
| 核心管道覆盖率 | ≥ 85% | pytest --cov=cobol_testgen --cov=hina --cov=orchestrator |
| Python 测试总数 | ≥ 650 | pytest --collect-only -q |
| gcov 动态验证(可编译类型)| line_rate ≥ 50% | pytest tests/test_gcov_basic.py |
### 15.3 回归验收
- [ ] 所有现有测试通过: pytest tests/ --ignore=e2e/ -q → 0 failed
- [ ] 新增测试不降低现有覆盖率
- [ ] 所有 __all__ 中列出的公开函数有类型注解
---
---