@team-ai/teamai-cli 0.0.0-stage → 0.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +1416 -0
  2. package/LICENSE +13 -0
  3. package/README.ja.md +177 -0
  4. package/README.ko.md +177 -0
  5. package/README.md +176 -2
  6. package/README.th.md +177 -0
  7. package/README.zh-CN.md +183 -0
  8. package/agents/teamai-recall.md +406 -0
  9. package/dist/cli.js +136359 -0
  10. package/dist/index.js +9 -0
  11. package/package.json +100 -4
  12. package/skill-data/core/SKILL.md +250 -0
  13. package/skill-data/core/references/commands.md +471 -0
  14. package/skill-data/core/references/contribute-member.md +161 -0
  15. package/skill-data/core/references/troubleshooting.md +419 -0
  16. package/skill-data/setup/SKILL.md +80 -0
  17. package/skill-data/setup/references/join-member.md +189 -0
  18. package/skill-data/setup/references/manage-admin.md +354 -0
  19. package/skill-data/setup/references/provider-tgit.md +101 -0
  20. package/skill-data/setup/references/setup-admin.md +312 -0
  21. package/skill-data/setup/references/uninstall.md +180 -0
  22. package/skill-data/share/SKILL.md +70 -0
  23. package/skill-data/share/references/doc-template.md +44 -0
  24. package/skill-data/wiki/SKILL.md +317 -0
  25. package/skill-data/wiki/references/agents/graph-rag-agent.md +344 -0
  26. package/skill-data/wiki/references/agents/kb-doc-generator.md +325 -0
  27. package/skill-data/wiki/references/methodology/phase0-collection.md +54 -0
  28. package/skill-data/wiki/references/methodology/phase1-reverse-engineering.md +89 -0
  29. package/skill-data/wiki/references/methodology/phase2-document-types.md +341 -0
  30. package/skill-data/wiki/references/methodology/phase3-ai-enhancement.md +164 -0
  31. package/skill-data/wiki/references/methodology/phase4-quality.md +232 -0
  32. package/skill-data/wiki/references/overview.md +125 -0
  33. package/skill-data/wiki/references/phases/k1-reverse-engineering.md +118 -0
  34. package/skill-data/wiki/references/phases/k2-documents.md +68 -0
  35. package/skill-data/wiki/references/phases/k3-ai-native.md +121 -0
  36. package/skill-data/wiki/references/phases/k4-quality.md +190 -0
  37. package/skill-data/wiki/references/phases/phase0-init.md +113 -0
  38. package/skill-data/wiki/references/templates/project-overview.md +149 -0
  39. package/skill-data/wiki/scripts/scan_repo.py +224 -0
  40. package/skill-data/wiki/scripts/validate_kb.py +256 -0
  41. package/skills/teamai/SKILL.md +46 -0
