| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #!/usr/bin/env python3
- """Generate the auditable frontend deletion inventory from the working tree."""
- from __future__ import annotations
- import subprocess
- from collections import Counter, defaultdict
- from pathlib import Path
- ROOT = Path(__file__).resolve().parents[1]
- OUTPUT = ROOT / "docs" / "architecture" / "FRONTEND_REMOVAL_INVENTORY.md"
- def deleted_files() -> list[str]:
- result = subprocess.run(
- ["git", "diff", "--name-only", "--diff-filter=D", "--", "frontend"],
- cwd=ROOT,
- check=True,
- capture_output=True,
- text=True,
- )
- return sorted(line for line in result.stdout.splitlines() if line)
- def group_name(path: str) -> str:
- parts = Path(path).parts
- if len(parts) >= 5 and parts[:3] == ("frontend", "src", "views"):
- return f"views/{parts[3]}"
- if len(parts) >= 4 and parts[:3] == ("frontend", "src", "api"):
- return "api"
- if len(parts) >= 4 and parts[:3] == ("frontend", "src", "components"):
- return "components"
- if len(parts) >= 4 and parts[:3] == ("frontend", "src", "layout"):
- return "layout"
- return "/".join(parts[1:3])
- def render(files: list[str]) -> str:
- groups: dict[str, list[str]] = defaultdict(list)
- for path in files:
- groups[group_name(path)].append(path)
- counts = Counter({name: len(paths) for name, paths in groups.items()})
- lines = [
- "# 前端历史代码删除清单",
- "",
- "> 生成方式:`python scripts/generate_frontend_removal_inventory.py`。本文件基于当前未提交删除集生成;合并前应再次生成并复核。",
- "",
- "## 1. 基线与恢复方式",
- "",
- "- 原解析报告识别出 348 个前端未匹配调用,产品确认其主体为已下线后端服务遗留;本轮不重建这些旧接口。",
- f"- 当前 Git 删除集包含 {len(files)} 个前端文件;一个文件可包含多个调用,因此文件数不等于 348 个调用数。",
- "- 原始代码备份:`/Users/maxiaolong/Documents/Codex/2026-07-06/g-i/DataOps-platform-backup-before-cleanup-20260716-170321.tar.gz`。",
- "- SHA-256:`866c6c4aff127f88497a5ddf39ac8d8da93008cc784ae6f276f80a7cd17d4ef0`。",
- "- 恢复优先级:先从 Git 历史恢复单文件;若原始工作区未入库内容缺失,再从上述只读备份提取。禁止将整份备份直接覆盖当前工作区。",
- "",
- "## 2. 删除批次",
- "",
- "| 批次 | 范围 | 处置依据 |",
- "|---|---|---|",
- "| C1 | Vanna、Airflow、模型训练、问卷薪酬、图表定制 | 产品确认整体下线 |",
- "| C2 | 数据资源、数据模型、数据指标和旧数据资产原型 | 静态引用与路由复核后确认没有保留链路 |",
- "| C3 | 旧数据工厂非 n8n 页面、执行/调度/节点管理 | 执行能力统一由 n8n 提供 |",
- "| C4 | 旧系统管理、自助注册、租户、升级管理 | 后续以管理员/编辑者/查看者重建 |",
- "| C5 | 不可达公共组件、API 封装和演示页 | 无活跃路由或 import 消费方 |",
- "",
- "## 3. 明确保留例外",
- "",
- "- n8n 适配页面和 `/api/datafactory/*` 后端代理接口;Workflow 保留为 n8n 原生概念。",
- "- DataFlow 治理定义页面;后续新增一个 DataFlow 对多个 n8n Workflow 版本的映射。",
- "- 数据治理知识库入口和工作台;当前为验收占位,下一阶段补齐真实能力。",
- "- 数据安全入口;当前不宣称已实现安全治理能力。",
- "- HOPMS 数据导入工具及其验收样例。",
- "",
- "## 4. 按目录统计",
- "",
- "| 分组 | 删除文件数 |",
- "|---|---:|",
- ]
- for name, count in sorted(counts.items(), key=lambda item: (-item[1], item[0])):
- lines.append(f"| `{name}` | {count} |")
- lines.extend(
- [
- "",
- "## 5. 合并门禁",
- "",
- "1. `npm --prefix frontend run build` 成功。",
- "2. 路由表中不再出现已下线模块,活跃页面无失效 import。",
- "3. `tests/test_cleanup_contract.py`、Docker 静态隔离测试与本地冒烟测试全部通过。",
- "4. 数据安全、治理知识库、工作台、DataFlow 和 n8n 保留入口可访问。",
- "5. 生产数据库不执行删表;仅提交代码和建库脚本清理。",
- "",
- "## 6. 完整删除文件清单",
- "",
- ]
- )
- for name in sorted(groups):
- lines.append(f"### {name}")
- lines.append("")
- lines.extend(f"- `{path}`" for path in groups[name])
- lines.append("")
- return "\n".join(lines).rstrip() + "\n"
- def main() -> None:
- files = deleted_files()
- if not files:
- raise SystemExit("No deleted frontend files found in the working tree")
- OUTPUT.parent.mkdir(parents=True, exist_ok=True)
- OUTPUT.write_text(render(files), encoding="utf-8")
- print(f"Generated {OUTPUT.relative_to(ROOT)} with {len(files)} deleted files")
- if __name__ == "__main__":
- main()
|