初始提交:飞球 ETL 系统全量代码

This commit is contained in:
Neo
2026-02-13 08:05:34 +08:00
commit 3c51f5485d
441 changed files with 117631 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"generationMode": "requirements-first"}

View File

@@ -0,0 +1,424 @@
# 设计文档:仓库治理只读审计
## 概述
本设计描述三个 Python 审计脚本的实现方案,用于对 etl-billiards 仓库进行只读分析并生成三份 Markdown 报告。脚本仅读取文件系统和源代码,不连接数据库、不修改任何现有文件,仅在 `docs/audit/` 目录下输出报告。
审计脚本采用模块化设计:一个共享的仓库扫描器负责遍历文件系统,三个独立的分析器分别生成文件清单、流程树和文档对齐报告。
## 架构
```mermaid
graph TD
A[scripts/audit/run_audit.py<br/>审计主入口] --> B[scripts/audit/scanner.py<br/>仓库扫描器]
A --> C[scripts/audit/inventory_analyzer.py<br/>文件清单分析器]
A --> D[scripts/audit/flow_analyzer.py<br/>流程树分析器]
A --> E[scripts/audit/doc_alignment_analyzer.py<br/>文档对齐分析器]
B --> F[文件系统<br/>只读遍历]
C --> G[docs/audit/file_inventory.md]
D --> H[docs/audit/flow_tree.md]
E --> I[docs/audit/doc_alignment.md]
C --> B
D --> B
E --> B
```
### 执行流程
1. `run_audit.py` 作为主入口,初始化扫描器并依次调用三个分析器
2. `scanner.py` 递归遍历仓库,构建文件元信息列表(路径、大小、类型)
3. 各分析器接收扫描结果,执行各自的分析逻辑,输出 Markdown 报告
4. 所有报告写入 `docs/audit/` 目录
## 组件与接口
### 1. 仓库扫描器 (`scripts/audit/scanner.py`)
负责递归遍历仓库文件系统,返回结构化的文件元信息。
```python
@dataclass
class FileEntry:
"""单个文件/目录的元信息"""
rel_path: str # 相对于仓库根目录的路径
is_dir: bool # 是否为目录
size_bytes: int # 文件大小(目录为 0
extension: str # 文件扩展名(小写,含点号)
is_empty_dir: bool # 是否为空目录
EXCLUDED_PATTERNS: list[str] = [
".git", "__pycache__", ".pytest_cache",
"*.pyc", ".kiro",
]
def scan_repo(root: Path, exclude: list[str] = EXCLUDED_PATTERNS) -> list[FileEntry]:
"""递归扫描仓库,返回所有文件和目录的元信息列表"""
...
```
### 2. 文件清单分析器 (`scripts/audit/inventory_analyzer.py`)
对扫描结果进行用途分类和处置标签分配。
```python
# 用途分类枚举
class Category(str, Enum):
CORE_CODE = "核心代码"
CONFIG = "配置"
DATABASE_DEF = "数据库定义"
TEST = "测试"
DOCS = "文档"
SCRIPTS = "脚本工具"
GUI = "GUI"
BUILD_DEPLOY = "构建与部署"
LOG_OUTPUT = "日志与输出"
TEMP_DEBUG = "临时与调试"
OTHER = "其他"
# 处置标签枚举
class Disposition(str, Enum):
KEEP = "保留"
CANDIDATE_DELETE = "候选删除"
CANDIDATE_ARCHIVE = "候选归档"
NEEDS_REVIEW = "待确认"
@dataclass
class InventoryItem:
"""清单条目"""
rel_path: str
category: Category
disposition: Disposition
description: str
def classify(entry: FileEntry) -> InventoryItem:
"""根据路径、扩展名等规则对单个文件/目录进行分类和标签分配"""
...
def build_inventory(entries: list[FileEntry]) -> list[InventoryItem]:
"""批量分类所有文件条目"""
...
def render_inventory_report(items: list[InventoryItem], repo_root: str) -> str:
"""生成 Markdown 格式的文件清单报告"""
...
```
**分类规则(按优先级从高到低)**
| 路径模式 | 用途分类 | 默认处置 |
|---------|---------|---------|
| `tmp/` 下所有文件 | 临时与调试 | 候选删除/候选归档 |
| `logs/``export/` 下的运行时产出 | 日志与输出 | 候选归档 |
| `*.lnk``*.rar` 文件 | 其他 | 候选删除 |
| 空目录(如 `Deleded & backup/` | 其他 | 候选删除 |
| `tasks/``loaders/``scd/``orchestration/``quality/``models/``utils/``api/` | 核心代码 | 保留 |
| `config/` | 配置 | 保留 |
| `database/*.sql``database/migrations/` | 数据库定义 | 保留 |
| `database/*.py` | 核心代码 | 保留 |
| `tests/` | 测试 | 保留 |
| `docs/` | 文档 | 保留 |
| `scripts/` 下的 `.py` 文件 | 脚本工具 | 保留/待确认 |
| `gui/` | GUI | 保留 |
| `setup.py``build_exe.py``*.bat``*.sh``*.ps1` | 构建与部署 | 保留 |
| 根目录散落文件(`Prompt用.md``Untitled``fix_symbols.py` 等) | 其他 | 待确认 |
### 3. 流程树分析器 (`scripts/audit/flow_analyzer.py`)
通过静态分析 Python 源码的 `import` 语句和类继承关系,构建从入口到末端模块的调用树。
```python
@dataclass
class FlowNode:
"""流程树节点"""
name: str # 节点名称(模块名/类名/函数名)
source_file: str # 所在源文件路径
node_type: str # 类型entry/module/class/function
children: list["FlowNode"]
def parse_imports(filepath: Path) -> list[str]:
"""使用 ast 模块解析 Python 文件的 import 语句,返回被导入的本地模块列表"""
...
def build_flow_tree(repo_root: Path, entry_file: str) -> FlowNode:
"""从指定入口文件出发,递归追踪 import 链,构建流程树"""
...
def find_orphan_modules(repo_root: Path, all_entries: list[FileEntry], reachable: set[str]) -> list[str]:
"""找出未被任何入口直接或间接引用的 Python 模块"""
...
def render_flow_report(trees: list[FlowNode], orphans: list[str], repo_root: str) -> str:
"""生成 Markdown 格式的流程树报告(含 Mermaid 图和缩进文本)"""
...
```
**入口点识别**
- CLI 入口:`cli/main.py``main()` 函数
- GUI 入口:`gui/main.py``main()` 函数
- 批处理入口:`run_etl.bat``run_gui.bat``run_ods.bat` → 解析其中的 `python` 命令
- 运维脚本:`scripts/*.py` → 各自的 `if __name__ == "__main__"`
**静态分析策略**
- 使用 Python `ast` 模块解析源文件,提取 `import``from ... import` 语句
- 仅追踪项目内部模块(排除标准库和第三方包)
- 通过 `orchestration/task_registry.py` 的注册语句识别所有任务类及其源文件
- 通过类继承关系(`BaseTask``BaseLoader``BaseDwsTask` 等)识别任务和加载器层级
### 4. 文档对齐分析器 (`scripts/audit/doc_alignment_analyzer.py`)
检查文档与代码之间的映射关系、过期点、冲突点和缺失点。
```python
@dataclass
class DocMapping:
"""文档与代码的映射关系"""
doc_path: str # 文档文件路径
doc_topic: str # 文档主题
related_code: list[str] # 关联的代码文件/模块
status: str # 状态aligned/stale/conflict/orphan
@dataclass
class AlignmentIssue:
"""对齐问题"""
doc_path: str
issue_type: str # stale/conflict/missing
description: str
related_code: str
def scan_docs(repo_root: Path) -> list[str]:
"""扫描所有文档文件路径"""
...
def extract_code_references(doc_path: Path) -> list[str]:
"""从文档中提取代码引用(文件路径、类名、函数名、表名等)"""
...
def check_reference_validity(ref: str, repo_root: Path) -> bool:
"""检查文档中的代码引用是否仍然有效"""
...
def find_undocumented_modules(repo_root: Path, documented: set[str]) -> list[str]:
"""找出缺少文档的核心代码模块"""
...
def check_ddl_vs_dictionary(repo_root: Path) -> list[AlignmentIssue]:
"""比对 DDL 文件与数据字典文档的覆盖度"""
...
def check_api_samples_vs_parsers(repo_root: Path) -> list[AlignmentIssue]:
"""比对 API 响应样本与 ODS 表结构/解析器的一致性"""
...
def render_alignment_report(mappings: list[DocMapping], issues: list[AlignmentIssue], repo_root: str) -> str:
"""生成 Markdown 格式的文档对齐报告"""
...
```
**文档来源识别**
- `docs/` 目录下的 `.md``.txt``.csv` 文件
- 根目录的 `README.md`
- `开发笔记/` 目录
- 各模块内的 `README.md``gui/README.md``fetch-test/README.md`
- `.kiro/steering/` 下的引导文件
- `docs/test-json-doc/` 下的 API 响应样本及分析文档
**对齐检查策略**
- 过期点检测:文档中引用的文件路径、类名、函数名在代码中已不存在
- 冲突点检测DDL 中的表/字段定义与数据字典文档不一致API 样本字段与解析器不匹配
- 缺失点检测:核心代码模块(`tasks/``loaders/``orchestration/` 等)缺少对应文档
### 5. 审计主入口 (`scripts/audit/run_audit.py`)
```python
def run_audit(repo_root: Path | None = None) -> None:
"""执行完整审计流程,生成三份报告到 docs/audit/"""
...
if __name__ == "__main__":
run_audit()
```
## 数据模型
### FileEntry文件元信息
| 字段 | 类型 | 说明 |
|------|------|------|
| `rel_path` | `str` | 相对路径 |
| `is_dir` | `bool` | 是否为目录 |
| `size_bytes` | `int` | 文件大小 |
| `extension` | `str` | 扩展名 |
| `is_empty_dir` | `bool` | 是否为空目录 |
### InventoryItem清单条目
| 字段 | 类型 | 说明 |
|------|------|------|
| `rel_path` | `str` | 相对路径 |
| `category` | `Category` | 用途分类 |
| `disposition` | `Disposition` | 处置标签 |
| `description` | `str` | 简要说明 |
### FlowNode流程树节点
| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | `str` | 节点名称 |
| `source_file` | `str` | 源文件路径 |
| `node_type` | `str` | 节点类型 |
| `children` | `list[FlowNode]` | 子节点列表 |
### DocMapping / AlignmentIssue文档对齐
| 字段 | 类型 | 说明 |
|------|------|------|
| `doc_path` | `str` | 文档路径 |
| `doc_topic` / `issue_type` | `str` | 主题/问题类型 |
| `related_code` | `list[str]` / `str` | 关联代码 |
| `status` / `description` | `str` | 状态/描述 |
## 正确性属性
*属性Property是指在系统所有合法执行路径上都应成立的特征或行为——本质上是对"系统应该做什么"的形式化陈述。属性是连接人类可读规格说明与机器可验证正确性保证之间的桥梁。*
### Property 1: classify 完整性
*对于任意* `FileEntry``classify` 函数返回的 `InventoryItem``category` 字段应属于 `Category` 枚举,`disposition` 字段应属于 `Disposition` 枚举,且 `description` 字段为非空字符串。
**Validates: Requirements 1.2, 1.3**
### Property 2: 清单渲染完整性
*对于任意* `InventoryItem` 列表,`render_inventory_report` 生成的 Markdown 文本中,每个条目对应的行应包含该条目的 `rel_path``category.value``disposition.value``description` 四个字段。
**Validates: Requirements 1.4**
### Property 3: 空目录标记为候选删除
*对于任意* `is_empty_dir=True``FileEntry``classify` 返回的 `disposition` 应为 `Disposition.CANDIDATE_DELETE`
**Validates: Requirements 1.5**
### Property 4: .lnk/.rar 文件标记为候选删除
*对于任意* 扩展名为 `.lnk``.rar``FileEntry``classify` 返回的 `disposition` 应为 `Disposition.CANDIDATE_DELETE`
**Validates: Requirements 1.6**
### Property 5: tmp/ 下文件处置范围
*对于任意* `rel_path``tmp/` 开头的 `FileEntry``classify` 返回的 `disposition` 应为 `Disposition.CANDIDATE_DELETE``Disposition.CANDIDATE_ARCHIVE` 之一。
**Validates: Requirements 1.7**
### Property 6: 运行时产出目录标记为候选归档
*对于任意* `rel_path``logs/``export/` 开头且非 `__init__.py``FileEntry``classify` 返回的 `disposition` 应为 `Disposition.CANDIDATE_ARCHIVE`
**Validates: Requirements 1.8**
### Property 7: 扫描器排除规则
*对于任意* 文件树,`scan_repo` 返回的 `FileEntry` 列表中不应包含 `rel_path` 匹配排除模式(`.git``__pycache__``.pytest_cache`)的条目。
**Validates: Requirements 1.1**
### Property 8: 清单按分类分组
*对于任意* `InventoryItem` 列表,`render_inventory_report` 生成的 Markdown 中,同一 `Category` 的条目应连续出现(即按分类分组排列)。
**Validates: Requirements 1.10**
### Property 9: 流程树节点 source_file 有效性
*对于任意* `FlowNode` 树中的节点,`source_file` 字段应为非空字符串,且对应的文件在仓库中实际存在。
**Validates: Requirements 2.7**
### Property 10: 孤立模块检测正确性
*对于任意* 文件集合和可达模块集合,`find_orphan_modules` 返回的孤立模块列表中的每个模块都不应出现在可达集合中,且可达集合中的每个模块都不应出现在孤立列表中。
**Validates: Requirements 2.8**
### Property 11: 过期引用检测
*对于任意* 文档中提取的代码引用,若该引用指向的文件路径在仓库中不存在,则 `check_reference_validity` 应返回 `False`
**Validates: Requirements 3.3**
### Property 12: 缺失文档检测
*对于任意* 核心代码模块集合和已文档化模块集合,`find_undocumented_modules` 返回的缺失列表应恰好等于核心模块集合与已文档化集合的差集。
**Validates: Requirements 3.5**
### Property 13: 统计摘要一致性
*对于任意* 报告的统计摘要,各分类/标签的计数之和应等于对应条目列表的总长度。
**Validates: Requirements 4.5, 4.6, 4.7**
### Property 14: 报告头部元信息
*对于任意* 报告输出,头部应包含一个符合 ISO 格式的时间戳字符串和仓库根目录路径字符串。
**Validates: Requirements 4.2**
### Property 15: 写操作仅限 docs/audit/
*对于任意* 审计执行过程,所有文件写操作的目标路径应以 `docs/audit/` 为前缀。
**Validates: Requirements 5.2**
### Property 16: 文档对齐报告分区完整性
*对于任意* `render_alignment_report` 的输出Markdown 文本应包含"映射关系"、"过期点"、"冲突点"、"缺失点"四个分区标题。
**Validates: Requirements 3.8**
## 错误处理
| 场景 | 处理方式 |
|------|---------|
| 文件读取权限不足 | 记录警告到报告的"错误"分区,跳过该文件,继续处理 |
| Python 源文件语法错误(`ast.parse` 失败) | 记录警告,将该文件标记为"待确认",不中断流程树构建 |
| 文档中的代码引用格式无法解析 | 跳过该引用,不产生误报 |
| DDL 文件 SQL 语法不规范 | 使用正则提取 `CREATE TABLE` 和列定义,容忍非标准语法 |
| `docs/audit/` 目录创建失败 | 抛出异常并终止,因为无法输出报告 |
| 编码问题(非 UTF-8 文件) | 尝试 `utf-8``gbk``latin-1` 回退读取,记录编码警告 |
## 测试策略
### 测试框架
- 单元测试与属性测试均使用 `pytest`
- 属性测试库:`hypothesis`Python 生态最成熟的属性测试框架)
- 测试文件位于 `tests/unit/test_audit_*.py`
### 单元测试
针对具体示例和边界情况:
- 扫描器对实际仓库子集的遍历结果
- classify 对已知文件路径的分类正确性(如 `tmp/hebing.py` → 临时与调试/候选删除)
- 入口点识别对实际仓库的结果
- DDL 与数据字典的比对结果
- 文件读取失败时的容错行为
- `docs/audit/` 目录不存在时的自动创建
### 属性测试
每个正确性属性对应一个属性测试,使用 `hypothesis` 生成随机输入:
- 每个属性测试至少运行 100 次迭代
- 每个测试用注释标注对应的设计属性编号
- 标注格式:**Feature: repo-audit, Property {N}: {属性标题}**
**生成器策略**
- `FileEntry` 生成器:随机路径(含各种扩展名、目录层级)、随机大小、随机 is_dir/is_empty_dir
- `InventoryItem` 生成器:随机 Category/Disposition 组合、随机描述文本
- `FlowNode` 生成器:随机树结构(限制深度和宽度)
- 文件树生成器:构造临时目录结构用于扫描器测试

