# 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": , // 完整的可遍历分支树对象 "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 数据,之前显示"待集成") └── 重试历史展示 ```