fix(codebase): preserve local wiki refresh and lint targets

This commit is contained in:
jeffyxu
2026-09-09 11:13:22 +08:00
parent 6052e1620d
commit 1ca43acc1f
6 changed files with 57 additions and 8 deletions
+1 -1
View File
@@ -227,7 +227,7 @@ Matched: conflict | Missing: port
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
teamai codebase --lint --output /path/to/repo # check the locally extracted graph
```
The graph stores components, interfaces, configs, and cross-repo import edges. `teamai recall` uses it for graph-boosted re-ranking.
+1 -1
View File
@@ -227,7 +227,7 @@ Matched: conflict | Missing: port
teamai import --from-repo https://github.com/org/repo
teamai import --from-org myorg # 批量导入所有仓库
teamai codebase --extract /path/to/repo # 本地提取到 teamwiki/
teamai codebase --lint # 健康检查
teamai codebase --lint --output /path/to/repo # 检查本地提取的图谱
```
图谱存储组件、接口、配置和跨仓库依赖边。`teamai recall` 利用图谱进行增强排名。
+5 -2
View File
@@ -1074,8 +1074,11 @@ Dependency edges are extracted by two parallel tracks: a WASM tree-sitter **AST
# 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
# Incremental refresh: reuse the original repository path and project slug
teamai codebase --extract /path/to/repo --project my-service --incremental
# Check the local graph; --output is the repository root, not teamwiki/
teamai codebase --lint --output /path/to/repo
```
### Dashboard
+5 -2
View File
@@ -1062,8 +1062,11 @@ teamai import --from-repo https://github.com/org/repo --skip-enrich
# 从本地仓库提取代码事实与图谱(写入 <repo>/teamwiki/)
teamai codebase --extract /path/to/repo --project my-service
# 图谱健康检查
teamai codebase --lint
# 增量刷新:复用首次提取的仓库路径和项目名
teamai codebase --extract /path/to/repo --project my-service --incremental
# 检查本地提取的图谱;--output 指向仓库根目录,而非 teamwiki/
teamai codebase --lint --output /path/to/repo
```
### Dashboard
+2 -2
View File
@@ -892,8 +892,8 @@ _review/ ← 过程文件(不入知识库)
| 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. |
| 一键刷新 | Use `teamai codebase --extract <repo> --project <slug> --incremental`, reusing the Phase 0 repository path and project slug even when running from another directory. Do not look for another CLI. |
| 质量评估 | Use `scripts/validate_kb.py` and `teamai codebase --lint --output <repo>` to check `<repo>/teamwiki/` (`--output` takes the repository root, not the `teamwiki/` directory). Skip any extra evaluate binary. |
**路径约定**(本 skill 安装后):
@@ -77,4 +77,47 @@ describe('teamai codebase extract CLI (issue #360 slice 1)', () => {
fs.rmSync(fixture, { recursive: true, force: true });
}
});
it('refreshes and lints the same local graph using the skill commands from another directory', async () => {
const fixture = fs.mkdtempSync(path.join(os.tmpdir(), 'teamai-local-workflow-'));
const caller = fs.mkdtempSync(path.join(os.tmpdir(), 'teamai-workflow-caller-'));
try {
const skill = fs.readFileSync(path.join(ROOT, 'skills/team-wiki-codebase/SKILL.md'), 'utf8');
const commands = [...skill.matchAll(/`(teamai codebase [^`]+)`/g)].map(match => match[1]);
const refresh = commands.find(command => command.includes('--incremental'));
const lint = commands.find(command => command.includes('--lint'));
expect(refresh).toBeDefined();
expect(lint).toBeDefined();
const args = (command: string) => command.split(/\s+/).slice(1)
.map(arg => arg === '<repo>' ? fixture : arg === '<slug>' ? 'custom-service' : arg);
const source = path.join(fixture, 'greet.ts');
fs.writeFileSync(source, 'export function originalGreeting() { return "hello"; }\n');
const initial = await runCLI(
['codebase', '--extract', fixture, '--project', 'custom-service', '--json'], caller,
);
expect(initial.code, initial.output).toBe(0);
fs.writeFileSync(source, 'export function updatedGreeting() { return "updated"; }\n');
const refreshed = await runCLI([...args(refresh!), '--json'], caller);
expect(refreshed.code, refreshed.output).toBe(0);
expect(JSON.parse(refreshed.stdout)).toMatchObject({ project: 'custom-service', incremental: true });
const wiki = path.join(fixture, 'teamwiki');
expect(fs.readdirSync(path.join(wiki, 'evidence', 'code'))).toEqual(['custom-service']);
const evidence = fs.readFileSync(path.join(wiki, 'evidence', 'code', 'custom-service', 'component.md'), 'utf8');
expect(evidence).toContain('updatedGreeting');
expect(evidence).not.toContain('originalGreeting');
expect(fs.readFileSync(path.join(wiki, 'router.md'), 'utf8')).toContain('evidence/code/custom-service/index');
expect(fs.existsSync(path.join(caller, 'teamwiki'))).toBe(false);
const checked = await runCLI([...args(lint!), '--json'], caller);
expect(checked.code, checked.output).toBe(0);
const report = JSON.parse(checked.stdout);
const graph = JSON.parse(fs.readFileSync(path.join(wiki, '.indices', 'graph-index.json'), 'utf8'));
expect(report.graphHealth.nodeCount).toBe(graph.nodes.length);
expect(report.graphHealth.nodeCount).toBeGreaterThan(0);
} finally {
fs.rmSync(fixture, { recursive: true, force: true });
fs.rmSync(caller, { recursive: true, force: true });
}
});
});