backend-index

给本地后端项目建「模块 ↔ 目录/依赖/数据表」索引(.fe-index/):改模块前查依赖与被依赖,改表前查影响模块,接任务先看模块地图。触发:"后端索引"、"后端模块地图"、"改这个模块影响谁"、"改这张表影响哪些模块"。

SKILL.md

GitHub

后端模块索引(backend-index)

概述

目的:把「后端模块」的位置、边界、依赖与被依赖、数据面,从"每次 grep 试探 + 逐条读文件收敛"变成"查表直达"。改某模块前知道要连带看谁;改某张表前知道要通知哪些模块;接后端任务先拿到模块地图。

功能:

  • 扫描本地后端源码,提取模块(NestJS @Module / Django app):目录、定义处、挂载前缀、接口数、controller 文件
  • 双向依赖:模块 → 依赖(imports 的兄弟模块)+ 模块 → 被依赖(穷举反查,防漏)
  • 表双向:模块 → 数据表(forFeature / @InjectRepository / models.Model / 跨 app import)+ 表 → 模块(反向,改表找谁)
  • 非 HTTP 入口:MQ 消费者(@Processor)、CQRS Handler、定时任务;模块级守卫
  • 事件/命令耦合边:bus.execute(new X) → @CommandHandler(X) 所在模块、@InjectQueue('q') → @Processor('q') 所在模块——这类耦合不经 imports(靠 CQRS 总线 / 队列解耦),但"改一个 Command 或消息结构"照样影响对方。只统计模块自有文件,每条边都可用 grep 模块目录 复验
  • 专家资产探测:.module-experts/ 里有哪些专家包、各自关联哪个模块(索引成为专家团的入口)
  • 一键重建:--emit-tree 一条命令落盘整棵树;新鲜度闸门 --check 比对 commit
  • 诚实降级:展不开的常量数组、找不到 @Entity 的 token、默认命名的表名 → 全部进「待确认」,不猜

使用场景:

  • 要改 / 删某张数据表 → 先查哪些模块引用了它(防漏通知、防漏回归)
  • 要改某个模块的配置 / 依赖 / 对外面 → 先看它依赖谁、谁依赖它
  • 新会话接手后端项目 → 一份模块地图建立认知(含"哪些模块有专家资产可深挖")
  • 用户说"给后端建索引"、"后端模块地图"、"改这个模块影响谁"、"改这张表影响哪些模块"时
  • 之前建过索引的项目再次被问起——先查 .fe-index/INDEX.md 进消费模式,而不是重跑扫描

定位

与邻接 skill 的分工(防重叠)

邻接能力 它做什么 本 skill 做什么
expert-team(.module-experts/) 按模块深挖:契约层(怎么用 / 接口契约 / 数据流向 C4 / 关键决策)+ 实现层 Wiki 只给位置与依赖骨架,并指向专家资产。接口清单与契约一律不重复建设(专家 Step 8.3 已写 ki tags=api)
ki-search 接口信息 可检索的接口原子(按子功能聚合) 索引给"哪个模块",ki 给"接口怎么用"
strong-relation 人工/AI 沉淀的模块间强耦合关系 机械提取的模块依赖边(覆盖全量、零维护);两者互补,冲突时以代码为准
frontend-index 前端「页面 ↔ 接口」索引(.fe-index/{前端slug}/) 后端「模块 ↔ 表 / 依赖」索引(.fe-index/{后端slug}/);跨端 join 见「被其它 skill 集成」
GitNexus MCP(impact / context) 符号级影响面(需 CLI + 已建索引) 模块级视角、零依赖、产物人可读、不依赖 MCP 可用性
grep / LSP 随机访问(搜到什么算什么) 穷举反查 + 落盘复用(被依赖 / 表反查 / 跨会话一致)

一句话边界:本 skill 回答「去哪看、动了谁」;专家团回答「是什么、怎么用」;grep 回答「具体在哪一行」。

与 frontend-index 的关系(同族)

两个 skill 实现独立、产物同根(.fe-index/),口径一致:双模式 / 新鲜度闸门 / 退出码族 / [待确认] 不猜 / 脚本提取骨架 + AI 补语义。可以各自单独安装使用。


