원클릭으로
knowledge-graph
代码知识图谱 — 四层递进分析(符号表→调用链→数据流→模块依赖),产出完整结构化 Markdown 技术文档供 Loop Agent 和开发者阅读。每个文件有详细分析、每段关键代码有决策解释、模块间有影响矩阵。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
代码知识图谱 — 四层递进分析(符号表→调用链→数据流→模块依赖),产出完整结构化 Markdown 技术文档供 Loop Agent 和开发者阅读。每个文件有详细分析、每段关键代码有决策解释、模块间有影响矩阵。
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | knowledge-graph |
| description | 代码知识图谱 — 四层递进分析(符号表→调用链→数据流→模块依赖),产出完整结构化 Markdown 技术文档供 Loop Agent 和开发者阅读。每个文件有详细分析、每段关键代码有决策解释、模块间有影响矩阵。 |
| argument-hint | graph [path] | map [repo] relationships | trace [function] call chain |
| triggers | ["谁调用了","调用链","数据流","模块依赖","循环依赖","扇入","扇出"] |
不是读代码,是建一张可查询的关系网,并写成完整的技术文档。 四层递进:
符号表 (有什么) → 调用链 (谁调谁) → 数据流 (数据去哪) → 模块依赖 (模块怎么连)
每一层是下一层的基础。上一层没跑完,不进下一层。
旧版输出: 几百字节的 JSON → 塞进 state 文件 → 没人看、不能用。
新版输出: 完整的 Markdown 文档 → 写入 docs/loop-docs/ → Loop Agent 和开发者都能直接阅读。
输出目标: 即使没有 AI Agent,一个人类开发者打开 docs/loop-docs/knowledge-graph.md 就能完整理解这个项目的代码结构和调用关系。
所有文件写入项目根目录的 docs/loop-docs/:
| 文件 | 内容 | 何时生成 |
|---|---|---|
knowledge-graph.md | 四层完整分析 + 架构总览 | 始终 |
symbol-index.md | 按字母排序的符号索引表 | L1 完成后 |
call-graph.md | 树状调用链(从入口点展开) | L2 完成后 |
module-dependencies.md | 模块依赖矩阵 + 影响分析 | L4 完成后 |
| 深度 | 文件数 | 跑哪些层 | 核心产出 |
|---|---|---|---|
quick | < 100 | L1 符号表 + L4 模块依赖 | 模块依赖图 + 完整符号清单 |
standard | 100 - 500 | L1 + L2 + L4 | + 完整树状调用链 + 每个文件的调用关系 |
deep | > 500 | L1 + L2 + L3 + L4 | + 核心数据流追踪 + 代码决策分析 |
目标: 建立所有可引用符号的完整清单,每个符号附带它所在文件的上下文分析。
| 语言 | 首选工具 | 后备 |
|---|---|---|
| TypeScript / JavaScript | get_symbols (tree-sitter AST) | search_content "export (function|class|const|type|interface)" |
| Python | get_symbols (tree-sitter AST) | search_content "^def |^class " |
| Go | get_symbols (tree-sitter AST) | search_content "^func |^type " |
| Rust | get_symbols (tree-sitter AST) | search_content "^pub (fn|struct|enum|trait)" |
| Java | get_symbols (tree-sitter AST) | search_content "public (class|interface|enum)" |
| 其他 | search_content 按语言约定匹配 | — |
1. glob 列出所有源文件(按语言扩展名过滤)
2. 对每个文件调用 get_symbols,收集所有 definition 类符号
3. 过滤:保留 exported 符号 + 非导出但被同文件外引用的符号
4. 去重:同一符号名在不同文件 → 按文件路径区分
5. 对每个文件:read_file 读关键段落 → 写文件级分析
docs/loop-docs/symbol-index.md每个文件作为一节,包含:
## src/auth/login.ts (127 行)
**职责**: 用户登录端点,验证凭证并返回 JWT token
**入口**: `POST /auth/login` → `handleLogin(req, res)`
**关键符号**:
| 符号 | 类型 | 行号 | 可见性 | 说明 |
|---|---|---|---|---|
| `handleLogin` | async function | 15 | exported | 主处理函数——验证用户名/密码 → 签发 JWT |
| `validateCredentials` | function | 48 | private | 查询数据库验证密码哈希 |
| `signToken` | function | 82 | private | 用 HS256 签发 24h 过期 token |
| `LoginRequest` | interface | 8 | exported | 请求体 { username, password } |
| `LoginResponse` | interface | 12 | exported | 响应体 { token, expiresAt } |
**关键代码段**:
- L15-24: `handleLogin` 首先检查 rate-limit,使用 `checkRateLimit()` 防暴力破解。选择 rate-limit 在前而非在后是因为如果凭证无效仍需消耗限流配额来防止字典攻击。
- L48-62: `validateCredentials` 使用 bcrypt.compare 而非直接比较——密码从不以明文存储或比较。
- L82-95: `signToken` 的过期时间硬编码为 24h——如果改为配置项会影响所有客户端的刷新逻辑。
**依赖关系**:
- 上游调用者: `src/api/router.ts:33` (路由注册)
- 下游被调用: `src/auth/ratelimit.ts`, `src/db/users.ts`, `src/auth/jwt.ts`
前提: L1 符号表已完成。
目标: 从每个入口点出发,追踪完整的调用树,一直追到叶子节点。
1. 对每个入口点函数,用 find_in_code 在该文件内找它调用了什么 (kind: call)
2. 对每个被调用的符号,search_content 跨文件搜它的定义位置
3. 递归追踪,直到:
- 到达第三方库调用 (标记 [external])
- 到达无更多调用的叶子函数
- 到达已追踪过的函数 (标记 [recursive] 避免死循环)
4. 只记录同项目内的调用——第三方库标记 external 但不继续追踪
5. 每个调用边上标注调用行号和上下文(为什么在这里调用)
工具注册表 / 路由表 / 命令表只能证明"有哪些工具",不能证明"工具的实现质量"。
发现以下模式后必须继续追踪 handler 函数:
tool_table[] / tool_registry[] / route_table[]register_tool() / add_command() / app.get() / router.post()docs/loop-docs/call-graph.md以树状结构从每个入口点展开:
## 调用树: main() → 全链路
### 入口: `main()` @ `src/main.ts:42`
main() [src/main.ts:42] ├── Config.load() [src/config.ts:18] ← L45: 启动时加载配置 │ ├── parseEnvFile() [src/config.ts:30] ← 读取 .env │ │ └── fs.readFileSync() [external] ← Node 标准库 │ └── validateSchema() [src/config.ts:55] ← 校验配置格式 │ └── Ajv.validate() [external] ├── Database.connect() [src/db/index.ts:10] ← L48: 数据库连接池初始化 │ ├── Pool.create() [src/db/pool.ts:5] │ │ └── pg.Pool() [external] │ └── runMigrations() [src/db/migrate.ts:22] │ ├── readMigrationFiles() [src/db/migrate.ts:8] │ └── executeSQL() [src/db/migrate.ts:35] ├── Router.register() [src/api/router.ts:15] ← L52: 注册所有 API 路由 │ ├── app.post("/auth/login", auth.handleLogin) │ ├── app.get("/stocks/:code", stocks.getStock) │ └── app.use(authMiddleware) ← 全局认证中间件 └── Server.listen() [external] ← L60: 启动 HTTP 监听
### 调用统计
| 函数 | 文件 | 被调次数 | 调用数 | 深度 | 说明 |
|---|---|---|---|---|---|
| `Config.load` | src/config.ts:18 | 8 | 3 | 2 | 🟡 被 8 处调用——配置加载是基础设施 |
| `handleLogin` | src/auth/login.ts:15 | 1 | 4 | 4 | 仅路由调用,内部链路深 |
| `_formatPercent` | src/utils/format.ts:88 | 12 | 0 | 0 | 🟡 被 12 处调用——工具函数,需保持签名稳定 |
### 入口点清单
| 入口 | 文件 | 触发方式 | 调用深度 |
|---|---|---|---|
| `main()` | src/main.ts:42 | 进程启动 | 6 层 |
| `handleLogin()` | src/auth/login.ts:15 | POST /auth/login | 4 层 |
| `cronJob()` | src/scheduler.ts:10 | 定时任务 | 3 层 |
### 候选死代码
| 符号 | 文件 | 原因 | 删除保护检查 |
|---|---|---|---|
| `oldParser()` | src/parser.ts:200 | 扇入=0, 非导出 | 需检查: 动态 import? 测试引用? |
| `legacyHelper()` | src/utils/legacy.ts:45 | 扇入=0, 非导出 | 未发现引用, 可安全删除 |
entryPoints 至少有一个callGraph 中的 caller 全部在 L1 符号表中前提: L1 + L2 已完成。仅 deep 模式运行。
目标: 追踪核心数据结构的完整生命周期,解释每个阶段的设计决策。
knowledge-graph.md 的数据流章节)## 数据流分析
### `User` 类型 — 用户认证数据流
**定义**: `src/models/user.ts:5` — 7 个字段(id, username, passwordHash, email, role, createdAt, lastLoginAt)
**设计决策**:
- `passwordHash` 而非 `password`: 从不存储明文——bcrypt 哈希在 `validateCredentials` 中验证。
- `role` 是 enum 而非 string: 防止 SQL 注入利用角色字段提权,只有预定义的 3 种角色。
- `createdAt` 和 `lastLoginAt` 分离: 支持审计追踪(账户创建时间 vs 最近活跃时间)。
**完整生命周期**:
[创建] handler.parseUser() @ src/handler.ts:30 输入: JSON body { username, password, email } 处理: 校验 username 格式 → 检查 email 唯一性 → bcrypt 哈希密码 输出: User 对象(无 id——数据库自增) ↓ [校验] validator.check() @ src/validator.ts:12 输入: 未验证的 User 对象 处理: email 正则校验 → username 长度 ≥3 → password 强度 ≥8 位 输出: ValidationResult { valid: bool, errors: [] } ↓ [持久化] db.insertUser() @ src/db/users.ts:55 输入: 已验证的 User 对象 处理: INSERT INTO users ... RETURNING id 输出: User 对象(带数据库生成的 id) ↓ [缓存] cache.setUser() @ src/cache/users.ts:20 输入: id + User 对象 处理: Redis SETEX user:{id} 3600 {json} 决策: 1 小时 TTL——平衡了性能和用户信息变更的实时性 ↓ [读取] api.getUser() @ src/api/users.ts:22 输入: userId (URL param) 处理: 先查 Redis → miss 则查 PostgreSQL → 回填缓存 决策: Cache-aside 模式——避免缓存不一致 ↓ [序列化] json.Marshal() @ src/api/users.ts:25 输入: User 对象 处理: 排除 passwordHash 字段 (json:"-") 决策: 结构体 tag 控制序列化——比手动构建 JSON 更安全,不会遗漏新字段
### 数据流总览
| 数据结构 | 字段数 | 引用次数 | 生命周期步骤 | 跨模块 |
|---|---|---|---|---|
| User | 7 | 15 | 5 (创建→校验→存储→读取→序列化) | ✅ 4 模块 |
| Order | 12 | 23 | 6 (创建→校验→风控→存储→通知→归档) | ✅ 6 模块 |
| AnalysisResult | 28 | 45 | 3 (生成→格式化→推送) | ✅ 3 模块 |
前提: L1 符号表已完成。所有深度都运行。
目标: 汇总模块间依赖关系,生成影响矩阵和风险分析。
docs/loop-docs/module-dependencies.md## 模块依赖图
src/api/ ──→ src/auth/ ──→ src/db/ │ │ │ └──→ src/cache/ │ └──→ src/services/ ──→ src/db/ │ └──→ src/notification/ ──→ src/templates/
## 模块职责 + 影响力分析
### `src/core/` — 核心引擎
**职责**: 任务调度、分析流水线、生命周期管理
**文件**: pipeline.py (450行), scheduler.py (320行), lifecycle.py (180行)
**入口**: `pipeline.py:StockAnalysisPipeline.run()`
**对外接口**: `run_pipeline(config)`, `get_pipeline_status()`
**依赖方向**:
- 依赖: `src/llm/`, `src/data_provider/`, `src/notification/`
- 被依赖: `main.py`, `src/services/scheduler.py`
**影响力**: 🔴 核心节点——被 6 个模块依赖
**修改此模块的风险**:
- `pipeline.py:run()` 是主入口——任何签名变更影响 main.py 和 scheduler
- `scheduler.py` 的 cron 表达式变更影响所有定时任务
- 修改前必须通过 `tests/test_pipeline*.py` 全部 12 个测试
### `src/notification/` — 通知层
**职责**: 多渠道消息推送(14 个通道)
**文件**: notification.py (1024行), notification_reports.py (1627行)
**入口**: `NotificationService.send()`
**对外接口**: `send_daily_report()`, `get_notification_service()`
**依赖方向**:
- 依赖: `src/notification_sender/` (14个sender), `src/config/`
- 被依赖: `src/core/pipeline.py`, `main.py`
**影响力**: 🟡 中等——被 3 个模块依赖
**修改此模块的风险**:
- 新增推送通道只需加 sender 实现——不影响现有通道
- `generate_*_report()` 方法签名变更影响所有调用者
- 14 个 sender 各自独立——单个修改爆炸半径小
## 模块依赖矩阵
| | api | core | auth | db | services | notification | llm | data_provider |
|---|---|---|---|---|---|---|---|---|
| **api** | - | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| **core** | ❌ | - | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| **auth** | ❌ | ❌ | - | ✅ | ❌ | ❌ | ❌ | ❌ |
| **db** | ❌ | ❌ | ❌ | - | ❌ | ❌ | ❌ | ❌ |
| **services** | ❌ | ❌ | ❌ | ✅ | - | ❌ | ❌ | ❌ |
| **notification** | ❌ | ❌ | ❌ | ❌ | ❌ | - | ❌ | ❌ |
| **llm** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | - | ❌ |
| **data_provider** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | - |
✅ = 行模块依赖列模块
## 风险结构
### 🔴 循环依赖
无
### 🟡 高扇入(≥5 个模块依赖它)
| 模块 | 扇入 | 依赖它的模块 |
|---|---|---|
| src/types/ | 8 | api, core, services, notification, db, llm, agent, data_provider |
| src/config/ | 7 | api, core, services, notification, llm, agent, bot |
### 🟡 高扇出(≥7 个模块被它依赖)
| 模块 | 扇出 | 它依赖的模块 |
|---|---|---|
| main.py | 9 | core, config, llm, services, notification, agent, db, api, bot |
### ⚪ 孤岛模块(扇入=0 且扇出=0)
无
docs/loop-docs/knowledge-graph.md这是合并四层分析的主文档,供 Loop Agent 和开发者阅读:
# [项目名] 代码知识图谱
## 元信息
- 仓库: owner/repo
- 语言: TypeScript (87%) + CSS (13%)
- 规模: M (187 源文件)
- 深度: standard
- 分析时间: 2026-07-12 14:30:00 UTC
## 架构总览
[从 L4 模块依赖图摘取的一段文字描述 + ASCII 依赖图]
## 入口点
[从 L2 入口点清单摘取]
## 符号统计
[从 L1 汇总: 总符号数 / 导出符号 / 类 / 函数 / 类型]
## 调用链
[从 call-graph.md 摘取关键路径,复杂调用链引用详细文件]
## 数据流(deep 模式)
[从 L3 摘取核心数据结构的生命周期]
## 模块依赖
[从 module-dependencies.md 摘取关键发现]
## 风险清单
[汇总: 循环依赖 / 高扇入 / 高扇出 / 孤岛 / 候选死代码]
## 文件清单
[所有源文件列表,每文件一行,含行数和职责一句话]
下限(低于此值 = 敷衍,不可接受):
| 文档 | 下限 | 检查方式 |
|---|---|---|
symbol-index.md | 每个源文件 ≥ 3 行(符号名/类型/一行说明) | 行数 / 文件数 ≥ 3 |
call-graph.md | 每个入口点有完整调用树(追到叶子或 external) | 调用边数 ≥ 符号数 × 0.5 |
module-dependencies.md | 依赖矩阵 + 所有警告 + 每个模块一行影响分析 | 矩阵行列 = 模块数 |
knowledge-graph.md | 四层摘要 + 入口点清单 + 风险清单 + 文件清单 | 主文档行数 ≥ 60 |
上限(超过此值 = 膨胀,需拆分):
| 文档 | 上限 | 超过时操作 |
|---|---|---|
symbol-index.md | 500 行 | 按目录拆分为 symbol-index-{dir}.md,主文档只保留索引 |
call-graph.md | 800 行 | 按入口点拆分为 call-graph-{entry}.md,主文档只保留入口点清单 + 调用统计 |
module-dependencies.md | 300 行 | 不拆分——模块数通常有限,超过说明分析过于啰嗦 |
knowledge-graph.md | 500 行 | 将各层详细内容推到子文档(已在设计中),主文档只保留总览 + 引用链接 |
规则: 超过上限时,将详细内容 push 到对应子文档,主文档保留 ≤ 上限的摘要 + 指向子文档的引用。
| # | Agent 借口 | 反驳 |
|---|---|---|
| 1 | "这个文件没有 export,跳过符号提取" | 没有 export 的文件可能是 CLI 入口或测试辅助,跳过导致调用链断裂 |
| 2 | "调用链只看前 3 层就够了" | 第 4-5 层的 bug 是最难排查的。不追踪到叶子节点 = 没做 |
| 3 | "数据流可以等需要时再追踪" | 数据流追踪耗时最长,等需要时再来追 → 整个流程被阻塞 |
| 4 | "模块依赖用肉眼看一下就行" | 肉眼看不出循环依赖的完整链路,也数不清扇入扇出 |
| 5 | "文件分析写个摘要就行了,不用解释为什么" | 技术文档的价值在"为什么"。只写"做了什么" = API 文档,不是技术文档 |
| 6 | "符号索引写太详细了,一个文件 5 行够了" | 5 行不够解释一段代码为什么那样写。Loop 的 Fix 阶段需要这些上下文来决定怎么改 |
| 7 | "调用树太深了,截断到 3 层" | 截断的调用树 = 残缺的地图。追到叶子或 external,不要截断 |
docs/loop-docs/knowledge-graph.md 已生成,包含完整的四层分析docs/loop-docs/symbol-index.md 每个源文件都有至少一节分析docs/loop-docs/call-graph.md 每个入口点都有完整调用树(追到叶子)docs/loop-docs/module-dependencies.md 包含依赖矩阵 + 影响分析file:line上下文园艺师 — 先读项目,再读 CLAUDE.md,逐层审计四层架构(CLAUDE.md → skills/ → hooks/ → memory/)。不做代码修改,只做审查、总结、归纳。生成建议报告,可视化花园输出。
将 repo-decompose 需求树 + mvp-approach 核心路径转化为分阶段可执行的交付计划。每个 Phase 有明确目标、任务清单、验收标准和依赖关系。
代码优化循环总控 — 12 阶段生命周期(2 前置门控 Detect+EnvReady,10 阶段优化闭环 Observe→Understand→Diagnose→Plan→Bound→Fix→Verify→SelfReview→Learn→Decide)。跨 Agent 自适应,环境自动就绪,任务驱动单流程。
基于 knowledge-graph 模块依赖 + mvp-approach 边界条件 + task-graph 任务清单,生成可修改文件白名单和禁止触碰红区。防止 Agent 无意中修改核心模块。
循环日志管理 — 每个阶段产出结构化 markdown 日志,记录完整分析过程,可追溯、可检索。自动保存到 .loop-log/,支持按阶段/日期/关键词检索。
最小可行性方案 — 基于已完成的全项目分析(repo-decompose + knowledge-graph + semantic-rag),设定最严格的最小边界条件,剪裁出刚好能跑的核心路径。