@@ -0,0 +1,256 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ validate_kb.py: knowledge base quality validation tool
4
+
5
+ Purpose: in the Phase 4 quality assessment stage, automatically check the generated knowledge base for:
6
+ 1. Link integrity (dead link detection)
7
+ 2. search-anchor coverage
8
+ 3. AI Quick Reference table coverage
9
+ 4. Bidirectional link integrity
10
+ 5. README index coverage
11
+
12
+ Usage:
13
+ python3 validate_kb.py /path/to/knowledge-base-dir
14
+ python3 validate_kb.py /path/to/knowledge-base-dir --verbose
15
+ """
16
+
17
+ import os
18
+ import re
19
+ import sys
20
+ import argparse
21
+ from pathlib import Path
22
+ from collections import defaultdict
23
+
24
+ # Markdown link regex: [text](path) or [text](path#anchor)
25
+ LINK_PATTERN = re.compile(r'\[([^\]]*)\]\(([^)]+)\)')
26
+ # search-anchor regex
27
+ ANCHOR_PATTERN = re.compile(r'<!--\s*search-anchor\s*:(.*?)-->', re.DOTALL)
28
+ # AI Quick Reference table regex. Matches both the current English heading and the
29
+ # legacy Chinese heading so knowledge bases built with earlier releases still validate.
30
+ # Legacy knowledge bases carry the Chinese heading; matched by code point so the source stays ASCII-only.
31
+ AI_TABLE_PATTERN = re.compile(r'##\s*🤖\s*AI\s*(?:Quick\s*Reference|\u5feb\u901f\u7406\u89e3)', re.IGNORECASE)
32
+ # Bidirectional link: a link back to the main / technical architecture document.
33
+ # Bilingual for the same reason as AI_TABLE_PATTERN.
34
+ BACK_LINK_PATTERN = re.compile(
35
+ r'\[📘.*(?:Technical\s*Architecture|\u4e3b\u67b6\u6784|\u6280\u672f\u67b6\u6784)|Position in the overall architecture|\u5728\u6574\u4f53\u67b6\u6784\u4e2d\u7684\u4f4d\u7f6e',
36
+ re.IGNORECASE,
37
+ )
38
+
39
+
40
+ def find_md_files(kb_dir: Path) -> list:
41
+ """Find all .md files"""
42
+ md_files = []
43
+ for root, dirs, files in os.walk(kb_dir):
44
+ dirs[:] = [d for d in dirs if not d.startswith('.')]
45
+ for f in files:
46
+ if f.endswith('.md'):
47
+ md_files.append(Path(root) / f)
48
+ return sorted(md_files)
49
+
50
+
51
+ def check_links(md_file: Path, kb_dir: Path) -> list:
52
+ """Check that the links in the file resolve"""
53
+ broken = []
54
+ try:
55
+ content = md_file.read_text(encoding='utf-8', errors='ignore')
56
+ except OSError:
57
+ return [("READ_ERROR", str(md_file), "cannot read file")]
58
+
59
+ for match in LINK_PATTERN.finditer(content):
60
+ link_text = match.group(1)
61
+ link_target = match.group(2)
62
+
63
+ # Skip external links and anchor-only links
64
+ if link_target.startswith(('http://', 'https://', 'mailto:', '#')):
65
+ continue
66
+
67
+ # Split path and anchor
68
+ path_part = link_target.split('#')[0]
69
+ if not path_part:
70
+ continue
71
+
72
+ # Resolve the relative path
73
+ target_path = (md_file.parent / path_part).resolve()
74
+ if not target_path.exists():
75
+ rel = str(md_file.relative_to(kb_dir))
76
+ broken.append((rel, link_target, link_text))
77
+
78
+ return broken
79
+
80
+
81
+ def check_anchor(md_file: Path) -> bool:
82
+ """Check whether the file contains a search-anchor"""
83
+ try:
84
+ content = md_file.read_text(encoding='utf-8', errors='ignore')
85
+ return bool(ANCHOR_PATTERN.search(content))
86
+ except OSError:
87
+ return False
88
+
89
+
90
+ def check_ai_table(md_file: Path) -> bool:
91
+ """Check whether the file contains the AI Quick Reference table"""
92
+ try:
93
+ content = md_file.read_text(encoding='utf-8', errors='ignore')
94
+ return bool(AI_TABLE_PATTERN.search(content))
95
+ except OSError:
96
+ return False
97
+
98
+
99
+ def check_back_link(md_file: Path) -> bool:
100
+ """Check whether the component document links back to the main architecture document"""
101
+ try:
102
+ content = md_file.read_text(encoding='utf-8', errors='ignore')
103
+ return bool(BACK_LINK_PATTERN.search(content))
104
+ except OSError:
105
+ return False
106
+
107
+
108
+ def check_readme_coverage(kb_dir: Path, md_files: list) -> tuple:
109
+ """Check whether the README indexes every .md file"""
110
+ readme_path = kb_dir / "README.md"
111
+ if not readme_path.exists():
112
+ return [], md_files
113
+
114
+ readme_content = readme_path.read_text(encoding='utf-8', errors='ignore')
115
+ covered = []
116
+ uncovered = []
117
+
118
+ for f in md_files:
119
+ if f.name == "README.md":
120
+ continue
121
+ # Check whether the README mentions this file
122
+ fname_no_ext = f.stem
123
+ if fname_no_ext in readme_content or f.name in readme_content:
124
+ covered.append(f)
125
+ else:
126
+ uncovered.append(f)
127
+
128
+ return covered, uncovered
129
+
130
+
131
+ def main():
132
+ parser = argparse.ArgumentParser(description="Knowledge base quality validation tool")
133
+ parser.add_argument("kb_dir", help="Path of the knowledge base directory")
134
+ parser.add_argument("--verbose", "-v", action="store_true", help="Print details")
135
+ args = parser.parse_args()
136
+
137
+ kb_dir = Path(args.kb_dir).resolve()
138
+ if not kb_dir.is_dir():
139
+ print(f"Error: {kb_dir} is not a valid directory", file=sys.stderr)
140
+ sys.exit(1)
141
+
142
+ md_files = find_md_files(kb_dir)
143
+ if not md_files:
144
+ print(f"Warning: no .md files found in {kb_dir}")
145
+ sys.exit(0)
146
+
147
+ # Filter the component design documents (files starting with a number)
148
+ component_docs = [f for f in md_files if re.match(r'^\d+_', f.name)]
149
+
150
+ print("=" * 70)
151
+ print(f" Knowledge base quality validation report")
152
+ print(f" Directory: {kb_dir}")
153
+ print(f" Files: {len(md_files)} .md files ({len(component_docs)} component documents)")
154
+ print("=" * 70)
155
+
156
+ total_score = 0
157
+ max_score = 0
158
+
159
+ # 1. Link integrity
160
+ print(f"\n## 1. Link integrity check\n")
161
+ all_broken = []
162
+ for f in md_files:
163
+ broken = check_links(f, kb_dir)
164
+ all_broken.extend(broken)
165
+
166
+ if all_broken:
167
+ print(f"❌ Found {len(all_broken)} dead links:")
168
+ for src, target, text in all_broken[:20]:
169
+ print(f" {src} → [{text}]({target})")
170
+ if len(all_broken) > 20:
171
+ print(f" ... and {len(all_broken) - 20} more")
172
+ else:
173
+ print(f"✅ All links valid ({len(md_files)} files checked)")
174
+ total_score += 20
175
+ max_score += 20
176
+
177
+ # 2. search-anchor coverage
178
+ print(f"\n## 2. Search-Anchor coverage\n")
179
+ has_anchor = sum(1 for f in md_files if check_anchor(f))
180
+ anchor_pct = has_anchor / len(md_files) * 100 if md_files else 0
181
+ print(f"{'✅' if anchor_pct >= 80 else '⚠️'} {has_anchor}/{len(md_files)} files have a search-anchor ({anchor_pct:.0f}%)")
182
+ if args.verbose:
183
+ for f in md_files:
184
+ if not check_anchor(f):
185
+ print(f" Missing: {f.relative_to(kb_dir)}")
186
+ if anchor_pct >= 80:
187
+ total_score += 20
188
+ elif anchor_pct >= 50:
189
+ total_score += 10
190
+ max_score += 20
191
+
192
+ # 3. AI Quick Reference table coverage (component documents only)
193
+ print(f"\n## 3. AI Quick Reference table coverage (component documents)\n")
194
+ if component_docs:
195
+ has_ai_table = sum(1 for f in component_docs if check_ai_table(f))
196
+ ai_pct = has_ai_table / len(component_docs) * 100
197
+ print(f"{'✅' if ai_pct >= 90 else '⚠️'} {has_ai_table}/{len(component_docs)} component documents have an AI Quick Reference table ({ai_pct:.0f}%)")
198
+ if args.verbose:
199
+ for f in component_docs:
200
+ if not check_ai_table(f):
201
+ print(f" Missing: {f.relative_to(kb_dir)}")
202
+ if ai_pct >= 90:
203
+ total_score += 20
204
+ elif ai_pct >= 60:
205
+ total_score += 10
206
+ else:
207
+ print("⚠️ No numbered component documents found")
208
+ max_score += 20
209
+
210
+ # 4. Bidirectional link check (component documents link back to the main architecture)
211
+ print(f"\n## 4. Bidirectional link check (component → main architecture)\n")
212
+ if component_docs:
213
+ has_back = sum(1 for f in component_docs if check_back_link(f))
214
+ back_pct = has_back / len(component_docs) * 100
215
+ print(f"{'✅' if back_pct >= 90 else '⚠️'} {has_back}/{len(component_docs)} component documents link back to the main architecture ({back_pct:.0f}%)")
216
+ if back_pct >= 90:
217
+ total_score += 20
218
+ elif back_pct >= 60:
219
+ total_score += 10
220
+ else:
221
+ print("⚠️ No numbered component documents found")
222
+ max_score += 20
223
+
224
+ # 5. README index coverage
225
+ print(f"\n## 5. README index coverage\n")
226
+ covered, uncovered = check_readme_coverage(kb_dir, md_files)
227
+ if (kb_dir / "README.md").exists():
228
+ cover_pct = len(covered) / (len(covered) + len(uncovered)) * 100 if (covered or uncovered) else 100
229
+ print(f"{'✅' if cover_pct >= 90 else '⚠️'} README indexes {len(covered)}/{len(covered)+len(uncovered)} documents ({cover_pct:.0f}%)")
230
+ if uncovered and args.verbose:
231
+ print(" Not indexed:")
232
+ for f in uncovered[:10]:
233
+ print(f" {f.relative_to(kb_dir)}")
234
+ if cover_pct >= 90:
235
+ total_score += 20
236
+ elif cover_pct >= 60:
237
+ total_score += 10
238
+ else:
239
+ print("❌ README.md not found")
240
+ max_score += 20
241
+
242
+ # Summary
243
+ final_pct = total_score / max_score * 100 if max_score else 0
244
+ print(f"\n{'=' * 70}")
245
+ print(f" Overall score: {total_score}/{max_score} ({final_pct:.0f}%)")
246
+ if final_pct >= 90:
247
+ print(f" Rating: ✅ Excellent. The knowledge base meets the quality bar")
248
+ elif final_pct >= 70:
249
+ print(f" Rating: ⚠️ Good. Fixing the issues above is recommended")
250
+ else:
251
+ print(f" Rating: ❌ Needs improvement. There are many quality issues")
252
+ print(f"{'=' * 70}")
253
+
254
+
255
+ if __name__ == "__main__":
256
+ main()
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: teamai
3
+ description: >-
4
+ Make every team AI native — TeamAI syncs a team's AI skills, rules, docs and env across AI coding
5
+ tools. Use when the task operates on team-shared AI configuration or team knowledge: setting up a
6
+ team repo, joining one, managing members, syncing with pull or push, or checking team status.
7
+ Also use to build or query a codebase knowledge base for a large multi-repo project (architecture
8
+ analysis, architecture reverse-engineering, code-to-knowledge, team-wiki-codebase, architecture wiki),
9
+ and to share what a session taught you back to the team (share session learnings, contribute a
10
+ learning, share what I learned with my team), including
11
+ after a friction reminder. Triggers include "set up teamai", "join the team repo", "sync team
12
+ skills", "team wiki", "share what I learned", and running /teamai. Talking about a team needs no
13
+ skill; operating on what the team shares does.
14
+ allowed-tools: Bash(teamai skill:*), Bash(npx teamai-cli skill:*)
15
+ ---
16
+
17
+ # teamai
18
+
19
+ Make every team AI native — one shared foundation for the skills, rules, docs and env a team works with.
20
+
21
+ Install: `npm i -g teamai-cli@latest` (Node.js >= 20). If `teamai skill get` is not recognised, the installed CLI predates it; upgrade the same way.
22
+
23
+ ## Start here
24
+
25
+ This file is a discovery stub, not the usage guide. Load the workflow from the CLI before running anything, so the instructions match the installed version:
26
+
27
+ ```bash
28
+ teamai skill get core # daily work: routing, pull, push, status, doctor
29
+ teamai skill get core --full # adds the full command reference and troubleshooting
30
+ ```
31
+
32
+ The CLI serves skill content that always matches the installed version, so instructions never go stale. The content in this stub cannot change between releases, which is why it just points at `skill get`.
33
+
34
+ ## Specialized workflows
35
+
36
+ ```bash
37
+ teamai skill get setup # day 0: create a team repo (admin) or join one (member), manage, uninstall
38
+ teamai skill get wiki # large multi-repo codebase: architecture reverse-engineering and knowledge base
39
+ teamai skill get share # turn what this session taught you into a team learning (needs recall on)
40
+ ```
41
+
42
+ Publishing a skill, rule or doc the user already has is in `core`; it needs no recall.
43
+
44
+ A friction reminder at the end of a turn means `teamai skill get share`.
45
+
46
+ `teamai skill list` shows everything the installed version serves. `teamai skill path <name>` prints the directory holding a skill's scripts and templates.