核心原则

  1. 索引模块,不是索引接口:接口清单交给专家团与 ki(tags=api)——重复建设必然漂移。本索引只在模块卡里记「挂载前缀 + 接口数 + controller 文件」,不逐接口建表。
  2. 脚本管骨架,AI 管语义:穷举机械活(模块全集 / 前缀合成 / 依赖反查 / 表反查 / 一键重建)交给脚本;语义判断(模块中文职责、专家关联确认、分组)交给 AI。不让 AI 重复做穷举提取(会漏,且每次重建都贵)。
  3. 反查必须穷举:被依赖 与 表 → 模块 是"扫完全部才知道"的反查——漏一条边就是一份看起来完整但会误导的报告。这类活只能机械提取。
  4. 失效要显式:meta.json 记 commit,读表前 --check;范围外无变化不误报。
  5. 不猜:展不开的数组、找不到声明的 token、默认命名的表 → 进「待确认」,宁可缺,不给错。
  6. 双模式分离:消费模式(查表 → 读码,不跑脚本)与建造模式(采集建库)严格分开。
  7. 可见性由集成方负责:.fe-index/ 是隐藏目录,本 skill 不擅自往用户的 AGENTS.md / 规则里写钩子。

产物结构

落点一律在【项目根】(git rev-parse --show-toplevel;非 git 仓库则逐级向上找 .git):即 {项目根}/.fe-index/。 monorepo 里 --root 可以给应用子目录,但索引属于整个项目——--emit-tree 不带值就落这里,带相对路径也以项目根为基准(不看 cwd)。

{项目根}/.fe-index/
├── INDEX.md                      # 必存在:全项目登记表(一行一应用)—— 后续会话的发现入口
└── {app-slug}/
    ├── index.md                  # 必存在:模块地图 + 依赖图 + 表反查摘要 + 专家资产 + 待确认
    ├── modules/{模块slug}.md     # 每模块一张卡(占位/依赖/表/事件耦合/入口/守卫/专家指针/归属文件)
    ├── tables.md                 # 必存在:表 → 模块(反向索引)
    └── meta.json                 # 必存在:机器可读元信息(commit / 范围 / 统计)—— `--check` 依据
类别 文件 git 建议
人工维护(发现入口) INDEX.md 入库(一行一应用,冲突少)
派生产物(脚本生成) meta.json / index.md / modules/ / tables.md 默认不入库(会随代码过期)

INDEX.md 是这个机制的生命线:隐藏目录不会被自动发现,每次建造都必须同步更新它。

INDEX.md 模板(与 frontend-index 共用同一份文件,列结构必须一致)

# 索引登记表(.fe-index/)

> 涉及下列应用的问题,先查对应条目所在的分区/映射表,再看代码

| 应用 | 类型 | slug | 根目录 | 规模 | commit | 生成日期 |
|------|------|------|--------|------|--------|----------|
| cloud-web | frontend | cloud-web | `/root/xpert` | 页面 121 · 接口 66 | `889e265c` | 2026-10-13 |
| server-ai | backend | server-ai | `/root/xpert` | 模块 125 · 表 122 | `889e265c` | 2026-10-13 |

更新纪律:只增改本应用那一行,不动其他行;同一仓库前后端各占一行(slug 不同,不合并)。 「根目录」列口径(消费方按此解析):绝对路径直用;相对路径以 .fe-index/ 的上一级为基准(便于跨机器与仓库整体搬迁)。查找登记表时若 {root} 下没有,逐级向上找 ≤3 层。

meta.json 模板(--check 依赖,必写)

{
  "slug": "server-ai",
  "kind": "backend",
  "root": "/root/xpert",
  "scope": ["packages/**", "apps/**"],
  "framework": "nestjs",
  "commit": "889e265cdfdec200e5a6446f4463fe43505f84ac",
  "generated": "2026-10-13",
  "stats": { "modules": 125, "tables": 122, "deps_edges": 428, "routes": 806 },
  "scanner": "scan_backend.py v2.0.0"
}

--emit-tree 会自动写 meta.json(含 commit),无需手写;手工建库时(见阶段 2 的小项目分支)必须自己填。

index.md 模板

# {slug} 后端模块索引

