50995d3335
- SETUP.md: 完整环境搭建指南(同事用) - SETUP_QUICK.md: 快速搭环境(4步) - s22~s26: TNA端到端、覆盖率报告、回归检查 - procedure_grammar.lark: 实验性Lark语法 Co-Authored-By: Claude <noreply@anthropic.com>
660 lines
24 KiB
Markdown
660 lines
24 KiB
Markdown
# COBOL 迁移验证平台 — 增强测试方案 v3
|
||
|
||
> 版本: v4.0 | 基于多角色评审(架构师/设计师/COBOL专家)发现的 3 个问题修正
|
||
> 融合: HINA 程序分类 × 测试基准 × 覆盖率(静态+动态) × 质量门禁 × 分层重试
|
||
> 基于现有管线改造,不改 runners/comparator/web/worker 等稳定模块
|
||
|
||
---
|
||
|
||
## 一、总览
|
||
|
||
### 1.1 现状与目标
|
||
|
||
```
|
||
现状:
|
||
COPYBOOK → Agent1(解析) → Agent2(LLM盲生成) → DataWriter → Runners → Comparator → Report
|
||
↑ PASS 只说明 COBOL 和 Java 输出一致,不说明测试数据覆盖了全部逻辑
|
||
|
||
目标:
|
||
同一管线 → 新增 HINA 类型判定 → 规则引擎路径覆盖 + 语义化补充
|
||
→ 质量门禁拦截覆盖率不足的数据
|
||
→ 静态+动态双重验证覆盖率
|
||
→ 报告包含覆盖率/HINA信息/质量评分
|
||
```
|
||
|
||
### 1.2 不变的部分
|
||
|
||
| 模块 | 说明 |
|
||
|:-----|:------|
|
||
| `runners/*` | 编译执行逻辑不变(cobol_runner.py 仅新增编译参数,不改变原有流程) |
|
||
| `comparator/*` | 字段比对逻辑不依赖数据来源 |
|
||
| `agents/agent1_parser.py` | COPYBOOK → FieldTree 逻辑不变 |
|
||
| `agents/agent3_diagnostic.py` | 差异诊断逻辑不变 |
|
||
| `web/*` | Web UI 不改变 |
|
||
| `worker.py` | 任务队列逻辑不变 |
|
||
| `jcl/*` | JCL 解析执行不变 |
|
||
| `tests/*` | 现有 42 个测试不受影响 |
|
||
|
||
### 1.3 成本说明
|
||
|
||
每次验证涉及 4 个 Agent 调用:Agent1(~$0.001) + HINA Agent(~$0.002) + 策略 Agent(~$0.002) + Agent3(~$0.001 仅 mismatch 时),合计约 $0.005-0.006。准确性优先,不因成本压缩 Agent 调用。
|
||
|
||
### 1.4 术语说明
|
||
|
||
| 术语 | 说明 |
|
||
|:-----|:------|
|
||
| HINA | COBOL 程序类型分类体系(33+2 种类型) |
|
||
| cobol_testgen | 已有纯规则引擎(5000 行),可解析 COBOL 源码、枚举路径、生成覆盖率 |
|
||
| 质量门禁 | 执行前检查测试数据是否满足覆盖率和边界要求 |
|
||
| 交叉验证 | 静态(代码分析)与动态(gcov 插桩)覆盖率比对 |
|
||
|
||
### 1.5 版本变更记录
|
||
|
||
| 版本 | 变更 |
|
||
|:-----|:------|
|
||
| v1 | 初版 |
|
||
| v2 | 修复退回混用、分支树复用、Phase 1 保留 Agent2、补充 prompt 模板、定义评分公式 |
|
||
| v3 | 修复循环体每次重跑、重试计数器竞争条件、断言公式不适用 COBOL、Phase 1 门禁维度、类型优先级顺序、decision_gaps 未定义、交叉验证差异=0、拼写错误、重试可提前实施、文件映射依赖 |
|
||
| v4 | 修复 cobol_testgen 输出格式未定义(补充数据格式schema+映射函数)、固定格式 COBOL 源文件解析风险(补充格式检测逻辑)、阻断状态后用户操作路径缺失(补充操作指南+覆盖率分阶段展示规则) |
|
||
|
||
---
|
||
|
||
## 二、管线流程
|
||
|
||
### 2.1 增强后的管线
|
||
|
||
```
|
||
输入:
|
||
--copybook <文件> → Agent1
|
||
--cobol-src <文件> → cobol_testgen + HINA Agent
|
||
|
||
流程:
|
||
|
||
Step 1: Agent1(COPYBOOK) → FieldTree
|
||
|
||
Step 2: cobol_testgen.extract_structure(--cobol-src)
|
||
→ 分支树 + 结构摘要
|
||
|
||
Step 3: HINA Agent(--cobol-src + 结构摘要)
|
||
→ HINA 类型 + 確信度 + 策略参数
|
||
|
||
Step 4: cobol_testgen.generate_data(--cobol-src, 分支树)
|
||
→ base_test_cases (100% 路径覆盖)
|
||
|
||
Step 5: 策略 Agent(base + HINA 类型)
|
||
→ complete_test_cases (基础数据 + 语义化补充 + 边界值)
|
||
|
||
Step 6: 质量门禁(执行前检查)
|
||
├── 通过 → 继续
|
||
└── 不通过 → 分类退回(见 2.4)
|
||
|
||
Step 7: DataWriter(测试数据写入,不变)
|
||
|
||
Step 8: CobolRunner + JavaRunner(编译运行)
|
||
└── COBOL 编译加 -fprofile-arcs -ftest-coverage(可选)
|
||
|
||
Step 9: gcov 覆盖率采集(可选)
|
||
└── 不可用时降级为仅静态
|
||
|
||
Step 10: 交叉验证(静态 vs 动态)
|
||
|
||
Step 11: Comparator(字段比对,不变)
|
||
|
||
Step 12: Agent3 差异诊断(不变)
|
||
|
||
Step 13: 增强报告
|
||
```
|
||
|
||
### 2.2 数据流
|
||
|
||
```
|
||
Agent1 ── FieldTree ───────────────────────────────────────────┐
|
||
│
|
||
cobol_testgen.extract_structure() ── 分支树 ──┬──→ HINA Agent │
|
||
├──→ generate_data│
|
||
└──→ 质量门禁 │
|
||
│
|
||
HINA Agent ── 类型+策略参数 ──→ 策略 Agent ──→ complete_tests ──┤
|
||
▼
|
||
DataWriter
|
||
```
|
||
|
||
关键设计: **extract_structure() 输出的分支树同时传递给 HINA Agent、generate_data() 和质量门禁**,避免重复解析。
|
||
|
||
```
|
||
extract_structure() 输出的结构摘要 schema:
|
||
{
|
||
"paragraphs": ["100-MAIN", "200-PROCESS", ...],
|
||
"decision_points": [
|
||
{"id":1, "kind":"IF", "label":"TX-TYPE = 'P'", "branches":2},
|
||
{"id":2, "kind":"EVALUATE", "label":"MEM-STATUS", "branches":4},
|
||
],
|
||
"branch_tree": <BrSeq object>, // 完整的可遍历分支树对象
|
||
"file_count": 2,
|
||
"open_directions": {"TRANSIN":"INPUT", "VALIDOUT":"OUTPUT"},
|
||
"has_search_all": true,
|
||
"has_evaluate": true,
|
||
"total_branches": 25,
|
||
"total_paragraphs": 12,
|
||
}
|
||
```
|
||
|
||
### 2.3 数据格式与映射层
|
||
|
||
generate_data() 的输出格式必须与 DataWriter 的输入格式兼容。两者之间的映射关系:
|
||
|
||
```
|
||
cobol_testgen generate_data() 输出格式:
|
||
list[dict] — 每条记录:
|
||
{
|
||
"TX-CARD-NO": "6222021234567800", // 字段名 = COBOL 变量名
|
||
"TX-AMOUNT": "00000128050", // 值 = 字符串(COBOL DISPLAY 格式)
|
||
"TX-TYPE": "P",
|
||
...
|
||
}
|
||
|
||
现有 TestCase (data/test_case.py) 格式:
|
||
TestCase(id="TC-001", fields={"BR-AMT": 1500000})
|
||
// 字段名 = 映射后的业务名, 值 = Python 原生类型
|
||
|
||
DataWriter 需要的格式(runners/data_writer.py):
|
||
write_cobol_binary(): 接收 TestCase[] → 按 FieldTree 偏移写二进制
|
||
write_native_json(): 接收 TestCase[] → 写 JSON Lines
|
||
```
|
||
|
||
**Phase 1 适配方式**: 在 orchestrator.py 中增加一个轻量转换函数 `_cobol_testgen_to_testcases()`,将 cobol_testgen 的输出转换为 `TestCase[]`:
|
||
|
||
```python
|
||
def _cobol_testgen_to_testcases(records: list[dict]) -> list:
|
||
"""
|
||
将 cobol_testgen 的输出(字段名→字面值)转换为 TestCase 列表。
|
||
字段值保留为字符串(COBOL 原始格式),DataWriter 根据 PIC 类型自动解析。
|
||
"""
|
||
from data.test_case import TestCase
|
||
result = []
|
||
for i, rec in enumerate(records):
|
||
tc = TestCase(id=f"CTG-{i+1:04d}", fields=dict(rec))
|
||
result.append(tc)
|
||
return result
|
||
```
|
||
|
||
**分支树复用时的 COBOL 格式检测问题**:
|
||
|
||
cobol_testgen 的 `preprocess()` 在解析源码前需要检测文件格式(fixed/free)。**大型机迁移的 COBOL 程序 99% 是固定格式**(列 7-72 为代码区)。如果格式检测错误,PROCEDURE DIVISION 解析会失败或返回空分支树。
|
||
|
||
`extract_structure()` 的实现必须注意:
|
||
1. 强制指定格式假设: 默认按 fixed 格式解析(大型机迁移场景)
|
||
2. 如果解析后分支树为空,尝试另一种格式
|
||
3. 记录格式检测结果到结构摘要中 `"source_format": "fixed" | "free" | "auto"`
|
||
|
||
```python
|
||
# extract_structure() 中的格式处理逻辑
|
||
# 默认以 fixed 格式解析(大型机 COBOL 的行业惯例)
|
||
# 如果解析后无决策点,尝试 free 格式
|
||
source_format = "fixed"
|
||
proc = extract_procedure_division(preprocess(source))
|
||
tree, _ = build_branch_tree(proc)
|
||
if not has_any_decision(tree):
|
||
source_format = "free"
|
||
proc = extract_procedure_division(preprocess_free(source))
|
||
tree, _ = build_branch_tree(proc)
|
||
```
|
||
|
||
### 2.4 质量门禁的循环机制
|
||
|
||
**generate_data() 只执行一次,放在循环外部。** 每次迭代只做增量补充,不重跑全量生成。
|
||
|
||
```python
|
||
# 首次生成(循环外)
|
||
base_tests = cobol_testgen.generate_data(cobol_src_text, branch_tree)
|
||
complete_tests = strategy_agent.supplement(base_tests, hina_result)
|
||
|
||
# 质量门禁循环(只做增量补充,不重跑 generate_data)
|
||
MAX_TOTAL_RETRIES = 4
|
||
total_retry = 0
|
||
|
||
while total_retry < MAX_TOTAL_RETRIES:
|
||
gate_result = quality_gate.check(complete_tests, hina_result, coverage_data)
|
||
|
||
if gate_result["passed"]:
|
||
break
|
||
|
||
total_retry += 1
|
||
issues = gate_result["issues"]
|
||
# 格式: {"decision_gaps": [1, 3], "hina_gaps": ["MT-N002", "COM-A002"]}
|
||
made_progress = False
|
||
|
||
if issues.get("decision_gaps"):
|
||
# 对未覆盖的决策点增量补充
|
||
delta = cobol_testgen.incremental_supplement(
|
||
branch_tree, issues["decision_gaps"]
|
||
)
|
||
complete_tests = complete_tests + delta
|
||
made_progress = True
|
||
|
||
if issues.get("hina_gaps"):
|
||
# 对未满足的 HINA 必须项增量补充
|
||
delta = strategy_agent.supplement_only(complete_tests, issues["hina_gaps"])
|
||
complete_tests = complete_tests + delta
|
||
made_progress = True
|
||
|
||
if not made_progress:
|
||
# 没有可修复的问题 → 跳出(避免死循环)
|
||
break
|
||
|
||
# 循环结束后检查 final 结果
|
||
if not gate_result["passed"]:
|
||
# 经过 MAX_TOTAL_RETRIES 或无可修复项后仍未通过
|
||
# 不阻断管道(数据可以执行),但报告标记为 QUALITY_WARN
|
||
vr.status = "QUALITY_WARN"
|
||
vr.debug["quality_issues"] = gate_result["issues"]
|
||
```
|
||
|
||
**decision_gaps 的格式**:
|
||
```python
|
||
decision_gaps = [1, 3, 5] # 未覆盖的决策点 ID(对应结构摘要中的 decision_points[].id)
|
||
# cobol_testgen.incremental_supplement() 根据 ID 找到对应的分支条件,
|
||
# 生成恰好覆盖该分支的测试数据
|
||
```
|
||
|
||
**hina_gaps 的格式**:
|
||
```python
|
||
hina_gaps = ["MT-N002", "COM-A002"] # 未满足的 HINA 必须项 ID
|
||
# strategy_agent.supplement_only() 根据 ID 找到对应的测试场景,
|
||
# 补充必要的测试数据
|
||
```
|
||
|
||
### 2.4 不通过时的原因分类与处置
|
||
|
||
```
|
||
质量门禁检查结果 → 原因分类
|
||
|
||
决策点覆盖率 < 95%:
|
||
→ incremental_supplement(decision_point_ids),补充决策点覆盖
|
||
→ 不超过 4 次总循环
|
||
|
||
HINA 必须项不足(Phase 2 之后):
|
||
→ supplement_only(missing_item_ids)
|
||
→ 不超过 4 次总循环
|
||
|
||
字段覆盖不足:
|
||
→ 补字段值(数值 0 算非空,空格/空串算空,unused 字段跳过)
|
||
|
||
边界条件不足:
|
||
→ 策略 Agent 根据类型模板补充
|
||
```
|
||
|
||
### 2.5 交叉验证
|
||
|
||
```
|
||
交叉验证以 cobol_testgen 静态分析为计数基准,gcov 仅提供"实际执行了"的佐证。
|
||
|
||
验证方式:
|
||
1. cobol_testgen 统计静态分支总数和已覆盖数 → 分支覆盖率(静态)
|
||
2. gcov 统计实际运行时执行过的行/分支
|
||
3. 对比: 静态覆盖率 ≥ 95% 且 gcov 确认了执行
|
||
|
||
注意:
|
||
- 不要求"差异=0",因为静态和动态对分支的计数方式可能不同
|
||
- gcov 的作用是确认测试数据确实被执行了,而不是验证数量
|
||
- 如果 gcov 不可用,降级为仅静态分析,报告标记"仅静态"
|
||
```
|
||
|
||
---
|
||
|
||
## 三、阶段实施
|
||
|
||
### Phase 1: cobol_testgen 集成 + Agent2 保留(P0)
|
||
|
||
```
|
||
改动:
|
||
cobol_testgen/__init__.py → 暴露 extract_structure()、generate_data()
|
||
orchestrator.py → 插入 extract_structure() + generate_data()
|
||
└── Agent2(LLM) 仍然保留,在 cobol_testgen 之后补充语义化数据
|
||
|
||
流程:
|
||
cobol_testgen(路径覆盖) → Agent2(语义补充) → 质量门禁(初步)
|
||
|
||
Phase 1 质量门禁检查维度:
|
||
├── 决策点覆盖率 ≥90%? ✅ cobol_testgen 静态分析可用
|
||
├── 段落覆盖率 100%? ✅ cobol_testgen 静态分析可用
|
||
└── 其他维度(HINA/字段/边界)→ 尚未集成,跳过
|
||
|
||
中间状态:
|
||
- 报告包含"覆盖率(初步)"标记,注明仅含决策点和段落维度
|
||
- 覆盖率标准 ≥90%(低于正式标准的 95%)
|
||
```
|
||
|
||
**为什么要保留 Agent2**: cobol_testgen 按 PIC 类型生成边界值,但不知道字段的业务含义("TX-MERCHANT"应该用空/超长/特殊字符)。Agent2(LLM) 至少能看到字段名,能猜出业务含义。Phase 2 上线后 Agent2 被策略 Agent 取代。
|
||
|
||
**分层重试可在 Phase 1 同时部署:** retry.py 部署在调用者层,不依赖其他 Phase 的组件。
|
||
|
||
### Phase 2: HINA Agent + 策略 Agent(P1)
|
||
|
||
```
|
||
新增:
|
||
hina/classifier.py # HINA Agent 调用 (类型判定)
|
||
hina/strategy.py # 策略模板 + 策略 Agent 调用 (测试补充)
|
||
hina/gate.py # 质量门禁 (覆盖率和必须项检查)
|
||
|
||
修改:
|
||
orchestrator.py → Agent2 替换为策略 Agent
|
||
|
||
范围:
|
||
优先覆盖 jcl-cobol-git 中实际需要的类型(按匹配现有程序优先级排列):
|
||
1. マッチング系(M:N)— GENDATA/CRDVAL/CRDCALC 都需要
|
||
2. キーブレイク系(键中断)— CRDCALC/CRDRPT 需要
|
||
3. 内部表検索 (SEARCH/SEARCH ALL) — CRDVAL/CRDCALC 需要
|
||
4. 条件分岐系 (IF/EVALUATE) — 所有程序都有
|
||
5. 項目チェック系(字段校验)— CRDVAL 需要
|
||
|
||
匹配系的高级检查(多文件数据映射)包含在本阶段优先级中。
|
||
```
|
||
|
||
### Phase 3: 动态覆盖(P2)
|
||
|
||
```
|
||
修改:
|
||
runners/cobol_runner.py → 编译加 -fprofile-arcs
|
||
如果 GnuCOBOL 不支持插桩,降级为仅静态
|
||
|
||
新增:
|
||
hina/gcov_collector.py # gcov 解析 + 降级逻辑
|
||
|
||
修改:
|
||
orchestrator.py → 运行后采集 gcov + 交叉验证
|
||
```
|
||
|
||
### Phase 4: 增强报告(P2)
|
||
|
||
```
|
||
修改:
|
||
report/generator.py → 增加覆盖率/HINA/质量评分/重试历史
|
||
|
||
依赖:
|
||
- 覆盖率数据 → Phase 1/3 可用
|
||
- HINA 信息 → Phase 2 完成后可用
|
||
- 质量评分公式 → 依赖 Phase 2 的 HINA 必须项数据
|
||
|
||
质量评分公式(COBOL 版):
|
||
质量评分 = 覆盖质量 × 0.6 + 边界质量 × 0.4
|
||
|
||
覆盖质量 = 段落覆盖率 × 0.5 + 分支覆盖率 × 0.5
|
||
例: (1.0 × 0.5 + 0.92 × 0.5) = 0.96
|
||
|
||
边界质量 = HINA 必须项覆盖率(Phase 2 之后可用,之前以"待集成"显示)
|
||
例: 10/10 = 1.0
|
||
|
||
总评分 = 0.96 × 0.6 + 1.0 × 0.4 = 0.976 → 98/100
|
||
```
|
||
|
||
---
|
||
|
||
## 四、Agent 体系
|
||
|
||
### 4.1 4 个 Agent 分布
|
||
|
||
| Agent | 职责 | 输入 | 输出 | 位置 |
|
||
|:------|:-----|:-----|:-----|:-----|
|
||
| **Agent1** | COPYBOOK → FieldTree | COPYBOOK 文本 | 字段结构树 | Phase 0 原有 |
|
||
| **HINA Agent** | 程序类型判定 | COBOL 源码 + 结构摘要 | HINA 类型 + 確信度 | Phase 2 新增 |
|
||
| **策略 Agent** | 测试数据补充 | HINA 类型 + 规则数据 | 语义化测试值 | Phase 2 新增 |
|
||
| **Agent3** | 差异诊断 | 不匹配字段 | 诊断建议 | Phase 0 原有 |
|
||
|
||
**Phase 1 特殊状态**: Agent2 保留,在 cobol_testgen 之后做语义补充。Phase 2 上线后 Agent2 被策略 Agent 取代。
|
||
|
||
### 4.2 HINA Agent 的职责和 Prompt 模板
|
||
|
||
HINA Agent 遵循 cobol-test-benchmark.md 第3部的 Agent 边界设计。
|
||
|
||
**输入**: COBOL 源码 + 结构摘要
|
||
**输出**: JSON 格式的类型判定结果
|
||
|
||
```json
|
||
{
|
||
"category": "マッチング",
|
||
"subtype": "1:N",
|
||
"confidence": 0.95,
|
||
"method": "hybrid",
|
||
"features": ["MATCHING paragraph", "2 INPUT files", "KEY-BREAK processing"],
|
||
"required_tests": ["MT-N001", "MT-N002", "MT-N004", "MT-N005", "COM-N001"],
|
||
"strategy_params": {
|
||
"min_data_pairs": [3, 3],
|
||
"special_boundaries": ["不平衡: 主1件从N件", "空文件"],
|
||
"coverage_requirements": {"branch": 0.95, "paragraph": 1.0}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.3 策略 Agent 的职责
|
||
|
||
```
|
||
输入:
|
||
- cobol_testgen 生成的基础数据(保证路径覆盖)
|
||
- HINA 类型 + 策略参数
|
||
- FieldTree(字段定义)
|
||
|
||
职责:
|
||
1. 字段语义补充
|
||
"PIC X(20) 字段名为 TX-MERCHANT"→ 商户名 → 需要空值/超长/特殊字符
|
||
"PIC X(16) 字段名为 TX-CARD-NO"→ 卡号 → 需要 Luhn校验/全零/格式化
|
||
|
||
2. 类型特有边界
|
||
匹配系 → 不平衡比(1件 vs N件)
|
||
键中断 → 键值变化序列
|
||
校验系 → 异常值矩阵
|
||
|
||
3. 日文数据
|
||
检测到 PIC N → 根据字段用途选择全角/半角/外字
|
||
|
||
输出:
|
||
complete_test_cases(向已有数据追加补充)
|
||
```
|
||
|
||
---
|
||
|
||
## 五、质量门禁
|
||
|
||
### 5.1 检查项
|
||
|
||
| 检查 | 阶段 | 方法 | 标准 | 不通过处置 | 可用阶段 |
|
||
|:-----|:-----|:-----|:-----|:----------|:---------|
|
||
| 决策点覆盖 | 执行前 | cobol_testgen 静态 | ≥95% | 增量补充(≤4次) | Phase 1 |
|
||
| 段落覆盖 | 执行前 | cobol_testgen 静态 | 100% | 增量补充 | Phase 1 |
|
||
| HINA 必须项 | 执行前 | 规则判定 | 100% | 增量补充 | Phase 2 |
|
||
| 字段覆盖 | 执行前 | 枚举检查 | 100% | 补充值 | Phase 2 |
|
||
| 语句覆盖 | 执行后 | gcov 动态 | 佐证 | 记录到报告 | Phase 3 |
|
||
| 分支覆盖(动态) | 执行后 | gcov 动态 | 佐证 | 记录到报告 | Phase 3 |
|
||
|
||
### 5.2 HINA 必须项判定规则
|
||
|
||
HINA_CHECK_RULES 中的每条规则需要定义明确的判定函数和依赖:
|
||
|
||
```python
|
||
HINA_CHECK_RULES = {
|
||
"COM-A002": {
|
||
"description": "全部0件",
|
||
"depends_on": "file_mapping", # 需要知道哪些文件是输入文件
|
||
"check": "any(empty for each INPUT file)",
|
||
"note": "所有类型通用"
|
||
},
|
||
"MT-N001": {
|
||
"description": "1:1 主键完全匹配",
|
||
"depends_on": "file_mapping", # 需要文件→FD→方向映射
|
||
"check": "len(file_a) >= 1 and len(file_b) >= 1 and all_match(...)",
|
||
"note": "匹配系特有"
|
||
},
|
||
# ... 其他必须项
|
||
}
|
||
```
|
||
|
||
**文件映射逻辑**: 门禁需要知道哪些 FD 是 INPUT、哪些是 OUTPUT,才能判断"全部0件"。这个信息来自 `extract_structure().open_directions`。
|
||
|
||
### 5.3 质量评分公式(COBOL 版)
|
||
|
||
```
|
||
质量评分 = 覆盖质量 × 0.6 + 边界质量 × 0.4
|
||
|
||
覆盖质量 = 段落覆盖率 × 0.5 + 分支覆盖率 × 0.5
|
||
例: (1.0 × 0.5 + 0.92 × 0.5) = 0.96
|
||
|
||
边界质量 = HINA 必须项覆盖率
|
||
例: 10/10 = 1.0
|
||
|
||
总评分 = 0.96 × 0.6 + 1.0 × 0.4 = 0.976 → 98/100
|
||
```
|
||
|
||
---
|
||
|
||
## 六、增强报告
|
||
|
||
```
|
||
字段比对(原有):
|
||
BR-AMT: PASS (COBOL=1500.00, Java=1500.00)
|
||
|
||
覆盖率:
|
||
├── 覆盖率方式: ✅ 静态+动态 / 🟡 仅静态
|
||
├── 段落覆盖率: 100% (12/12) ✅
|
||
├── 分支覆盖率(静态): 96% (24/25) → 1个未覆盖
|
||
├── 分支覆盖率(动态): 已执行 ✅(佐证)
|
||
├── 语句覆盖率(动态): 已执行 ✅(佐证/或 不可用)
|
||
├── 决策点覆盖率: 96% (24/25) → 1个未覆盖
|
||
└── 交叉验证: gcov 确认执行 ✅
|
||
|
||
HINA 信息(Phase 2+):
|
||
├── 判定类型: マッチング(1:N) — 確信度 95%
|
||
├── 判定方法: Agent (关键字+混淆组)
|
||
└── ◎必须项: 10/10 覆盖 ✅
|
||
|
||
质量评分(Phase 2+):
|
||
├── 覆盖质量: 96/100
|
||
├── 边界质量: 100/100
|
||
└── 总评分: 97/100 ✅ PASS
|
||
|
||
重试历史:
|
||
├── heal_retry: 1 (编译修复)
|
||
├── simple_retry: 0
|
||
├── quality_retries: 0
|
||
└── 最终状态: PASS
|
||
```
|
||
|
||
---
|
||
|
||
## 七、分层重试
|
||
|
||
### 7.1 部署位置
|
||
|
||
分层重试部署在 **orchestrator.py 调用者层**(在 main.py 和 worker.py 中),而不是在 orchestrator 内部。
|
||
|
||
```
|
||
worker.py: orchestrator.py:
|
||
result = retry_handler.run( run_pipeline(...)
|
||
lambda: run_pipeline(...) ↑ 失败时返回状态码
|
||
)
|
||
↑ 根据状态码决定重试策略 不负责重试
|
||
|
||
retry_handler 的责任:
|
||
1. 匹配已知失败模式 → 修复后 heal_retry
|
||
2. 未知原因 → simple_retry
|
||
3. 超出上限 → FATAL
|
||
```
|
||
|
||
**分层重试不依赖 Phase 2/3 的组件,可在 Phase 1 部署。**
|
||
|
||
### 7.2 重试层级
|
||
|
||
```
|
||
失败 → 匹配已知模式?
|
||
├── 编译失败 (COBCPY路径/方言不匹配) → 修复后 heal_retry +1
|
||
├── S0C7 (数值字段含非数值) → 数据补零后 heal_retry +1
|
||
├── 文件 OPEN 失败 → 检查 JCL/DD 后 heal_retry +1
|
||
├── HINA 判定低確信度 → Agent 重判定后 heal_retry +1
|
||
├── gcov 数据异常 → 重新编译插桩后 heal_retry +1
|
||
└── 其他 → simple_retry +1
|
||
|
||
累计判断:
|
||
heal_retry > 2 → HEAL_FAILED(降级,报告标注)
|
||
simple_retry > 3 → RETRY_EXHAUSTED(FATAL)
|
||
total_retry > 6 → FATAL
|
||
```
|
||
|
||
---
|
||
|
||
## 八、阻断状态与用户操作指南
|
||
|
||
### 8.1 阻断状态一览
|
||
|
||
| 条件 | 状态 | 对用户的影响 | 用户操作路径 |
|
||
|:-----|:-----|:------------|:------------|
|
||
| gcov 不可用 | ⚠️ 降级(继续) | 报告标记"仅静态" | 不需要操作。覆盖率以静态分析为准 |
|
||
| 质量门禁 4 次后仍未通过 | ⚠️ QUALITY_WARN(继续) | 报告包含未覆盖分支清单 | 查看报告中的未覆盖清单 → 补充测试数据覆盖缺失的分支 → 重新运行 |
|
||
| HINA Agent 確信度 < 70% | 🔴 阻断 | 命令行提示 "HINA 判定不确定,请指定类型"。候选类型列表随提示输出 | CLI: `--hina-type "マッチング"` 手动指定。Web: 待实现 |
|
||
| LLM API 超时 | ⚠️ 降级(继续) | Agent1/Agent3 降级。覆盖率/HINA 信息为 unknown | 检查 API 连接后重试 |
|
||
| cobol_testgen 路径枚举超 | ⚠️ 降级(继续) | 覆盖率标记"可能不完整" | 评估是否适合此程序的大路径数。可忽略 |
|
||
|
||
### 8.2 覆盖率展示规则(Phase 1-4 分阶段)
|
||
|
||
覆盖率在报告中按可用数据分阶段展示,避免展示不准确的数据造成误导:
|
||
|
||
| Phase | 报告展示 | 示例 | 说明 |
|
||
|:------|:---------|:-----|:------|
|
||
| Phase 1 | 总分支数 + 已生成记录数 + 不可计算 | `总分支: 25 / 记录: 15 / 覆盖率: ⏳ 需要 gcov` | 不展示百分比 |
|
||
| Phase 2 | 同上 + HINA 必须项数 | `HINA 必须项: 10/10 ✅` | 覆盖质量独立展示 |
|
||
| Phase 3 | 同上 + gcov 行覆盖率 | `行覆盖率(gcov): 92%` | 只展示 gcov 实际数据 |
|
||
| Phase 4 | 完整评分 | `总评分: 97/100` | 汇总所有维度 |
|
||
|
||
### 8.3 阻断后的恢复流程
|
||
|
||
```
|
||
HINA Agent 確信度 < 70% → 阻断
|
||
│
|
||
├── CLI 用户:
|
||
│ 查看提示的候选类型列表
|
||
│ 重新运行: python main.py --cobol-src ... --hina-type "マッチング"
|
||
│ 指定后跳过 Agent 判定,直接使用指定类型
|
||
│
|
||
├── Web 用户(待实现):
|
||
│ 页面显示 "类型判定失败,请选择正确的程序类型"
|
||
│ 下拉框显示候选类型 → 选择后自动继续
|
||
│
|
||
└── 不确定类型:
|
||
参考 cobol-test-benchmark.md 第1部的关键字识别表
|
||
按 PROGRAM-ID 命名规则、FILE-CONTROL 中的文件数、PROCEDURE DIVISION 中的段落名判断
|
||
|
||
QUALITY_WARN(不阻断,但覆盖率不足):
|
||
├── 查看报告中的未覆盖决策点清单
|
||
├── 针对每个未覆盖 ID,在源码中找到对应的 IF/EVALUATE 条件
|
||
├── 补充覆盖该条件的测试数据
|
||
└── 重新运行验证
|
||
```
|
||
|
||
---
|
||
|
||
## 九、实施步骤
|
||
|
||
```
|
||
Phase 1 (P0): cobol_testgen 集成 + Agent2 保留 + 分层重试
|
||
├── 暴露 extract_structure() + generate_data()+incremental_supplement()
|
||
├── 修改 orchestrator.py 插入路径覆盖
|
||
├── Agent2 保留做语义补充
|
||
├── 质量门禁(初步,仅决策点+段落维度,≥90%)
|
||
└── hina/retry.py 分层重试部署
|
||
|
||
Phase 2 (P1): HINA Agent + 策略 Agent
|
||
├── hina/classifier.py (HINA Agent)
|
||
├── hina/strategy.py (策略模板 + 策略 Agent)
|
||
├── hina/gate.py (质量门禁 + HINA 必须项)
|
||
├── Agent2 替换为策略 Agent
|
||
└── 优先覆盖: 匹配系 > 键中断 > 内部表 > 条件分支 > 校验系
|
||
|
||
Phase 3 (P2): 动态覆盖
|
||
├── CobolRunner 新增编译参数
|
||
├── hina/gcov_collector.py
|
||
└── 交叉验证
|
||
|
||
Phase 4 (P2): 增强报告
|
||
├── report/generator.py 增强(覆盖率/HINA/质量评分)
|
||
├── 质量评分公式(依赖 Phase 2 的 HINA 数据,之前显示"待集成")
|
||
└── 重试历史展示
|
||
```
|