feat(impact): Impact Agent MVP —— 变更点定位 + 影响调查书(追加改修场景)
- 门控:用户提供 existing_system 路径 → 进入影响调查;未提供 → 原流程不变
- CodeParser 解析 Java(@RestController/@Service/@Entity/@TableName)+ ExistingSystemExplorer 组装
- ImpactAgent 变更点定位(变更区分×既存対応 确定性比对,无 LLM)→ ImpactReport(JSON 可下载)
- 影响调查结果作为 Writer 生成概要设计书的主上下文({{impact}},无专用影响章)
- source_aggregator 解除 existing_system=None 硬编码
- 既有系统样本 sunOnly/stock-trade-system(无 LICENSE,仅测试输入,保留来源标注)
- 新造股票交易域追加改修样本 要件定義_追加改修_股票.xlsx(对齐 sunOnly 真实类名)
- 全量 351 passed / 99.27% 覆盖;门禁 PASS(16 要素:新规5/変更8/削除3/未受影响50)
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# Impact Agent MVP 设计(2026-08-23)
|
||||
|
||||
## 背景
|
||||
|
||||
用户指出:写概要设计书需要「根据要件定义书 + 既有系统的设计与代码做影响调查 → 确定修改范围」。当前
|
||||
`source_aggregator.py` 硬编码 `existing_system=None`,无 Impact Agent 实现。本次实现 **MVP 变更点定位 + 影响书**。
|
||||
|
||||
关键用户决策(brainstorming 确认):
|
||||
1. 场景 = **追加改修**(需影响调查)
|
||||
2. 既有系统输入形态 = **Java 项目源码**
|
||||
3. 既有系统样本 = `samples/existing-system/`(sunOnly/stock-trade-system,股票量化交易系统,无 LICENSE,
|
||||
仅作测试输入,保留来源标注)
|
||||
4. 里程碑范围 = **MVP**:解析既有系统 → 变更点定位 → 影响书(JSON);不做 LLM 要素抽取/关联推理
|
||||
5. 样本同域化:新造 `samples/要件定義_追加改修_股票.xlsx`(股票交易域,对齐 sunOnly 真实模块)
|
||||
6. **门控**:是否提供 `existing_system` 路径决定是否进入影响调查阶段(非章节级)
|
||||
7. **范围确认**:进入影响调查前与用户确认调查范围(模块/深度)
|
||||
8. **消费模型**:`ImpactReport` 是生成概要设计书的**主上下文**——整本概要设计书基于影响调查结果生成,
|
||||
**无专用影响章、无 `{{section:impact}}` 锚点门控**;`ImpactReport` 同时作为可下载独立产物
|
||||
|
||||
## 架构与数据流
|
||||
|
||||
```
|
||||
要件定義_追加改修_股票.xlsx(新造) samples/existing-system/(sunOnly 源码)
|
||||
│ 现有 ExcelParser │ 新增 CodeParser(Java 解析)
|
||||
▼ ▼
|
||||
StructuredSource.tables CodeStructure → ExistingSystemInfo
|
||||
│ │
|
||||
└──────────────┬───────────────────────────┘
|
||||
▼
|
||||
ImpactAgent(变更点定位,确定性比对)
|
||||
- 取 変更区分 + 既存対応 列
|
||||
- 与 ExistingSystemInfo 连接比对(存在性校验)
|
||||
▼
|
||||
ImpactReport(JSON 中间产物,可下载)
|
||||
▼
|
||||
WriteOrchestrator.generate(impact_report)
|
||||
- ImpactReport 作为主上下文喂给 WriterAgent
|
||||
- 整本概要设计书基于影响结果生成
|
||||
```
|
||||
|
||||
## 门控与范围确认
|
||||
|
||||
- **门控(流水线级)**:`SourceParser.parse(existing_system_path=...)` 提供路径 ⇒ `StructuredSource.existing_system`
|
||||
非 None ⇒ 进入影响调查;`WriteOrchestrator.generate` 检测到 `existing_system` 非 None 且未显式传
|
||||
`impact_report` 时,自动运行 `ImpactAgent` 生成影响书。
|
||||
- **范围确认(human-in-loop)**:MVP 默认范围 = 提供的整个目录树(全模块、Controller/Service/Entity/Endpoint 全层);
|
||||
可按参数收窄(`modules`/`depth`)。完整 UI 确认留后续。
|
||||
- **门控降级**:CodeParser 失败(非 Java/无源码)⇒ 跳过影响调查并告警,生成照常(无 ImpactReport)。
|
||||
|
||||
## 变更点定位规则(确定性,无 LLM)
|
||||
|
||||
| 要件情况 | 判定 |
|
||||
|---|---|
|
||||
| 新規 + 既存対応空 | `new`(确认新增) |
|
||||
| 新規 + 既存対応指定 | `conflict` 告警(自相矛盾) |
|
||||
| 変更 + 既存対応命中且类存在 | `modified`(受影响既有类 = 映射清单) |
|
||||
| 変更 + 既存対応缺失/类不存在 | `warning`(无法定位修改对象) |
|
||||
| 削除 + 既存対応命中 | `deleted`(确认删除) |
|
||||
| 削除 + 既存対応缺失/类不存在 | `warning` |
|
||||
| 既有类未被任何要件引用 | `unchanged`(summary 计数) |
|
||||
|
||||
`既存対応` 列值 = Controller/Service/Entity 类名(逗号分隔);命中判定为类名出现在
|
||||
`ExistingSystemInfo` 三层清单中(不区分大小写,后缀 `Controller`/`Service`/`Entity` 可选)。
|
||||
|
||||
## 数据模型(data_models.py 新增)
|
||||
|
||||
```python
|
||||
class ChangeType(Enum):
|
||||
NEW = "新規"; MODIFIED = "変更"; DELETED = "削除"; UNCHANGED = "不变"
|
||||
|
||||
@dataclass
|
||||
class ChangeElement:
|
||||
element_id: str; element_type: str; name: str
|
||||
change_type: ChangeType
|
||||
existing_mapping: list[str] # 既存対応 声明值
|
||||
impacted_existing: list[str] # 确认命中的既有类
|
||||
evidence: str # 既有类 source_uri / 空
|
||||
status: str # "ok" | "conflict" | "warning"
|
||||
|
||||
@dataclass
|
||||
class ImpactWarning:
|
||||
element_id: str; issue: str
|
||||
|
||||
@dataclass
|
||||
class ChangeAnalysis:
|
||||
project_type: str # "enhancement"
|
||||
new_elements: list[ChangeElement]
|
||||
modified_elements: list[ChangeElement]
|
||||
deleted_elements: list[ChangeElement]
|
||||
unchanged_elements: list[ChangeElement]
|
||||
warnings: list[ImpactWarning]
|
||||
|
||||
@dataclass
|
||||
class ImpactReport:
|
||||
metadata: dict
|
||||
change_analysis: ChangeAnalysis
|
||||
summary: dict
|
||||
```
|
||||
|
||||
## 组件
|
||||
|
||||
### `src/genesis/impact/code_parser.py`(新)
|
||||
- `CodeParser.parse(root_path) -> CodeStructure`:扫描 `**/*.java`,按注解识别:
|
||||
- `@RestController|@Controller` → ControllerInfo(base_path 取 `@RequestMapping`,endpoints 取方法级映射)
|
||||
- `@Service` → ServiceInfo(methods)
|
||||
- `@Entity|@Table(name=...)` → EntityInfo(table_name、fields)
|
||||
- 方法映射 → EndpointInfo
|
||||
- 顶层目录 → modules;失败(无 Java/路径无效)→ 抛 `CodeParseError`
|
||||
|
||||
### `src/genesis/impact/existing_system_explorer.py`(新)
|
||||
- `ExistingSystemExplorer.explore(code: CodeStructure) -> ExistingSystemInfo`
|
||||
|
||||
### `src/genesis/impact/impact_agent.py`(新)
|
||||
- `ImpactAgent.run(structured_source, scope=None) -> ImpactReport`
|
||||
- 从 `tables` 提取带 `変更区分`/`既存対応` 列的表行 → 按上表规则分类 → summary
|
||||
|
||||
### `src/genesis/parsers/source_aggregator.py`(改)
|
||||
- `parse(..., existing_system_path=None)`:提供路径时解析并填充 `existing_system`
|
||||
|
||||
### `src/genesis/writer/`(改)
|
||||
- `GenerationContext` 新增 `impact_report: object | None = None`;`to_vars()` 增加 `"impact"` 变量
|
||||
- `WRITER_PROMPT_TEMPLATE` 增加 `影响调查上下文:\n{{impact}}\n`(在参考资料前)
|
||||
- `context_builder.build_contexts` 从 `structured_source.impact_report` 透传
|
||||
- `WriteOrchestrator.generate(..., impact_report=None)`:门控自动跑 `ImpactAgent`;上下文携带影响书
|
||||
- `StructuredSource` 新增 `impact_report: ImpactReport | None = None`(生成后回填,便于 QA/日志)
|
||||
|
||||
## 错误处理
|
||||
|
||||
- `CodeParseError`(非 Java/无源码/路径无效)→ 门控降级跳过 + 告警
|
||||
- `既存対応` 引用不存在 → `warning`,不阻断
|
||||
- `新規` 却映射既有 → `conflict` warning
|
||||
|
||||
## 测试策略(TDD,全量 ≥99%)
|
||||
|
||||
- `tests/test_data_models.py`:新增 ImpactReport 模型默认值/构造
|
||||
- `tests/test_code_parser.py`:用 `samples/existing-system` 真实文件断言提取(类名/数量/路径)
|
||||
- `tests/test_existing_system_explorer.py`:组装 ExistingSystemInfo 分层
|
||||
- `tests/test_impact_agent.py`:给定 要件定義(新造样本)+ ExistingSystemInfo → 断言分类
|
||||
- `tests/test_source_aggregator.py`:`existing_system_path` 加载;无效路径降级/报错
|
||||
- `tests/test_phase5_models.py`:更新 `test_generation_context_no_impact_field` → 断言 `impact` 变量存在且为空
|
||||
- `tests/test_phase5_writer_agent.py`:断言模板含影响上下文变量
|
||||
- `tests/test_phase5_writer_orchestrator.py`:传 impact_report → 断言 `variables["impact"]` 含影响信息
|
||||
- 门禁(fake 模式):sunOnly + 新造样本端到端产出 ImpactReport + 概要设计书
|
||||
|
||||
## 新造样本规格
|
||||
|
||||
`samples/要件定義_追加改修_股票.xlsx`(股票交易域,对齐 sunOnly 真实模块):
|
||||
- 機能一覧:F001 止损风控机能(新規,无既存対応) / F002 订单状态查询扩展(変更→OrderController,OrderQueryService)
|
||||
/ F003 实时行情显示扩展(変更→RealtimeMarketDataController) / F004 旧回测机能(削除→StrategyBacktestController)
|
||||
- 画面一覧(对应画面 + 変更区分)/DB定義(新規 止损设定表/変更 订单表/削除 旧回测表)/IF定義(新規 风控告警连携IF)
|
||||
- 各表新增 `既存対応` 列(类名或留空)+ `変更区分` 列
|
||||
- `改修ポイント` 自由文本(改修概要)
|
||||
|
||||
## 里程碑外(后续)
|
||||
|
||||
- LLM 要素抽取 / 关联推理 / 影响矩阵
|
||||
- v1→用户逐条修正→v2 生命周期 UI
|
||||
- 范围确认 UI / API 化
|
||||
Reference in New Issue
Block a user