> 根目录:`…` · 框架:**nestjs** · 全局前缀:`/api`
> 生成:2026-10-13 · commit:`889e265cdf` · 范围:`packages/**, apps/**`
> 新鲜度校验:`python3 scan_backend.py --root <根> --check --index <本目录>`

**这个索引回答什么**:改某模块要连带看谁、改某张表要通知哪些模块、模块的数据面与非 HTTP 入口、模块的代码在哪。
**接口级契约**见 `.module-experts/` 专家资产与 ki 接口信息(`tags=api`)——本索引不重复建设。

## 1. 模块地图(N)
| 模块 | 目录 | 挂载前缀 | 接口 | 表 | 依赖 | 被依赖 | 非 HTTP 入口 | 专家资产 |
…(每模块一行,链接到 modules/{slug}.md)

## 2. 模块依赖图(M 条边)        ← mermaid graph LR(边 >120 时降级为文本列表)
## 3. 表 → 模块(反向,K 张表)    ← 摘要,完整见 tables.md
## 4. 专家资产(N 个)             ← 专家名 / 路径 / 关联模块(未关联显式标注)
## 5. 待确认(N)                  ← 类型 / 位置 / 内容 / 原因

modules/{模块slug}.md 模板

# {模块名}(`{slug}`)
- 位置:`{目录}/` · 归属文件 N 个 · 约 M 行
- 定义:`{module.ts}:{line}`(nestjs) | 挂载前缀:`/api/x` · 接口 N 个 | 置信度:🟢
## 控制器(模块对外面)   ← 文件 / 前缀 / 接口数 / 行号
## 依赖关系              ← 依赖(改它要连带看)/ 被依赖(动它会影响)/ 依赖的库
## 事件/命令耦合          ← 我发出(→ 目标模块 + 命令/队列名)/ 我接收(← 来源模块 + 命令名)
## 数据表(N)           ← 表 / 实体 / 引用次数 / 来源(定义 or import)/ 证据 file:line
## 非 HTTP 入口          ← MQ / CQRS / 定时任务
## 守卫/权限
## 专家资产(深挖读这些)
## 归属文件(N)

工作流

第一步先判模式(必做):读 .fe-index/INDEX.md(不存在则视为首次建库;被集成时落点以调用方指定为准)。

