Files
cobol-java-v3/docs/plans/db-pipeline-agent2data-integration.md
T

9.1 KiB
Raw Blame History

DB 管道接入 Agent2Data — 实现计划

问题

DB 管道 (orchestrator_db.py) 从未调用 Agent2Data,而 Agent2Data 的 LLM 场景/边界数据是 cobol_testgen 覆盖率基线的补充,应作为第 4 个数据源合并。

同时,非 DB 管道存在两条重复入口(orchestrator.py + __init__.py:main() 行内管线),导致:

  • 行内管线不经过我们刚修的 Agent2Data 合并逻辑
  • 行内管线不走质量门/hina 分类/Agent3 诊断
  • 两条管线功能不一致

阶段 ADB 管道接入 Agent2Data

目标

data_merger.py:generate_all_data() 中新增 Agent2Data 作为第 4 个数据源,使其在 DB 管道 (orchestrator_db.py) 中生效。

修改文件

A1. data_merger.pygenerate_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=Nonellm_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.pyCobolRunner.compile() + CobolRunner.run()(旧 APIstdin/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 后单独处理)