feat(web): 项目级配置 + 会话命名/历史 + 设计文档纳入影响调查
- 会话支持 name/project 字段,上传要件定义后自动命名;前端侧边栏会话历史 + localStorage 恢复,顶部只显示会话名 - 新增 ProjectsStore(SQLite)与 /api/projects CRUD;绑定项目后 _rebuild_source 合并模板/规则/代码库/设计文档,上传区仅要件定义 - StructuredSource.design_docs 与 ImpactReport.design_references;影响调查新增既有设计文档确定性交叉引用(无 LLM) - 同步更新 docs/design.md §12.7、README、_AI_USAGE_LOG.md;全量测试 558 通过,覆盖率 99.10%
This commit is contained in:
@@ -7,11 +7,13 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
from genesis.data_models import (
|
||||
ChangeAnalysis,
|
||||
ChangeElement,
|
||||
ChangeType,
|
||||
DesignReference,
|
||||
ExcelTable,
|
||||
ImpactReport,
|
||||
ImpactWarning,
|
||||
@@ -66,6 +68,10 @@ def impact_report_to_dict(report: ImpactReport) -> dict:
|
||||
"warnings": [{"element_id": w.element_id, "issue": w.issue} for w in ca.warnings],
|
||||
},
|
||||
"summary": dict(report.summary),
|
||||
"design_references": [
|
||||
{"doc_name": r.doc_name, "identifier": r.identifier, "snippet": r.snippet}
|
||||
for r in report.design_references
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +130,7 @@ class ImpactAgent:
|
||||
"unchanged": unchanged,
|
||||
"warnings": len(warnings),
|
||||
}
|
||||
design_references = self._cross_ref_design_docs(structured_source, lookup)
|
||||
return ImpactReport(
|
||||
metadata={
|
||||
"version": "v1",
|
||||
@@ -134,8 +141,40 @@ class ImpactAgent:
|
||||
},
|
||||
change_analysis=change_analysis,
|
||||
summary=summary,
|
||||
design_references=design_references,
|
||||
)
|
||||
|
||||
def _cross_ref_design_docs(
|
||||
self, structured_source: StructuredSource, lookup: dict[str, list[dict]]
|
||||
) -> list[DesignReference]:
|
||||
"""既有设计文档确定性交叉引用(Type A 辅助证据)。
|
||||
|
||||
以既有系统(existing_system)解析出的标识符(类/方法/模块名)为锚,
|
||||
在 design_docs 的 markdown 文本中检索命中,输出 DesignReference 列表。
|
||||
无 LLM 参与,纯字符串匹配。
|
||||
"""
|
||||
design_docs = getattr(structured_source, "design_docs", []) or []
|
||||
if not design_docs:
|
||||
return []
|
||||
identifiers = [k for k in lookup.keys() if len(k) >= 3]
|
||||
refs: list[DesignReference] = []
|
||||
for doc in design_docs:
|
||||
text = getattr(doc, "markdown_content", "") or ""
|
||||
if not text:
|
||||
continue
|
||||
doc_name = Path(getattr(doc, "source_path", "design.docx")).name
|
||||
text_lower = text.lower()
|
||||
for ident in identifiers:
|
||||
il = ident.lower()
|
||||
idx = text_lower.find(il)
|
||||
if idx >= 0:
|
||||
token = text[idx:idx + len(il)] # 设计文档中的原始大小写
|
||||
start = max(0, idx - 30)
|
||||
end = min(len(text), idx + len(il) + 30)
|
||||
snippet = text[start:end].replace("\n", " ").strip()
|
||||
refs.append(DesignReference(doc_name=doc_name, identifier=token, snippet=snippet))
|
||||
return refs
|
||||
|
||||
# ---------- 内部 ----------
|
||||
|
||||
def _classify_table(
|
||||
|
||||
Reference in New Issue
Block a user