fix(codebase): point builtin wiki skill at teamai extract

Phase 0 of team-wiki-codebase instructed agents to run a standalone
team-wiki CLI that is not shipped with teamai. Use the existing
`teamai codebase --extract` path, unhide it in --help, drop the dead
GRAPH-CAPABILITIES.md link, and skip later team-wiki-only steps with
an English note that no extra plugin is required.

Related: #360
This commit is contained in:
jimpablo
2026-09-08 22:47:46 +08:00
parent 24260bd5f7
commit e151d434c4
10 changed files with 166 additions and 29 deletions
+2
View File
@@ -226,6 +226,7 @@ Matched: conflict | Missing: port
```bash
teamai import --from-repo https://github.com/org/repo
teamai import --from-org myorg # batch import all repos
teamai codebase --extract /path/to/repo # local extract into teamwiki/
teamai codebase --lint # health check
```
@@ -267,6 +268,7 @@ Insight into how the team actually uses its AI tools, and a starting point for t
| `teamai recall promote [learningId]` | Promote a high-confidence learning to formal knowledge (skills/rules/docs) |
| `teamai recall maintenance` | Maintain knowledge base health: prune low-confidence learnings, writeback confidence scores, flag stale entries |
| `teamai import` | Import knowledge (`--dir`, `--from-repo`, `--from-org`, `--from-repo-list`, `--from-mr`) |
| `teamai codebase --extract [path]` | Extract code facts and build the local graph under `teamwiki/` |
| `teamai codebase --lint` | Knowledge graph health check |
| `teamai ci extract-mr --url <url>` | CI: extract knowledge from MR, post comments, write after merge |
| `teamai members` | List team members |
+2
View File
@@ -226,6 +226,7 @@ Matched: conflict | Missing: port
```bash
teamai import --from-repo https://github.com/org/repo
teamai import --from-org myorg # 批量导入所有仓库
teamai codebase --extract /path/to/repo # 本地提取到 teamwiki/
teamai codebase --lint # 健康检查
```
@@ -267,6 +268,7 @@ WASM 解析器是纯 JavaScript 依赖,无需任何原生编译工具链。若
| `teamai recall promote [learningId]` | 将高置信度 learning 晋升为正式知识(skills/rules/docs) |
| `teamai recall maintenance` | 维护知识库健康:清理低置信度 learnings、回写置信度、标记过时条目 |
| `teamai import` | 导入知识(`--dir`、`--from-repo`、`--from-org`、`--from-repo-list`、`--from-mr`) |
| `teamai codebase --extract [path]` | 提取代码事实并在 `teamwiki/` 下构建本地图谱 |
| `teamai codebase --lint` | 知识图谱健康检查 |
| `teamai ci extract-mr --url <url>` | CI:从 MR 提取知识、发评论、合并后写入 |
| `teamai members` | 查看团队成员 |
+3
View File
@@ -1071,6 +1071,9 @@ The graph stores components, interfaces, configs, and cross-repo dependencies. `
Dependency edges are extracted by two parallel tracks: a WASM tree-sitter **AST track** (TypeScript/JavaScript, Python, Go) that resolves imports, calls, and TS `implements` clauses to precise file-to-file edges (`code-ast`), and a regex **heuristic track** (all languages, `code-heuristic`) that also covers languages the AST track does not. AST results win on overlap. The AST parser needs no native toolchain; on load failure, extraction falls back to heuristics and records an `AST_UNAVAILABLE` gap. Set `TEAMAI_SKIP_AST=1` to force heuristic-only extraction.
```bash
# Extract code facts and the graph from a local repo (writes <repo>/teamwiki/)
teamai codebase --extract /path/to/repo --project my-service
# Graph health check
teamai codebase --lint
```
+3
View File
@@ -1059,6 +1059,9 @@ teamai import --from-repo https://github.com/org/repo --skip-enrich
依赖边由两条并行轨道提取:WASM tree-sitter **AST 轨**(TypeScript/JavaScript、Python、Go),将 import、调用、以及 TS `implements` 子句解析为精确的文件到文件边(`code-ast`);以及正则 **启发式轨**(所有语言,`code-heuristic`),同时覆盖 AST 轨未支持的语言。重叠时 AST 结果优先。AST 解析器无需原生编译工具链;加载失败时提取会降级到启发式并记录一条 `AST_UNAVAILABLE` gap。设置 `TEAMAI_SKIP_AST=1` 可强制仅用启发式提取。
```bash
# 从本地仓库提取代码事实与图谱(写入 <repo>/teamwiki/)
teamai codebase --extract /path/to/repo --project my-service
# 图谱健康检查
teamai codebase --lint
```
+3 -3
View File
@@ -1,6 +1,6 @@
# team-wiki-codebase — 大型代码库 AI 认知工程
> Team Wiki 插件内置 skill:方法论、脚本与 Agent 规范均随 `team-wiki install` / `upgrade` 部署到项目的 `.codebuddy/`、`.cursor/` 等目录。
> TeamAI builtin skill:方法论、脚本与 Agent 规范随 `teamai pull` / `teamai init` 部署到项目的 `.codebuddy/`、`.cursor/` 等目录。TeamAI does not ship a separate team-wiki CLI. No extra plugin is required.
## 为什么需要这个 skill
@@ -22,7 +22,7 @@
- 每条组件关系有置信度标注(`EXTRACTED` / `INFERRED` / `AMBIGUOUS`)
- 每次生成后有准确性统计,超标自动警告
- AI 读知识库而非读源码,**约 1/50 的 token 消耗**获得全局架构认知
- Phase 0 可用 `team-wiki compile code --extract ast,heuristic` 生成可证据化的结构边(TS/JS/Python/Go)
- Phase 0 可用 `teamai codebase --extract` 生成可证据化的结构边(TS/JS/Python/Go AST + 多语言 heuristic)
---
@@ -39,7 +39,7 @@
├── XX_{项目名}产品规则速查表.md
├── XX_{项目名}业务开发规范SOP.md
├── {反模式/RPC契约/排障记录} × N
├── _manifest.json ← 机器可读 manifest(供 team-wiki compile 快路径)
├── _manifest.json ← 机器可读 manifest(供后续图谱合并)
└── graph/ ← Graph RAG 图谱文档集
├── G1 组件依赖关系矩阵
├── G2 调用链路全景 + 状态机
+18 -23
View File
@@ -6,7 +6,7 @@ description: |
适用场景:项目有 10+ 仓库或微服务,AI 直接读代码无法全局理解、回答不准确、token 开销大。
产出:组件设计文档 × N + 架构总览 + 桥梁文档 + Graph RAG 图谱(G1~G9) + _manifest.json + team-wiki 编译产物。
产出:组件设计文档 × N + 架构总览 + 桥梁文档 + Graph RAG 图谱(G1~G9) + _manifest.json + teamai extract graph (teamwiki/)。
Trigger: team-wiki-codebase, code-to-knowledge, 代码知识库, 架构分析, 架构逆向
Prerequisites: 可访问的源码目录(支持多仓库);本 skill 目录下 `references/` 与 `scripts/`
@@ -14,8 +14,8 @@ description: |
# team-wiki-codebase — 大型代码库 AI 认知工程
> 方法论与脚本位于本 skill 的 `references/`、`scripts/`(`team-wiki upgrade` 后出现在 `.cursor/skills/team-wiki-codebase/` 或 `.codebuddy/skills/team-wiki-codebase/`)。人类可读概览见 [README.md](./README.md)。
> 图谱 CLI 能力见 [GRAPH-CAPABILITIES.md](../GRAPH-CAPABILITIES.md)。
> 方法论与脚本位于本 skill 的 `references/`、`scripts/`(`teamai pull` 后出现在 `.cursor/skills/team-wiki-codebase/` 或 `.codebuddy/skills/team-wiki-codebase/`)。人类可读概览见 [README.md](./README.md)。
> Phase 0 结构基线使用 `teamai codebase --extract`。TeamAI does not ship a separate team-wiki CLI. No extra plugin is required.
**解决什么问题**:大型项目(10+ 仓库、数十微服务、迭代多年)让 AI 无法全局理解——上下文窗口装不下所有代码,组件关系散落各处,业务规则隐藏在深层调用链中。直接让 AI 读代码,既慢(海量 token)又不准(缺乏全局视角)。
@@ -300,22 +300,17 @@ FOR repo in repos:
**Step 0D:CLI 结构基线(每个代码仓库,推荐)**
在 K1 深读之前,用 Team Wiki CLI 生成可证据化的 import/call 结构边(Python/Go/TS 等,`code-ast`)并与 regex 基线合并(`code-heuristic`):
在 K1 深读之前,用 TeamAI 提取可证据化的 import/call 结构边(Python/Go/TS 等,`code-ast`)并与 regex 基线合并(`code-heuristic`):
```bash
# 对每个 repo(<wiki_root> 通常为项目下的 .teamwiki 或 .wiki)
team-wiki compile code <repo_abs_path> <wiki_root> \
--project <project_slug> \
--extract ast,heuristic \
--write
# 预览 AST 统计(不写盘)
team-wiki compile code <repo> <wiki> --extract ast --dry-run
# For each repo. Writes <repo>/teamwiki/ (evidence pages + .indices/graph-index.json).
# Existing flags only: --extract [path], optional --project <slug>, optional --incremental.
teamai codebase --extract <repo_abs_path> --project <project_slug>
```
- 输出:`code/<project>/` 下 index/component/relation 等页;`graph/<project>-graph-index.json`(结构边草案)。
- K1/K2/K3 写 `_manifest.json` 的 `edges[]` 时:**优先引用** compile 的 `code-ast` 边 + `evidenceRefs`(`path:line`),Agent 推断标 `INFERRED`/`AMBIGUOUS`。
- K3 完成后写入 wiki 图:`team-wiki compile code <output_dir> <wiki_root> --extract ast,heuristic --write`(有 `_manifest.json` 时走 manifest 快路径 merge `graph-index.json`)。
- Output: `teamwiki/evidence/code/<project>/` pages; `teamwiki/.indices/graph-index.json` (structural edges).
- K1/K2/K3 写 `_manifest.json` 的 `edges[]` 时:**优先引用** extract 的 `code-ast` 边 + `evidenceRefs`(`path:line`),Agent 推断标 `INFERRED`/`AMBIGUOUS`。
- After Phase K3, skip any extra graph compile / merge step that is not a `teamai` command. TeamAI does not ship a separate team-wiki CLI. Continue with this skill using `teamai` and the files under this skill directory. No extra plugin is required.
写入初始 progress.json(current_phase: "phase0_done"),进入 **Phase K1**。
@@ -889,16 +884,16 @@ _review/ ← 过程文件(不入知识库)
---
## 与 Team Wiki CLI 的配合(必读)
## 与 TeamAI CLI 的配合(必读)
| 阶段 | 命令 / 路径 |
|------|-------------|
| Phase 0 结构基线 | `team-wiki compile code <repo> <wiki> --extract ast,heuristic --write` |
| K3 后编译进 wiki | `team-wiki compile code <knowledge_output> <wiki> --write`(检测 `_manifest.json` → manifest 快路径) |
| 产品文档入图 | `team-wiki compile docs <docs> <wiki> --extract structure,entity --write` |
| 产品↔代码桥接 | `team-wiki reconcile <wiki> --write` |
| 一键刷新 | `team-wiki refresh <wiki> --repo <repo> [--docs <docs>] --extract-code ast,heuristic --write` |
| 质量评估 | `team-wiki evaluate <wiki>`(含 `graph.structuralEdgeRatio` 等) |
| Phase 0 结构基线 | `teamai codebase --extract <repo> --project <slug>`(writes `<repo>/teamwiki/`) |
| K3 后编译进 wiki | Skip. TeamAI does not ship a separate team-wiki CLI. Continue with this skill using `teamai` and the files under this skill directory. No extra plugin is required. |
| 产品文档入图 | Skip. Same English note as above. |
| 产品↔代码桥接 | Skip. Same English note as above. |
| 一键刷新 | Use `teamai codebase --extract --incremental` when updating a repo already extracted. Do not look for another CLI. |
| 质量评估 | Use `scripts/validate_kb.py` and `teamai codebase --lint` on `teamwiki/`. Skip any extra evaluate binary. |
**路径约定**(本 skill 安装后):
@@ -906,4 +901,4 @@ _review/ ← 过程文件(不入知识库)
- Agent:`references/agents/kb-doc-generator.md`、`references/agents/graph-rag-agent.md`
- 脚本:`scripts/scan_repo.py`、`scripts/validate_kb.py`
所有流程在本 skill(`references/`、`scripts/`)与 `team-wiki` CLI 内完成。
所有流程在本 skill(`references/`、`scripts/`)与 `teamai` CLI 内完成。No extra plugin is required.
@@ -31,7 +31,7 @@
**边类型**: `[CALLS]`(同步RPC/HTTP) / `[PUBLISHES]`(异步MQ) / `[CONSUMES]`(MQ消费) / `[READS]`(DB读) / `[WRITES]`(DB写) / `[CONFIGURES]`(配置驱动) / `[MAPS_TO]`(产品→代码)
**构建方法**(按可用性排序):
1. **`team-wiki compile code --extract ast,heuristic --write`** — Tree-sitter 结构边(**TS/JS/Python/Go** 等)+ 多语言 heuristic 事实页
1. **`teamai codebase --extract`** — Tree-sitter 结构边(**TS/JS/Python/Go** 等)+ 多语言 heuristic 事实页(writes `teamwiki/`)
2. Grep + Read(Agent K1/K2)— 补充动态路由、配置驱动调用
3. 解析编排配置 → 模块→命令映射
4. 解析 Proto/IDL/DDL → 数据结构和表关系(结构化文件,可精确解析)
@@ -39,7 +39,7 @@
6. API 映射 → 外部 API 名称 → 内部 Handler 入口
> `code-ast` 对相对 import 可产出 `DEPENDS_ON` 边;包级/动态调用仍可能遗漏,标 `[UNVERIFIED]` 或 `AMBIGUOUS`。
> 能力 ID 与边优先级见插件内 `GRAPH-CAPABILITIES.md`。
> AST 结果优先于 heuristic。There is no separate capabilities doc in this package; use `teamai codebase --extract` output under `teamwiki/`.
## 输入源优先级
@@ -0,0 +1,80 @@
import { describe, it, expect, beforeAll } from 'vitest';
import { spawn } from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
const CLI = path.join(ROOT, 'dist', 'index.js');
interface RunResult {
code: number | null;
stdout: string;
stderr: string;
output: string;
}
function runCLI(args: string[], cwd: string = ROOT): Promise<RunResult> {
return new Promise((resolve) => {
const child = spawn('node', [CLI, ...args], {
env: { ...process.env, FORCE_COLOR: '0' },
stdio: ['pipe', 'pipe', 'pipe'],
cwd,
});
let stdout = '';
let stderr = '';
child.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });
child.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });
child.stdin.end();
child.on('close', (code) => {
resolve({ code, stdout, stderr, output: stdout + stderr });
});
});
}
describe('teamai codebase extract CLI (issue #360 slice 1)', () => {
beforeAll(() => {
if (!fs.existsSync(CLI)) {
throw new Error(`CLI binary not found at ${CLI}. Run "npm run build" first.`);
}
});
it('lists --extract on teamai codebase --help', async () => {
const result = await runCLI(['codebase', '--help']);
expect(result.code).toBe(0);
expect(result.stdout).toContain('--extract');
});
it('extracts a tiny local repo into teamwiki graph output', async () => {
const fixture = fs.mkdtempSync(path.join(os.tmpdir(), 'teamai-extract-360-'));
try {
const srcDir = path.join(fixture, 'src');
fs.mkdirSync(srcDir);
fs.writeFileSync(
path.join(srcDir, 'greet.ts'),
'export function greet(name: string): string {\n return `hello ${name}`;\n}\n',
);
const result = await runCLI(
['codebase', '--extract', fixture, '--project', 'slice360', '--json', '--max-files', '10'],
fixture,
);
expect(result.code, result.output).toBe(0);
const graphPath = path.join(fixture, 'teamwiki', '.indices', 'graph-index.json');
expect(fs.existsSync(graphPath), result.output).toBe(true);
const graph = JSON.parse(fs.readFileSync(graphPath, 'utf8')) as {
nodes?: unknown[];
edges?: unknown[];
};
const artifactCount = (graph.nodes?.length ?? 0) + (graph.edges?.length ?? 0);
expect(artifactCount).toBeGreaterThan(0);
const evidenceDir = path.join(fixture, 'teamwiki', 'evidence', 'code', 'slice360');
expect(fs.existsSync(evidenceDir)).toBe(true);
} finally {
fs.rmSync(fixture, { recursive: true, force: true });
}
});
});
@@ -0,0 +1,52 @@
import { describe, it, expect } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
const SKILL_DIR = path.join(ROOT, 'skills', 'team-wiki-codebase');
const SKILL_FILES = [
path.join(SKILL_DIR, 'SKILL.md'),
path.join(SKILL_DIR, 'README.md'),
path.join(SKILL_DIR, 'references', 'methodology', 'phase0-collection.md'),
] as const;
const FORBIDDEN_REQUIRED_COMMANDS = [
'team-wiki compile code',
'team-wiki reconcile',
'team-wiki evaluate',
'team-wiki compile docs',
'team-wiki refresh',
] as const;
describe('team-wiki-codebase builtin skill (issue #360 slice 1)', () => {
it('ships the packaged skill files', () => {
for (const file of SKILL_FILES) {
expect(fs.existsSync(file), file).toBe(true);
}
});
it('tells Phase 0 to run teamai codebase --extract', () => {
for (const file of SKILL_FILES) {
const text = fs.readFileSync(file, 'utf8');
expect(text, file).toContain('teamai codebase --extract');
}
});
it('does not point at GRAPH-CAPABILITIES.md', () => {
for (const file of SKILL_FILES) {
const text = fs.readFileSync(file, 'utf8');
expect(text, file).not.toContain('GRAPH-CAPABILITIES.md');
}
});
it('does not require standalone team-wiki CLI commands', () => {
for (const file of SKILL_FILES) {
const text = fs.readFileSync(file, 'utf8');
for (const cmd of FORBIDDEN_REQUIRED_COMMANDS) {
expect(text, `${file} must not require ${cmd}`).not.toContain(cmd);
}
}
});
});
+1 -1
View File
@@ -873,7 +873,7 @@ program
program
.command('codebase')
.description('Inspect and maintain team-codebase outputs')
.addOption(new Option('--extract [path]', 'Extract code knowledge and build graph from source').hideHelp())
.option('--extract [path]', 'Extract code knowledge and build graph from source')
.addOption(new Option('--incremental', 'Only re-extract changed files (requires prior manifest)').hideHelp())
.addOption(new Option('--project <name>', 'Project slug for extract output (default: directory name)').hideHelp())
.addOption(new Option('--max-files <n>', 'Max source files to scan (default: 200)').hideHelp())