View File

@@ -0,0 +1,90 @@
# 需求文档:仓库治理只读审计
## 简介
对飞球 ETL 系统 (etl-billiards) 仓库进行全面的只读审计分析,产出三份结构化报告:文件/目录清单(含处置建议)、项目流程树(从入口到末端逻辑)、文档对齐报告(文档与代码的映射关系)。本阶段不修改任何文件,所有处置决策留待用户逐一确认后再执行。
## 术语表
- **审计脚本 (Audit_Script)**:执行只读分析并生成报告的 Python 脚本集合
- **文件清单 (File_Inventory)**:按用途归类的仓库文件与目录列表,每项附带处置标签
- **处置标签 (Disposition_Tag)**:对文件/目录的处置建议,取值为:保留、候选删除、候选归档、待确认
- **流程树 (Flow_Tree)**:从程序入口出发,沿调用链展开到各子模块/子逻辑的树状结构
- **文档对齐报告 (Doc_Alignment_Report)**:文档与代码之间映射关系的分析报告,包含过期点、冲突点、缺失点
- **入口 (Entry_Point)**:程序的顶层启动点,如 `cli/main.py``gui/main.py``scripts/*.py`
- **ODS/DWD/DWS**:数据仓库三层架构——操作数据存储层/明细数据层/数据服务层
- **SCD2**:缓慢变化维度类型 2维度表的历史版本管理策略
## 需求
### 需求 1文件与目录清单生成
**用户故事:** 作为项目维护者,我希望获得一份按用途归类的仓库文件与目录清单,以便了解每个文件的角色并决定其去留。
#### 验收标准
1. WHEN 审计脚本扫描仓库根目录时THE Audit_Script SHALL 递归遍历所有文件和目录(排除 `.git/``__pycache__/``.pytest_cache/` 等运行时缓存目录)
2. WHEN 审计脚本处理每个文件或目录时THE Audit_Script SHALL 将其归入以下用途分类之一核心代码、配置、数据库定义、测试、文档、脚本工具、GUI、构建与部署、日志与输出、临时与调试、其他
3. WHEN 审计脚本完成归类后THE Audit_Script SHALL 为每个条目分配一个处置标签(保留/候选删除/候选归档/待确认)
4. WHEN 审计脚本生成清单时THE File_Inventory SHALL 包含以下字段:相对路径、用途分类、处置标签、简要说明
5. WHEN 审计脚本遇到空目录(如 `database/Deleded & backup/``scripts/Deleded & backup/`THE Audit_Script SHALL 将其标记为"候选删除"
6. WHEN 审计脚本遇到 `.lnk` 快捷方式文件或 `.rar` 压缩包时THE Audit_Script SHALL 将其标记为"候选删除"
7. WHEN 审计脚本遇到 `tmp/` 目录下的文件时THE Audit_Script SHALL 逐一评估并标记为"候选删除"或"候选归档"
8. WHEN 审计脚本遇到 `logs/``export/` 目录下的运行时产出文件时THE Audit_Script SHALL 将其标记为"候选归档"
9. IF 审计脚本无法确定某文件的用途分类THEN THE Audit_Script SHALL 将其标记为"待确认"并在说明中注明原因
10. WHEN 审计脚本完成清单生成后THE File_Inventory SHALL 以 Markdown 表格格式输出,按用途分类分组排列
### 需求 2项目流程树生成
**用户故事:** 作为项目维护者,我希望获得一份从入口到各子模块的调用流程树,以便理解系统的执行路径和模块依赖关系。
#### 验收标准
1. WHEN 审计脚本分析项目入口时THE Audit_Script SHALL 识别以下入口点:`cli/main.py`CLI 主入口)、`gui/main.py`GUI 主入口)、`scripts/*.py`(运维脚本)、批处理文件(`run_etl.bat``run_gui.bat``run_ods.bat` 等)
2. WHEN 审计脚本从 CLI 入口展开时THE Flow_Tree SHALL 追踪以下调用链CLI 参数解析 → 配置加载 → 调度器初始化 → 任务注册表查询 → 任务执行Extract → Transform → Load→ 加载器调用 → 数据库操作
3. WHEN 审计脚本从 GUI 入口展开时THE Flow_Tree SHALL 追踪以下调用链GUI 主窗口初始化 → 各面板/组件加载 → 后台工作线程 → CLI 命令构建 → 任务执行
4. WHEN 审计脚本分析任务模块时THE Flow_Tree SHALL 区分以下任务类型ODS 抓取任务、DWD 加载任务、DWS 汇总任务、校验任务、Schema 初始化任务
5. WHEN 审计脚本分析加载器模块时THE Flow_Tree SHALL 区分以下加载器类型ODS 通用加载器、维度加载器SCD2、事实表加载器
6. WHEN 审计脚本生成流程树时THE Flow_Tree SHALL 以缩进文本或 Mermaid 图的形式输出,层级深度至少达到函数/方法级别
7. WHEN 审计脚本分析模块依赖时THE Flow_Tree SHALL 标注每个节点所在的源文件路径
8. IF 审计脚本发现存在孤立模块未被任何入口直接或间接引用的代码文件THEN THE Flow_Tree SHALL 在报告末尾单独列出这些孤立模块
### 需求 3文档对齐报告生成
**用户故事:** 作为项目维护者,我希望了解现有文档与代码之间的对齐状况,以便识别过期、冲突和缺失的文档。
#### 验收标准
1. WHEN 审计脚本扫描文档目录时THE Audit_Script SHALL 识别以下文档来源:`docs/` 目录、`README.md``开发笔记/`、各模块内的 `README.md`(如 `gui/README.md``fetch-test/README.md`)、`.kiro/steering/` 下的引导文件
2. WHEN 审计脚本分析每份文档时THE Doc_Alignment_Report SHALL 建立文档与代码模块之间的映射关系
3. WHEN 审计脚本检测到文档引用了已不存在的代码实体函数、类、文件路径THE Doc_Alignment_Report SHALL 将该引用标记为"过期点"
4. WHEN 审计脚本检测到文档描述与代码实际行为不一致时THE Doc_Alignment_Report SHALL 将该处标记为"冲突点"
5. WHEN 审计脚本检测到核心代码模块缺少对应文档时THE Doc_Alignment_Report SHALL 将该模块标记为"缺失点"
6. WHEN 审计脚本分析 DDL 文件(`database/schema_*.sql`THE Doc_Alignment_Report SHALL 检查数据字典文档(`docs/dwd_main_tables_dictionary.md``docs/dws_tables_dictionary.md`)是否覆盖了所有表和字段
7. WHEN 审计脚本分析 `docs/test-json-doc/` 下的 API 响应样本时THE Doc_Alignment_Report SHALL 检查样本字段是否与 ODS 表结构和解析器(`models/parsers.py`)一致
8. WHEN 审计脚本完成分析后THE Doc_Alignment_Report SHALL 以 Markdown 格式输出,包含以下分区:映射关系表、过期点列表、冲突点列表、缺失点列表
### 需求 4报告输出与格式规范
**用户故事:** 作为项目维护者,我希望审计报告以统一、可读的格式输出,以便后续逐项决策和执行。
#### 验收标准
1. THE Audit_Script SHALL 将三份报告输出到 `docs/audit/` 目录下,文件名分别为 `file_inventory.md``flow_tree.md``doc_alignment.md`
2. THE Audit_Script SHALL 在每份报告的头部包含生成时间戳和仓库根目录路径
3. WHEN 报告引用代码标识符类名、函数名、变量名、文件路径THE Audit_Script SHALL 保留英文原文,使用行内代码格式(反引号)
4. WHEN 报告包含说明性文字时THE Audit_Script SHALL 使用简体中文
5. THE Audit_Script SHALL 在文件清单报告末尾附加统计摘要:各用途分类的文件数量、各处置标签的文件数量
6. THE Audit_Script SHALL 在流程树报告末尾附加统计摘要:入口点数量、任务数量、加载器数量、孤立模块数量
7. THE Audit_Script SHALL 在文档对齐报告末尾附加统计摘要:过期点数量、冲突点数量、缺失点数量
### 需求 5只读安全保障
**用户故事:** 作为项目维护者,我希望审计过程不会修改仓库中的任何文件,以确保分析阶段的安全性。
#### 验收标准
1. THE Audit_Script SHALL 仅执行文件系统的读取操作(读取文件内容、列出目录、获取文件元信息)
2. THE Audit_Script SHALL 仅在 `docs/audit/` 目录下创建新文件,该目录为报告专用输出目录
3. IF 审计脚本在执行过程中遇到权限错误或文件读取失败THEN THE Audit_Script SHALL 在报告中记录该错误并继续处理其余文件
4. THE Audit_Script SHALL 在运行前检查 `docs/audit/` 目录是否存在,若不存在则创建该目录

View File

@@ -0,0 +1,118 @@
# 实施计划:仓库治理只读审计
## 概述
将设计文档中的审计脚本拆分为增量式编码任务。每个任务构建在前一个任务之上,最终产出可运行的审计工具集。所有脚本位于 `scripts/audit/` 目录,报告输出到 `docs/audit/`
## 任务
- [x] 1. 搭建审计脚本骨架和数据模型
- [x] 1.1 创建 `scripts/audit/__init__.py` 和数据模型定义
- 定义 `FileEntry` dataclass`rel_path`, `is_dir`, `size_bytes`, `extension`, `is_empty_dir`
- 定义 `Category``Disposition` 枚举
- 定义 `InventoryItem` dataclass
- 定义 `FlowNode` dataclass
- 定义 `DocMapping``AlignmentIssue` dataclass
- _Requirements: 1.2, 1.3, 1.4, 2.7, 3.2, 3.3_
- [x] 1.2 编写 classify 完整性属性测试
- **Property 1: classify 完整性**
- **Validates: Requirements 1.2, 1.3**
- [x] 2. 实现仓库扫描器
- [x] 2.1 创建 `scripts/audit/scanner.py`
- 实现 `EXCLUDED_PATTERNS` 常量和排除匹配逻辑
- 实现 `scan_repo(root, exclude)` 函数:递归遍历文件系统,返回 `list[FileEntry]`
- 处理空目录检测(`is_empty_dir`
- 处理文件读取权限错误(跳过并记录)
- _Requirements: 1.1, 5.1, 5.3_
- [x] 2.2 编写扫描器排除规则属性测试
- **Property 7: 扫描器排除规则**
- **Validates: Requirements 1.1**
- [x] 3. 实现文件清单分析器
- [x] 3.1 创建 `scripts/audit/inventory_analyzer.py`
- 实现 `classify(entry: FileEntry) -> InventoryItem` 函数,包含完整分类规则表
- 实现 `build_inventory(entries) -> list[InventoryItem]` 批量分类函数
- 实现 `render_inventory_report(items, repo_root) -> str` Markdown 渲染函数
- 包含统计摘要生成(各分类/标签计数)
- 注意:需求 1.8 仅覆盖 `logs/``export/` 目录(不含 `reports/`
- _Requirements: 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 4.2, 4.5_
- [x] 3.2 编写 classify 分类规则属性测试
- **Property 3: 空目录标记为候选删除**
- **Property 4: .lnk/.rar 文件标记为候选删除**
- **Property 5: tmp/ 下文件处置范围**
- **Property 6: 运行时产出目录标记为候选归档**(仅 `logs/``export/`
- **Validates: Requirements 1.5, 1.6, 1.7, 1.8**
- [x] 3.3 编写清单渲染属性测试
- **Property 2: 清单渲染完整性**
- **Property 8: 清单按分类分组**
- **Validates: Requirements 1.4, 1.10**
- [x] 4. 检查点 - 确保文件清单模块测试通过
- 确保所有测试通过,如有疑问请向用户确认。
- [x] 5. 实现流程树分析器
- [x] 5.1 创建 `scripts/audit/flow_analyzer.py`
- 实现 `parse_imports(filepath)` 函数:使用 `ast` 模块解析 Python 文件的 import 语句
- 实现 `build_flow_tree(repo_root, entry_file)` 函数:从入口递归追踪 import 链
- 实现 `find_orphan_modules(repo_root, all_entries, reachable)` 函数
- 实现 `render_flow_report(trees, orphans, repo_root)` 函数:生成 Mermaid 图和缩进文本
- 包含入口点识别逻辑CLI、GUI、批处理、运维脚本
- 包含任务类型和加载器类型区分逻辑
- 包含统计摘要生成
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 4.6_
- [x] 5.2 编写流程树属性测试
- **Property 9: 流程树节点 source_file 有效性**
- **Property 10: 孤立模块检测正确性**
- **Validates: Requirements 2.7, 2.8**
- [x] 6. 实现文档对齐分析器
- [x] 6.1 创建 `scripts/audit/doc_alignment_analyzer.py`
- 实现 `scan_docs(repo_root)` 函数:扫描所有文档来源
- 实现 `extract_code_references(doc_path)` 函数:从文档提取代码引用
- 实现 `check_reference_validity(ref, repo_root)` 函数
- 实现 `find_undocumented_modules(repo_root, documented)` 函数
- 实现 `check_ddl_vs_dictionary(repo_root)` 函数DDL 与数据字典比对
- 实现 `check_api_samples_vs_parsers(repo_root)` 函数API 样本与解析器比对
- 实现 `render_alignment_report(mappings, issues, repo_root)` 函数
- 包含统计摘要生成
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 4.7_
- [x] 6.2 编写文档对齐属性测试
- **Property 11: 过期引用检测**
- **Property 12: 缺失文档检测**
- **Property 16: 文档对齐报告分区完整性**
- **Validates: Requirements 3.3, 3.5, 3.8**
- [x] 7. 检查点 - 确保流程树和文档对齐模块测试通过
- 确保所有测试通过,如有疑问请向用户确认。
- [x] 8. 实现审计主入口和报告输出
- [x] 8.1 创建 `scripts/audit/run_audit.py`
- 实现 `run_audit(repo_root)` 主函数:依次调用扫描器和三个分析器
- 实现 `docs/audit/` 目录检查与创建逻辑
- 实现报告头部元信息(时间戳、仓库路径)注入
- 实现三份报告的文件写入
- 添加 `if __name__ == "__main__"` 入口
- _Requirements: 4.1, 4.2, 4.3, 4.4, 5.2, 5.4_
- [x] 8.2 编写报告输出属性测试
- **Property 13: 统计摘要一致性**
- **Property 14: 报告头部元信息**
- **Property 15: 写操作仅限 docs/audit/**
- **Validates: Requirements 4.2, 4.5, 4.6, 4.7, 5.2**
- [x] 9. 最终检查点 - 确保所有测试通过
- 确保所有测试通过,如有疑问请向用户确认。
## 备注
- 标记 `*` 的子任务为可选,可跳过以加速 MVP 交付
- 每个任务引用了具体的需求编号,便于追溯
- 属性测试使用 `hypothesis` 库,每个测试至少 100 次迭代
- 单元测试验证具体示例和边界情况,属性测试验证通用正确性