消费模式(查表 → 读码)

  1. 读 .fe-index/INDEX.md → 找到对应应用与 slug
  2. 新鲜度闸门(必做):
    python3 <skill>/scripts/scan_backend.py --root <根> --check --index .fe-index/{slug}
    
    • 退出码 0:新鲜 → 继续
    • 退出码 6:过期 → 先问用户是否重建(重建 = 重跑 --emit-tree,秒级)
    • 退出码 7:缺 meta.json → 按"无新鲜度信息"处理,告知用户
    • 退出码 3:git 不可用 / 记录的 commit 不可达 → 按"无法判定"处理,建议重建
  3. 按问题查表:
    • "改这张表要注意什么" → tables.md 找到表 → 拿到模块清单(定义方 vs 使用方)→ 读对应 modules/*.md
    • "改这个模块影响谁" → modules/{slug}.md 的被依赖 → 逐个看
    • "改一个 Command / 队列消息影响谁" → modules/{slug}.md 的事件/命令耦合段(我发出 → 目标模块;我接收 ← 来源模块)
    • "这个接口/功能在哪" → index.md 模块地图按前缀定位模块 → 进模块目录看 controller
    • "这个模块怎么用 / 契约是什么" → 交给专家资产(模块卡里有指针);没有专家则 ki tags=api 或现场读码
  4. 命中即止:不再全库 grep;只有模块定位后需要行级细节时才在模块目录内查

建造模式总览

阶段 0 准入与模式判定 → 阶段 1 约定探测(含"值不值得建/要不要跑脚本")→ 阶段 2 提取(脚本 --emit-tree)
   → 阶段 3 语义补充(AI,可选但推荐)→ 阶段 4 登记(INDEX.md)→ 阶段 5 交付与使用协议

阶段 0:准入判断(AI 自主)

信号 处置
目标应用已在 INDEX.md 在册 ➡️ 转消费模式(用户要求重建除外)
后端模块 ≤10 个且只要"模块在哪",不需要"谁依赖我 / 改表影响谁" ➡️ 小项目分支:AI 直接读代码建索引,不跑脚本(仍需写 meta.json 与 INDEX.md;不承诺 --check)
需要反向穷举(被依赖 / 表 → 模块)或模块数 >10 或要跨会话复用 ✅ 进建造模式(跑脚本)
代码不在本地 / 无源码 ❌ 退出(本 skill 只索引本地代码)

阶段 1:约定探测(唯一的用户确认点)

python3 <skill>/scripts/scan_backend.py --root <根> --dump-config

输出:框架(nestjs / django)、全局前缀、src_dirs、模块声明数、建议 include。

  • 有 {项目根}/.fe-index/config.json(集成方或此前建库留下)→ 脚本自动读取并应用(--config 可指定路径;只认 kind=backend,--app/--slug 选应用)→ 重建零猜测;文件里只有他端条目(如只声明了前端)时说明一行后忽略,不拦路
  • 与用户确认:扫描范围(哪个应用、哪些包、slug 名)
  • 框架识别失败(退出码 2)→ 用 --framework 显式指定,或收窄 --include
  • 探测结果建议固化为声明文件(--dump-config 会给出 suggested_config):与前端共用同一份 config.json,各自按 kind 取用自己的条目

阶段 2:脚本提取

python3 <skill>/scripts/scan_backend.py --root <根> --framework nestjs \
  --include 'packages/**' --include 'apps/**' --slug server-ai \
  --emit-tree

--emit-tree 不带值 → 自动落 {项目根}/.fe-index/server-ai/(推荐用法)。要自定义位置时才给它一个值(绝对路径直用;相对路径以项目根为基准)。 一步完成:模块全集 / 前缀 / 依赖图(含被依赖)/ 表双向 / 非 HTTP 入口 / 专家探测 / 待确认 / meta.json。

退出码处置:

码 含义 处置
0 成功 继续
2 未识别框架 --framework 显式指定 / 收窄 --include
3 根目录不存在或 git 失败 修正参数
4 识别到框架但零模块 检查 --include 是否覆盖后端源码
5 入参非法 修正参数
6 --check 判定过期(范围文件有变化) 先问用户是否重建(--emit-tree 覆盖落盘)
7 --check 缺 meta.json 或无 commit 按"无新鲜度信息"处理,建议重建

成本:实测 3183 个 TS 文件 0.5 秒(NestJS)/ 5530 个 PY 文件 1.3 秒(Django)。重建近乎零成本——这是"索引不会腐烂"的前提。

阶段 3:语义补充(AI,可选但推荐)

脚本出的是机械骨架;下面这些 AI 直接读代码补,更准:

  1. 模块中文职责:给核心模块补一句话(写进模块卡顶部)。只补"改代码前需要知道的",不写百科。
  2. 专家关联确认:脚本按名字机械匹配,可能漏(专家用中文业务名)。逐个核对 未关联 的专家,人工指到模块卡里。
  3. 待确认处理:读 index.md 第 5 节,对影响判断的项(如展不开的数组、缺 @Entity 的关键 token)回源码确认,确认结果写进模块卡或 meta.json 的 notes。
  4. 分组(可选):模块 >40 个时,按业务域在 index.md 里给模块地图加分组小标题(不改 modules/ 目录结构)。

成本闸门:阶段 3 读文件 ≤15 个(骨架已由脚本给出,只读"需要判断"的)。

阶段 4:登记(INDEX.md)

  • 脚本没写 INDEX.md(它是跨应用登记表):新增或更新该应用那一行(应用 / 类型 backend / 根目录 / 范围 / 规模 / commit / 日期)
  • 若同项目已有前端索引:保持两个 slug 各自一行,不要合并

阶段 5:交付

  1. 一句话总结:模块数、表数、依赖边数、待确认数、专家资产覆盖情况
  2. 给出使用协议(消费模式三问:改表去哪查 / 改模块去哪查 / 接口契约去哪查)
  3. 可选提醒:在 AGENTS.md 里加一句"改后端模块或数据表前,先查 .fe-index/INDEX.md"(加不加由用户决定,本 skill 不代劳)

反模式

  • ❌ 把接口清单再抄一遍:专家团/ki 已有(tags=api)——重复建设必然漂移,且接口级数据天然过期快
  • ❌ 让 AI 全量手工建库:模块数 >10 或需要反查时会漏边,且每次重建成本高到不会重建 → 索引腐烂
  • ❌ 不写 meta.json 就交付:没有 commit 就无法判断新鲜度,索引会静默过期
  • ❌ 跳过 --check 直接信表:代码映射失效是静默的(表还能查,结果是错的)
  • ❌ 在建造模式里逐模块读代码(脚本已给骨架):除非属于阶段 3 的"需要判断"清单
  • ❌ 把「未关联」的专家当无关:专家名多为中文业务名,与代码标识无字面重叠 → 需人工指认
  • ❌ 拿默认命名的表名当真:Django/TypeORM 默认命名在「待确认」里,向用户确认后才写入结论

行为边界(明确不承诺)

  • ❌ 运行时行为:动态模块(forRootAsync 里拼出来的)、反射注册的 provider、@Controller 路径运行时改写
  • ❌ 跨服务:RPC / 微服务另一端的模块(只到本仓声明)
  • ❌ 接口级清单与契约(归专家团 / ki)、精确到 file:line 的调用链(归 GitNexus / LSP / grep)
  • ❌ 非 NestJS / Django 框架的模块体系(可扩展,见 reference.md 的规则表)
  • ⚠️ monorepo 需 --include 限定应用范围;前后端同仓时前端文件会被自动排除(同名类污染,已实测)
  • ⚠️ 表名若为框架默认命名(Django {app}_{模型} / TypeORM 类名推断)→ 标 🟡 进「待确认」
  • ⚠️ 依赖边分两类:imports 声明(模块间依赖)与事件/命令耦合(bus.execute(new X) / @InjectQueue 配对,只取模块自有文件)。仍不入图:字符串主题的事件(emit('x'))、跨进程 MQ 主题约定、共享配置 / 环境变量——需要时按 reference.md 的抽样核对方法局部 grep 补齐
  • ⚠️ 同仓多框架(NestJS + Django 并存)时 --framework 一次只扫一侧:脚本会显式告警,另一侧需单独建一个 slug

被其它 skill 集成(调用契约 · SSOT)

规则只在本节维护,调用方引用本 skill,不复制规则。

集成方 建议用法 状态
index-lookup(统一查询入口) 消费方(code-review / debug / product-manager / expert-team / code-survey …)先调它按代码路径判定该查前端还是后端索引(读同一张 .fe-index/INDEX.md),再按本 skill 的查询口径查表 推荐接入:不要让每个消费方自己实现"选哪端",否则口径必然漂移
跨端 join(与 frontend-index 组合) 先读后端 index.md 的「模块 → 挂载前缀」,再用前端 apis/{分区}.md 里的接口路径匹配前缀 → 答"后端改接口 → 前端哪些页面在用" 可直接用(两端产物同根、口径已对齐;@Controller() 无前缀的模块用「方法路径」提示匹配)
expert-team 建完专家包后重跑 --emit-tree,专家列会因目录存在而出现 → 索引成为专家团的发现入口(解决"建了没人知道") 可直接用(产物级衔接,无需改对方)
module-teach 讲解某后端模块前读 modules/{slug}.md 定位范围与依赖 已接入(「与相邻 skill 的分工与路由」表,module 类讲解先用索引锁定范围)
code-survey / 设计前调研 查 INDEX.md 命中则消费,未命中再决定是否建库 已接入(「ki-search 与资产复用优先」链,缩小搜索域)
bug-impact-analysis / code-review / debug 改到后端模块或数据表时,用被依赖与表反查确认影响面 已接入(bug-impact-analysis 3.0 / code-review 阶段 2 / debug Step 0)

上表不声明"已接入":本 skill 的产物需要目标项目先建一次索引,集成方需自行降级(无索引时按原流程 grep)。

全局前缀匹配口径(跨端 join 的关键,写清防歧义):挂载前缀 = "/" + global_prefix + controller前缀;@Controller() 无路径时,用方法路径首段(模块卡/表格里显示为"方法路径 x、y")与前端接口路径做包含匹配。


更多资源

  • reference.md:为什么是模块级(设计依据与专家团证据)· 框架提取规则明细 · 脚本参数与退出码全表 · 证据分级与 [待确认] 规则 · 两靶子实测数据与已知坑 · 抽样核对方法