9.1 KiB
DB 管道接入 Agent2Data — 实现计划
问题
DB 管道 (orchestrator_db.py) 从未调用 Agent2Data,而 Agent2Data 的 LLM 场景/边界数据是 cobol_testgen 覆盖率基线的补充,应作为第 4 个数据源合并。
同时,非 DB 管道存在两条重复入口(orchestrator.py + __init__.py:main() 行内管线),导致:
- 行内管线不经过我们刚修的 Agent2Data 合并逻辑
- 行内管线不走质量门/hina 分类/Agent3 诊断
- 两条管线功能不一致
阶段 A:DB 管道接入 Agent2Data
目标
在 data_merger.py:generate_all_data() 中新增 Agent2Data 作为第 4 个数据源,使其在 DB 管道 (orchestrator_db.py) 中生效。
修改文件
A1. data_merger.py — generate_all_data() 新增 Agent2Data 源
现状:三路合并(白盒 + 功能 + 策略),参数不含 FieldTree
改动:
def generate_all_data(
program_id: str,
src_text: str,
st: dict,
copybook_dirs: list = None,
design_doc_dir: str = None,
llm_client=None,
config: dict = None,
merge_strategy: str = "default",
field_tree=None, # ← NEW: Agent2Data 需要的 FieldTree
) -> list[dict]:
在原有 _dedup() 链后新增第 4 个源:
# ④ Agent2Data LLM 场景数据 (NEW)
agent2_records = []
if field_tree is not None and llm_client is not None:
try:
from agents import Agent2Data
suite = Agent2Data(llm_client).design(
field_tree,
target=config.get("coverage_default", "boundary"),
spark_mode=False,
)
for tc in suite.test_cases:
rec = dict(tc.fields)
rec["_source"] = "agent2"
agent2_records.append(rec)
logger.info(f" Agent2Data records: {len(agent2_records)}")
except Exception as e:
logger.warning(f" Agent2Data failed, skipped: {e}")
# 合并:additional(agent2) 优先,再追加 whitebox+func 中不重复的
all_records = _dedup(addition=agent2_records, main=all_records)
优雅降级:field_tree=None 或 llm_client=None 时不调用,不影响现有管线。
A2. orchestrator_db.py:step2_generate_inputs() — 构造 FieldTree 并传入
现状:调用 generate_all_data() 时未传 field_tree 参数
改动(在 generate_all_data 调用附近):
from data.field_tree import FieldTree, Field
# 从 structure['data_fields'] 构造 FieldTree
data_fields = st.get("data_fields", [])
field_tree = None
if data_fields:
try:
fields = []
for f in data_fields:
if f.get("is_88"):
continue
pi = f.get("pic_info", {})
fields.append(Field(
name=f["name"],
level=f.get("level", 0),
pic=f.get("pic", ""),
usage=f.get("usage", "DISPLAY"),
length=pi.get("length", 0) or pi.get("digits", 0) + pi.get("decimal", 0),
decimal=pi.get("decimal", 0),
signed=pi.get("signed", False),
redefines=f.get("redefines"),
occurs=f.get("occurs"),
))
field_tree = FieldTree(fields=fields, copybook_name=self.program_id)
except Exception as e:
logger.warning(f" FieldTree construction failed (Agent2Data will be skipped): {e}")
# 传入 generate_all_data
recs = generate_all_data(
...,
field_tree=field_tree, # ← NEW
)
A3. 前置:data_merger.py 导入补充
# 文件头部新增 import (紧接现有 import)
try:
from agents import Agent2Data
except ImportError:
Agent2Data = None
验证方法
cd C:\Users\marye\Desktop\2026技术大赛\cobol-java-v3
set COB_LIBRARY_PATH=<tna>\bin;<v3>\gixsql\lib
set GIXSQL_DB_PATH=C:\Temp\gix
python -m cobol_testgen --gcov <tna>\src\ZAN06UPD.cbl runtime\
检查日志输出是否包含 Agent2Data records: N。
阶段 B:统一非 DB 入口
目标
消除 __init__.py:main() 中的 ~350 行行内管线代码,非 DB 程序统一走 orchestrator.py:run_pipeline(),同时将行内管线的 gcov + HTML 覆盖率报告功能搬迁到 orchestrator.py。
修改文件
B1. orchestrator.py:run_pipeline() — 增加 gcov 支持 + HTML 覆盖率报告
现状:orchestrator.py 用 CobolRunner.compile() + CobolRunner.run()(旧 API,stdin/stdout 管道),没有 gcov,没有 HTML 覆盖率报告。
改动:
def run_pipeline(cfg: Config, cpath: str, cbl: str, java: str, map_path: str) -> VerificationRun:
t0 = time.time()
vr = VerificationRun(program=Path(java).stem, runner=cfg.runner_mode)
try:
text = Path(cpath).read_text()
# ... 保持 Agent1Parser + cobol_testgen + hina + Agent2Data + DataWriter 不变 ...
# COBOL 编译 (改为新 API + gcov 支持)
cob = CobolRunner()
source_dir = str(Path(cbl).parent)
work_dir = Path("temp_work").resolve()
work_dir.mkdir(parents=True, exist_ok=True)
copybook_dirs = [str(Path(cbl).parent.parent / "cpy")] # 从 config/copybook_paths 获取
sub_o = compile_sub_modules(source_dir, work_dir, copybook_dirs)
exe_path = compile_program(
program_name=Path(cbl).stem,
source_dir=source_dir,
work_dir=work_dir,
sub_objects=sub_o,
cpy_dir=copybook_dirs,
gcov=cfg.gcov_enabled,
)
# COBOL 运行 (文件 I/O)
skip_expected = ...
run_all(
program_name=Path(cbl).stem,
outdir=str(output_dir),
temp_dir=work_dir,
fields_dict=..., fd_fields=...,
select_info=..., open_dir=...,
term_types=..., records=...,
expected_records=...,
source_dir=source_dir,
path_infos=...,
multi_write_fds=...,
skip_records=...,
skip_term_types=...,
)
# HTML 覆盖率报告
if cfg.gcov_enabled:
run_coverage(...)
generate_coverage_index(...)
# ... 保持 Java 编译运行 + 比对 + Agent3 + ReportGenerator 不变 ...
B2. __init__.py:main() 非 DB 分支 — 委托给 orchestrator.py
现状:~350 行行内管线代码
改动:
# 非 DB 程序
for filepath in non_db_files:
try:
from orchestrator import run_pipeline
from config import Config
cfg = Config()
cfg.gcov_enabled = gcov_mode
# 复制相关路径配置
cfg.copybook_paths = [str(filepath.parent / ".." / "cpy")]
vr = run_pipeline(
cfg=cfg,
cpath=str(filepath), # 用作 COPYBOOK
cbl=str(filepath),
java="", # 无双版本验证时跳过
map_path="",
)
# 输出处理(拷贝到 prog_outdir,生成覆盖率索引等)
...
except Exception as e:
logger.error(f" orchestrator pipeline failed: {e}")
# 回退:行内管线
...
回退策略:如果 orchestrator.py 调用失败,自动回退到行内管线(保留原有行为)。
验证方法
统一前后结果应完全一致:
# 统一前
python -m cobol_testgen --gcov <tna>\src\ZAN01CHK.cbl runtime-new\
# 统一后
python -m cobol_testgen --gcov <tna>\src\ZAN01CHK.cbl runtime-unified\
diff -r runtime-new runtime-unified
两条命令的输出目录结构、覆盖率数据应一致。
实施顺序与依赖
阶段 A (DB + Agent2Data) ──────────── 独立,无外部依赖
├── A1: data_merger.py ─── 新增 field_tree 参数 + Agent2Data 调用
└── A2: orchestrator_db.py ─── 构造 FieldTree 并传入
阶段 B (入口统一) ─────────────────── 依赖阶段 A 完成后可开始
├── B1: orchestrator.py ─── 增加 gcov + HTML 覆盖率能力
├── B2: __init__.py:main() ─── 非 DB 委托给 orchestrator.py
└── B3: 验证一致性 + 清理旧代码
主要风险
| 风险 | 等级 | 缓解 |
|---|---|---|
| Agent2Data 字段值不符合 PIC 格式(阶段 A) | 🟡 | Agent2Data 数据排在末尾,不破坏基线;后续可加 PIC 格式化 |
| FieldTree 构造精度不足(阶段 A) | 🟡 | st["data_fields"] 来自 extract_structure(),与 Agent1Parser 的 FieldTree 结构等价但来源不同 |
orchestrator.py 搬入 gcov 后与行内管线行为不一致(阶段 B) |
🔴 | 并排运行对比,保持回退机制 |
行内管线的 C01 特定逻辑 (_inject_c01_coverage_records 等) 在 orchestrator.py 中缺失(阶段 B) |
🔴 | 搬迁时确认 orchestrator.py 是否也需要这些逻辑;若不需要则跳过(行内管线专门为 KIN/ZAN 程序集优化) |
不纳入范围
- Agent2Data 输出值的 PIC 格式化(后续优化)
- 统一后删除
__init__.py行内管线死代码(阶段 B 完成后清理) main.py废弃(阶段 B 后单独处理)