docs: 更新TRA编程培训课程材料、课件与AI技能交付包

- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
This commit is contained in:
smart
2026-08-08 11:00:36 +08:00
parent e7d6db93c3
commit 67837df8d0
169 changed files with 6618 additions and 2887 deletions
@@ -0,0 +1,133 @@
---
name: project-knowledge-builder
description: Use when a user asks “项目知识库”, “看项目”, “整理项目”, or otherwise wants to inspect a software project deeply, build/refresh a project knowledge base, create onboarding docs, architecture maps, domain glossaries, ADRs, generated API/config/database indexes, or RAG-ready repository documentation.
---
# Project Knowledge Builder
## Overview
Build a source-grounded project knowledge base that helps humans and AI agents understand, extend, troubleshoot, and index a codebase. Treat the knowledge base as a maintained system artifact, not a README rewrite.
## Quick Use
Users should not need to remember commands, script paths, or `$project-knowledge-builder`.
The shortest trigger is enough:
- `项目知识库`
Treat the current repository as the target and `docs/project-knowledge/` as the output path unless the user says otherwise. Run the bundled inventory script yourself and write the docs. Only show manual commands when the user explicitly asks for command-line usage.
## Language And Audience Defaults
If the user writes in Chinese or asks for Chinese, write human-facing narrative docs in Chinese by default: README, context, architecture, runtime, backend, frontend, data, auth/permissions, extension, troubleshooting, RAG guidance and ADRs. Keep source paths, class names, commands, API paths, config keys, table names, permission codes and metadata enum values unchanged.
Treat beginners as a primary audience. A useful knowledge base should let a new maintainer answer four questions without extra coaching:
1. What is this project and where are the main modules?
2. How do I run it locally or identify the active runtime mode?
3. How do I find the backend endpoint, frontend page, database table and permission code for a feature?
4. What must change when adding a normal feature, especially menu/button permissions?
Do not make generated indexes overly friendly at the cost of precision. Keep generated files machine-refreshable; make narrative docs readable.
## Core Rule
Every claim must be traceable to the repository or to an explicitly marked inference. Prefer source paths, commands, generated inventories, and unresolved-question lists over confident prose.
## Workflow
1. **Set scope.** Confirm or assume the output location. Default to `docs/project-knowledge/`. If the user mentions RAG, Feishu/Lark, Dify, Notion, onboarding, architecture review, or API docs, tailor the output contract.
2. **Read local instructions first.** Check root docs plus `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.codex/`, `.agents/`, package manifests, build files, env examples, Docker files, and module READMEs.
3. **Generate an inventory.** Run `scripts/project_inventory.py` from this skill against the repo. Use its output as a factual base, then inspect important files manually.
4. **Map contexts.** Identify bounded contexts, runtime modes, major modules, owners implied by paths, external systems, and data stores. Use `CONTEXT.md` and `CONTEXT-MAP.md` style docs.
5. **Extract generated indexes.** Produce machine-refreshable docs where possible: endpoints, frontend routes/views, config keys, env variables, database tables, permission codes, scheduled jobs, queues, and extension points.
6. **Write human guides.** Produce onboarding, architecture, local run/deploy, data model, auth/permission, extension, troubleshooting, and glossary docs. Match the user's language for narrative docs; for Chinese users, use Chinese section titles such as `已观察来源`, `核心事实`, `操作影响`, and `未知与风险`.
7. **Create ADRs for real decisions.** Record important architecture decisions already embodied in the code. Do not invent future decisions unless marked as proposed.
8. **Add RAG metadata guidance.** Include chunking, source-path metadata, stale-data policy, and exclusion rules.
9. **Verify.** Re-run the inventory, scan docs for placeholders, broken relative links, stale paths, and unsupported claims. Report what was verified and what remains uncertain.
## Output Contract
Read `references/output-contract.md` when creating or upgrading a full knowledge base.
Minimum useful set:
```text
docs/project-knowledge/
├── README.md
├── CONTEXT.md
├── CONTEXT-MAP.md
├── 01-architecture.md
├── 02-runtime.md
├── 03-backend.md
├── 04-frontend.md
├── 05-data-and-migrations.md
├── 06-auth-permissions.md
├── 07-extension-guide.md
├── 08-troubleshooting.md
├── 09-rag-indexing.md
├── adr/
│ └── 0001-current-runtime-architecture.md
└── generated/
├── project-inventory.md
├── backend-endpoints.md
├── frontend-routes.md
├── config-reference.md
├── database-dictionary.md
└── permission-codes.md
```
Scale down only if the repo is small or the user requests a lighter artifact.
## Source-Grounding Standards
- Cite source paths inline for non-obvious claims.
- Distinguish **Observed** from **Inferred** and **Unknown**.
- Do not summarize generated code, dependencies, or configs from memory. Read them.
- If external docs are needed for unstable facts, browse primary sources and link them.
- Preserve project-specific conventions. If a repo requires trace comments, ADR format, or issue IDs, document and follow that.
## Cross-Platform Compatibility
Read `references/compatibility.md` when the user asks about macOS, Windows, Linux, CI, portability, or installing/running the skill across machines. The bundled inventory script is intended to run on Python 3.9+ with only the standard library.
## Inventory Script
Use this only for manual refreshes or when the user asks for the command. Run from the target repo:
macOS/Linux:
```sh
python3 /path/to/skill/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
```
Windows PowerShell:
```powershell
py -3 C:\path\to\skill\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
```
Useful options:
```sh
python3 /path/to/skill/scripts/project_inventory.py --root . --out ./kb-inventory --json
python3 /path/to/skill/scripts/project_inventory.py --root . --out docs/project-knowledge/generated --max-files 20000
```
The script is a starting point, not a replacement for reading core files. Inspect representative files before writing narrative docs.
## Quality Gates
Before final response:
- List generated docs with a platform-appropriate command, such as `find docs/project-knowledge -type f | sort` on macOS/Linux or `Get-ChildItem docs/project-knowledge -Recurse -File` on PowerShell.
- `rg -n "TODO|TBD|待补|unknown|your/path|foo|bar" docs/project-knowledge`
- Re-run the inventory script after edits.
- Check that top-level README links resolve.
- If the user is Chinese, scan narrative docs for English-only structural headings such as `Observed Sources`, `Core Facts`, `Operational Implications`, `Unknowns/Risks`, `Architecture`, `Runtime`, `Backend`, `Frontend`, `Troubleshooting`, and translate them unless they are code, metadata, or generated output.
- Check newcomer usefulness: README gives a reading order; runtime doc names local/Docker/cloud modes; auth doc explains menu/button permission flow; extension doc explains backend CRUD, frontend page and permission changes.
- `git status --short` to report changed files.
If the user asked for “deep” or “落地”, do not stop at a single overview. Deliver generated indexes plus human guides.
@@ -0,0 +1,133 @@
---
name: project-knowledge-builder
description: 当用户要求“项目知识库”“看项目”“整理项目”,或需要深度检查软件项目、构建/刷新项目知识库、创建入门文档、架构图、领域词汇表、ADR、API/配置/数据库生成索引或 RAG 友好仓库文档时使用。
---
# 项目知识库构建
## 概览
构建一个有源码依据的项目知识库,帮助人和 AI 理解、扩展、排障和索引代码库。把知识库视为持续维护的系统资产,而不是 README 改写。
## 快速使用
用户不需要记住命令、脚本路径或 `$project-knowledge-builder`。
最短触发语即可:
- `项目知识库`
除非用户另有说明,将当前仓库作为目标,输出到 `docs/project-knowledge/`。由你运行 bundled inventory 脚本并写文档。只有用户明确要求命令行用法时,才展示手工命令。
## 语言和受众默认值
如果用户使用中文或要求中文,人类阅读的叙述文档默认使用中文:README、上下文、架构、运行、后端、前端、数据、认证/权限、扩展、排障、RAG 指南和 ADR。源码路径、类名、命令、API 路径、配置键、表名、权限码、元数据枚举值保持原样。
把新维护者作为主要受众。一个有用的知识库应该让新人无需额外辅导就能回答四个问题:
1. 这个项目是什么,主要模块在哪里?
2. 如何本地运行,或如何识别当前运行模式?
3. 如何找到某个功能对应的后端接口、前端页面、数据库表和权限码?
4. 新增普通功能时通常需要修改什么,尤其是菜单/按钮权限?
生成索引不要为了友好而牺牲精确性。生成文件要便于机器刷新;叙述文档要便于人阅读。
## 核心规则
每个结论都必须能追溯到仓库,或明确标记为推断。优先使用源码路径、命令、生成索引和未解决问题清单,而不是自信散文。
## 工作流
1. **设定范围。** 确认或默认输出位置为 `docs/project-knowledge/`。如果用户提到 RAG、飞书/Lark、Dify、Notion、入门、架构 Review 或 API 文档,调整输出契约。
2. **优先读取本地说明。** 检查根文档,以及 `AGENTS.md`、`CLAUDE.md`、`GEMINI.md`、`.codex/`、`.agents/`、包管理文件、构建文件、env 示例、Docker 文件和模块 README。
3. **生成 inventory。** 对目标仓库运行本 Skill 的 `scripts/project_inventory.py`。用输出作为事实基础,再人工检查关键文件。
4. **映射上下文。** 识别限界上下文、运行模式、主要模块、路径暗示的 owner、外部系统和数据存储。使用 `CONTEXT.md` 和 `CONTEXT-MAP.md` 风格文档。
5. **提取生成索引。** 尽可能产出可机器刷新的文档:接口、前端路由/视图、配置键、环境变量、数据库表、权限码、定时任务、队列、扩展点。
6. **编写人类指南。** 产出入门、架构、本地运行/部署、数据模型、认证/权限、扩展、排障和术语表文档。按用户语言书写;中文用户使用 `已观察来源`、`核心事实`、`操作影响`、`未知与风险` 等标题。
7. **为真实决策创建 ADR。** 记录当前代码已经体现的重要架构决策。不要发明未来决策,除非标为 proposed。
8. **添加 RAG 元数据指南。** 包括切块、source-path metadata、过期策略和排除规则。
9. **验证。** 重新运行 inventory,扫描占位符、坏链接、过期路径和无依据结论。报告已验证内容和仍不确定内容。
## 输出契约
创建或升级完整知识库时读取 `references/output-contract_zh.md`。
最小有用集合:
```text
docs/project-knowledge/
├── README.md
├── CONTEXT.md
├── CONTEXT-MAP.md
├── 01-architecture.md
├── 02-runtime.md
├── 03-backend.md
├── 04-frontend.md
├── 05-data-and-migrations.md
├── 06-auth-permissions.md
├── 07-extension-guide.md
├── 08-troubleshooting.md
├── 09-rag-indexing.md
├── adr/
│ └── 0001-current-runtime-architecture.md
└── generated/
├── project-inventory.md
├── backend-endpoints.md
├── frontend-routes.md
├── config-reference.md
├── database-dictionary.md
└── permission-codes.md
```
只有仓库较小或用户要求轻量产物时,才缩小范围。
## 来源依据标准
- 非显然结论必须内联引用来源路径。
- 区分 **已观察**、**推断** 和 **未知**。
- 不要凭记忆总结生成代码、依赖或配置,必须读取。
- 如果不稳定事实需要外部文档,浏览一手来源并附链接。
- 保留项目专用约定。如果仓库要求追踪注释、ADR 格式或 issue ID,记录并遵守。
## 跨平台兼容
当用户询问 macOS、Windows、Linux、CI、可移植性或跨机器安装/运行时,读取 `references/compatibility_zh.md`。bundled inventory 脚本面向 Python 3.9+,只使用标准库。
## Inventory 脚本
仅在手工刷新或用户询问命令时展示。请在目标仓库运行:
macOS/Linux:
```sh
python3 /path/to/skill/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
```
Windows PowerShell:
```powershell
py -3 C:\path\to\skill\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
```
常用选项:
```sh
python3 /path/to/skill/scripts/project_inventory.py --root . --out ./kb-inventory --json
python3 /path/to/skill/scripts/project_inventory.py --root . --out docs/project-knowledge/generated --max-files 20000
```
脚本只是起点,不能替代阅读核心文件。编写叙述文档前,必须检查代表性文件。
## 质量门禁
最终回复前:
- 用适合平台的命令列出生成文档,例如 macOS/Linux 使用 `find docs/project-knowledge -type f | sort`,PowerShell 使用 `Get-ChildItem docs/project-knowledge -Recurse -File`。
- 执行 `rg -n "TODO|TBD|待补|unknown|your/path|foo|bar" docs/project-knowledge`。
- 编辑后重新运行 inventory 脚本。
- 检查顶层 README 链接是否可解析。
- 如果用户是中文用户,扫描叙述文档中是否仍有英文结构标题,例如 `Observed Sources`、`Core Facts`、`Operational Implications`、`Unknowns/Risks`、`Architecture`、`Runtime`、`Backend`、`Frontend`、`Troubleshooting`,除代码、元数据或生成输出外应翻译。
- 检查新人可用性:README 给出阅读顺序;运行文档说明本地/Docker/云端模式;权限文档说明菜单/按钮权限流;扩展文档说明后端 CRUD、前端页面和权限变更。
- 使用 `git status --short` 报告变更文件。
如果用户要求“深度”或“落地”,不要停在单页概览。必须交付生成索引和人类指南。
@@ -0,0 +1,4 @@
interface:
display_name: "项目知识库"
short_description: "深度整理代码仓库知识库"
default_prompt: "Use $project-knowledge-builder 为当前项目生成 docs/project-knowledge 项目知识库。"
@@ -0,0 +1,65 @@
# Cross-Platform Compatibility
Use this reference when running or installing the skill on macOS, Windows, Linux, or CI.
## Compatibility Summary
| Area | macOS | Linux | Windows |
| --- | --- | --- | --- |
| `SKILL.md` workflow | Supported | Supported | Supported |
| `project_inventory.py` | Supported with Python 3.9+ | Supported with Python 3.9+ | Supported with Python 3.9+ |
| Python dependencies | Standard library only | Standard library only | Standard library only |
| Path handling | `pathlib` | `pathlib` | `pathlib` |
| Shell dependency | None in script | None in script | None in script |
| Generated Markdown paths | POSIX-style relative paths | POSIX-style relative paths | POSIX-style relative paths |
The script intentionally emits repository-relative paths with `/` separators so generated Markdown is stable across platforms and friendlier for URLs, GitHub, and RAG metadata.
## Python Invocation
macOS and Linux usually have one of these:
```sh
python3 skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
python skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
```
Windows PowerShell usually uses:
```powershell
py -3 skills\project-knowledge-builder\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
python skills\project-knowledge-builder\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
```
CI should prefer an explicit Python:
```sh
python -m py_compile skills/project-knowledge-builder/scripts/project_inventory.py
python skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated --json
```
## Command Substitutions
| Task | macOS/Linux | Windows PowerShell |
| --- | --- | --- |
| List docs | `find docs/project-knowledge -type f \| sort` | `Get-ChildItem docs/project-knowledge -Recurse -File \| Sort-Object FullName` |
| Search placeholders | `rg -n "TODO|TBD" docs/project-knowledge` | `rg -n "TODO|TBD" docs/project-knowledge` |
| Show git status | `git status --short` | `git status --short` |
| Remove temp output | `rm -rf ./kb-inventory` | `Remove-Item .\kb-inventory -Recurse -Force` |
`rg` is preferred where available. If `rg` is not installed, use the platform search available in the environment.
## Avoid In Skill Examples
- Hard-coded `/tmp` paths when the command should work on Windows.
- POSIX-only command chains such as `cmd1 && cmd2` in user-facing instructions when a PowerShell equivalent is needed.
- Shell glob assumptions that behave differently between zsh, bash, PowerShell, and cmd.
- Python code that depends on executable shebang behavior; Windows users should call `py -3 script.py`.
## Known Limits
- Java endpoint extraction is regex-based and intentionally conservative. It does not fully resolve constants, composed annotations, or inherited controller mappings.
- SQL table extraction looks for `CREATE TABLE`; tables created dynamically or through migrations in another DSL need manual documentation.
- Frontend route extraction scans route-like literals and view files; runtime-generated route data from APIs still requires backend menu/permission data or database export.
- Very large repositories may need `--max-files` tuning or additional ignore directories.
@@ -0,0 +1,64 @@
# 跨平台兼容
在 macOS、Windows、Linux 或 CI 上运行或安装本 Skill 时使用本参考。
## 兼容性摘要
| 项目 | macOS | Linux | Windows |
| --- | --- | --- | --- |
| `SKILL.md` 工作流 | 支持 | 支持 | 支持 |
| `project_inventory.py` | Python 3.9+ 支持 | Python 3.9+ 支持 | Python 3.9+ 支持 |
| Python 依赖 | 仅标准库 | 仅标准库 | 仅标准库 |
| 路径处理 | `pathlib` | `pathlib` | `pathlib` |
| shell 依赖 | 脚本无依赖 | 脚本无依赖 | 脚本无依赖 |
| 生成 Markdown 路径 | POSIX 风格相对路径 | POSIX 风格相对路径 | POSIX 风格相对路径 |
脚本故意使用带 `/` 分隔符的仓库相对路径,使生成 Markdown 在跨平台、GitHub URL 和 RAG metadata 中更稳定。
## Python 调用
macOS 和 Linux 通常使用:
```sh
python3 skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
python skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated
```
Windows PowerShell 通常使用:
```powershell
py -3 skills\project-knowledge-builder\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
python skills\project-knowledge-builder\scripts\project_inventory.py --root . --out docs\project-knowledge\generated
```
CI 应优先使用明确的 Python:
```sh
python -m py_compile skills/project-knowledge-builder/scripts/project_inventory.py
python skills/project-knowledge-builder/scripts/project_inventory.py --root . --out docs/project-knowledge/generated --json
```
## 命令替换
| 任务 | macOS/Linux | Windows PowerShell |
| --- | --- | --- |
| 列出文档 | `find docs/project-knowledge -type f \| sort` | `Get-ChildItem docs/project-knowledge -Recurse -File \| Sort-Object FullName` |
| 搜索占位符 | `rg -n "TODO|TBD" docs/project-knowledge` | `rg -n "TODO|TBD" docs/project-knowledge` |
| 查看 git 状态 | `git status --short` | `git status --short` |
| 删除临时输出 | `rm -rf ./kb-inventory` | `Remove-Item .\kb-inventory -Recurse -Force` |
优先使用 `rg`。如果环境中没有 `rg`,使用该平台可用的搜索工具。
## Skill 示例中应避免
- 在应支持 Windows 的命令中写死 `/tmp` 路径。
- 在面向用户的说明中只给 POSIX 命令链,例如 `cmd1 && cmd2`,而不给 PowerShell 等价方式。
- 假设 shell glob 在 zsh、bash、PowerShell、cmd 中行为一致。
- 依赖 shebang 可执行行为的 Python 用法;Windows 用户应调用 `py -3 script.py`。
## 已知限制
- Java endpoint 提取基于正则,故意保持保守。它不会完整解析常量、组合注解或继承的 controller mapping。
- SQL 表提取查找 `CREATE TABLE`;动态创建的表或其他迁移 DSL 需要人工文档化。
- 前端路由提取会扫描 route-like 字面量和 view 文件;运行时由 API 生成的路由仍需要后端菜单/权限数据或数据库导出。
- 超大仓库可能需要调整 `--max-files`,或增加忽略目录。
@@ -0,0 +1,142 @@
# Project Knowledge Builder Output Contract
Use this reference when producing a full codebase knowledge base.
## Language Policy
Match the user's language for human-facing narrative docs. If the user writes in Chinese or asks for Chinese, write README, context, architecture, runtime, backend, frontend, data, auth/permissions, extension, troubleshooting, RAG guidance and ADRs in Chinese.
Keep technical anchors unchanged: source paths, commands, class names, method names, API paths, config keys, table names, permission codes, JSON keys and metadata enum values.
Generated indexes may remain technical and source-like. Do not hand-translate generated values if it reduces refreshability.
## Document Roles
| File | Purpose |
| --- | --- |
| `README.md` | Entry point, reading order, high-value links, freshness note. For Chinese output, title and usage guidance should be Chinese. |
| `CONTEXT.md` | Domain language, business capabilities, user roles, core nouns, invariants. |
| `CONTEXT-MAP.md` | Bounded contexts, module ownership, upstream/downstream dependencies, runtime boundaries. |
| `01-architecture.md` | System shape, module graph, request/data/control flows, extension seams. |
| `02-runtime.md` | Local run, build, env vars, Docker, deployment modes, process topology. Must identify local, Docker standalone and cloud modes when present. |
| `03-backend.md` | Backend modules, entrypoints, API conventions, service/mapper/entity patterns. |
| `04-frontend.md` | Frontend bootstrap, routing, state, API client, component/page conventions. |
| `05-data-and-migrations.md` | Databases, migrations, schema sources, seed data, table families. |
| `06-auth-permissions.md` | Authentication, authorization, token/session flow, permission-code lifecycle. Must explain menu/button permission flow when the repo has backend-driven menus. |
| `07-extension-guide.md` | How to add a feature end-to-end, with source-grounded examples. Must cover backend CRUD, frontend page and permission/menu data changes when applicable. |
| `08-troubleshooting.md` | Symptom-driven runbook with commands, files, and likely causes. |
| `09-rag-indexing.md` | Chunking, metadata, exclusions, refresh cadence, stale-data policy. |
| `adr/*.md` | Architecture decisions observed in the current code. |
| `generated/*.md` | Data-derived indexes that can be regenerated. |
## Required Sections
Each narrative doc should include:
- **Observed Sources:** concrete files or commands used.
- **Core Facts:** concise source-backed statements.
- **Operational Implications:** what developers must do differently because of those facts.
- **Unknowns/Risks:** gaps that need runtime access, DB export, product owner input, or external docs.
For Chinese output, use equivalent section labels:
- **已观察来源**
- **核心事实**
- **操作影响**
- **未知与风险**
## Newcomer Usefulness Gate
Before considering the knowledge base useful for handoff, verify that a new maintainer can answer:
1. What is the product/project, and which directories matter first?
2. How do I start or identify the active runtime mode?
3. Where are backend endpoints, frontend routes/pages, config, tables and permission codes indexed?
4. How do menu, button and backend permission checks connect?
5. When adding a normal feature, which backend, frontend, database and permission artifacts usually change?
If the answer is not obvious from README plus the narrative docs, add or revise human-facing guidance before finishing. Do not solve this by making generated indexes longer.
## Generated Indexes
### `project-inventory.md`
Include:
- repository roots
- build/package manifests
- primary languages
- major directories
- scripts
- Docker/compose files
- env files
- test files
### `backend-endpoints.md`
Include route method, path, class/file, approximate line, auth annotations, and notes. Do not invent full route paths when class-level and method-level mappings require Java expression resolution; show observed fragments and mark composition limitations.
### `frontend-routes.md`
Include static router files, dynamic route loaders, `src/views` index, route guard files, and external route package loaders.
### `config-reference.md`
Include env files, YAML/properties files, relevant keys, default values, and risk notes. Redact secrets.
### `database-dictionary.md`
Include SQL files, migration files, table names, table families, and whether the table is initialized, migrated, or inferred. Avoid loading huge SQL into prose; summarize and link.
### `permission-codes.md`
Include backend annotations, frontend permission helpers/usages, menu/permission SQL occurrences, and auth lifecycle notes.
## ADR Template
```markdown
# ADR NNNN: Title
Date: YYYY-MM-DD
Status: Observed
## Context
Source-backed facts that show the decision exists.
## Decision
The architecture decision embodied by the current code.
## Consequences
Benefits, tradeoffs, operational constraints, and migration risks.
## Sources
- `path/to/file`
```
## RAG Metadata
Recommended metadata per chunk:
```json
{
"project": "name",
"snapshot_date": "YYYY-MM-DD",
"source_path": "path",
"doc_type": "architecture|runtime|generated|adr|runbook",
"domain": "backend|frontend|data|auth|deploy",
"freshness": "manual|generated",
"confidence": "observed|inferred|unknown"
}
```
## Anti-Patterns
- A long essay without generated indexes.
- “Best practice” advice unrelated to the repo.
- Copying README marketing text as architecture documentation.
- Claiming an endpoint, table, permission, or runtime mode exists without a source path.
- Hiding unknowns instead of listing them.
@@ -0,0 +1,135 @@
# 项目知识库输出契约
生成完整代码库知识库时使用本参考。
## 语言策略
人类阅读的叙述文档应匹配用户语言。如果用户使用中文或要求中文,README、上下文、架构、运行、后端、前端、数据、认证/权限、扩展、排障、RAG 指南和 ADR 都应使用中文。
技术锚点保持原样:源码路径、命令、类名、方法名、API 路径、配置键、表名、权限码、JSON key 和元数据枚举值。
生成索引可以保持技术化和接近源码。不要为了翻译而破坏可刷新性。
## 文档职责
| 文件 | 用途 |
| --- | --- |
| `README.md` | 入口、阅读顺序、高价值链接、新鲜度说明。中文输出时标题和使用说明应为中文。 |
| `CONTEXT.md` | 领域语言、业务能力、用户角色、核心名词、不变量。 |
| `CONTEXT-MAP.md` | 限界上下文、模块归属、上下游依赖、运行边界。 |
| `01-architecture.md` | 系统形态、模块图、请求/数据/控制流、扩展点。 |
| `02-runtime.md` | 本地运行、构建、环境变量、Docker、部署模式、进程拓扑。存在时必须识别本地、Docker standalone 和云端模式。 |
| `03-backend.md` | 后端模块、入口点、API 约定、service/mapper/entity 模式。 |
| `04-frontend.md` | 前端启动、路由、状态、API client、组件/页面约定。 |
| `05-data-and-migrations.md` | 数据库、迁移、schema 来源、种子数据、表族。 |
| `06-auth-permissions.md` | 认证、授权、token/session 流、权限码生命周期。仓库存在后端驱动菜单时,必须解释菜单/按钮权限流。 |
| `07-extension-guide.md` | 如何端到端新增功能,并给出有来源依据的示例。适用时必须覆盖后端 CRUD、前端页面和权限/菜单数据变更。 |
| `08-troubleshooting.md` | 面向症状的排障手册,包含命令、文件和可能原因。 |
| `09-rag-indexing.md` | 切块、元数据、排除规则、刷新频率、过期数据策略。 |
| `adr/*.md` | 当前代码已经体现的架构决策。 |
| `generated/*.md` | 可重新生成的数据索引。 |
## 必要章节
每份叙述文档应包含:
- **已观察来源**:使用过的具体文件或命令。
- **核心事实**:简洁、有来源依据的陈述。
- **操作影响**:开发者因这些事实需要采取的不同做法。
- **未知与风险**:需要运行权限、数据库导出、产品负责人输入或外部文档才能确认的缺口。
## 新人可用性门禁
认为知识库可交接前,确认新维护者能回答:
1. 这个产品/项目是什么,哪些目录最重要?
2. 如何启动,或如何识别当前运行模式?
3. 后端接口、前端路由/页面、配置、数据表、权限码在哪里索引?
4. 菜单、按钮和后端权限校验如何连接?
5. 新增普通功能时,通常会改哪些后端、前端、数据库和权限产物?
如果 README 加叙述文档无法明显回答这些问题,先补充或修改人类阅读指南。不要通过加长生成索引来解决。
## 生成索引
### `project-inventory.md`
包含:
- 仓库根路径
- 构建/包管理清单
- 主要语言
- 主要目录
- scripts
- Docker/compose 文件
- env 文件
- 测试文件
### `backend-endpoints.md`
包含路由方法、路径、类/文件、近似行号、认证注解和备注。不要在 class-level 与 method-level mapping 需要 Java 表达式解析时编造完整路径;展示已观察片段,并标记组合限制。
### `frontend-routes.md`
包含静态路由文件、动态路由加载器、`src/views` 索引、路由守卫文件和外部路由包加载器。
### `config-reference.md`
包含 env 文件、YAML/properties 文件、相关 key、默认值和风险说明。敏感信息必须脱敏。
### `database-dictionary.md`
包含 SQL 文件、迁移文件、表名、表族,以及表是初始化、迁移还是推断得出。不要把巨大 SQL 写进正文;摘要并链接来源。
### `permission-codes.md`
包含后端注解、前端权限 helper/usage、菜单/权限 SQL 命中和认证生命周期说明。
## ADR 模板
```markdown
# ADR NNNN: 标题
Date: YYYY-MM-DD
Status: Observed
## Context
说明该决策已经存在的来源事实。
## Decision
当前代码体现的架构决策。
## Consequences
收益、取舍、操作约束和迁移风险。
## Sources
- `path/to/file`
```
## RAG 元数据
推荐每个 chunk 使用:
```json
{
"project": "name",
"snapshot_date": "YYYY-MM-DD",
"source_path": "path",
"doc_type": "architecture|runtime|generated|adr|runbook",
"domain": "backend|frontend|data|auth|deploy",
"freshness": "manual|generated",
"confidence": "observed|inferred|unknown"
}
```
## 反模式
- 只有长篇说明,没有生成索引。
- 写与仓库无关的“最佳实践”建议。
- 把 README 营销文案复制成架构文档。
- 没有来源路径就声称某接口、表、权限或运行模式存在。
- 隐藏未知问题,而不是列出来。
@@ -0,0 +1,313 @@
#!/usr/bin/env python3
"""Generate a source-grounded project inventory for knowledge-base work."""
from __future__ import annotations
import argparse
import json
import os
import re
from collections import Counter, defaultdict
from pathlib import Path
from typing import Iterable
IGNORE_DIRS = {
".git",
".idea",
".vscode",
"node_modules",
"dist",
"build",
"target",
".gradle",
".mvn/wrapper",
"coverage",
".next",
".nuxt",
"__pycache__",
}
MANIFEST_NAMES = {
"package.json",
"pnpm-lock.yaml",
"yarn.lock",
"package-lock.json",
"pom.xml",
"build.gradle",
"settings.gradle",
"Cargo.toml",
"pyproject.toml",
"requirements.txt",
"go.mod",
"composer.json",
"Gemfile",
}
CONFIG_PATTERNS = (
re.compile(r".*\.env(\..*)?$"),
re.compile(r".*application[-\w]*\.(yml|yaml|properties)$"),
re.compile(r".*\.(ya?ml|toml|ini|properties|conf)$"),
)
HTTP_MAPPING_RE = re.compile(
r"@(RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping|PatchMapping)\s*(?:\((.*?)\))?"
)
PERMISSION_RE = re.compile(r"@(?:RequiresPermissions|RequiresRoles)\s*\((.*?)\)")
TABLE_NAME_RE = re.compile(
r"\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?`?([A-Za-z0-9_.$-]+)`?",
re.IGNORECASE,
)
VUE_ROUTE_RE = re.compile(r"\b(path|name|component)\s*:\s*['\"]([^'\"]+)['\"]")
def is_ignored(path: Path, root: Path) -> bool:
rel_parts = path.relative_to(root).parts
for i in range(len(rel_parts)):
joined = "/".join(rel_parts[: i + 1])
if joined in IGNORE_DIRS or rel_parts[i] in IGNORE_DIRS:
return True
return False
def iter_files(root: Path, max_files: int) -> Iterable[Path]:
count = 0
for dirpath, dirnames, filenames in os.walk(root):
current = Path(dirpath)
dirnames[:] = [d for d in dirnames if not is_ignored(current / d, root)]
for name in filenames:
path = current / name
if is_ignored(path, root):
continue
count += 1
if count > max_files:
return
yield path
def rel(path: Path, root: Path) -> str:
return path.relative_to(root).as_posix()
def read_text(path: Path, limit: int = 400_000) -> str:
try:
data = path.read_bytes()
except OSError:
return ""
if len(data) > limit:
data = data[:limit]
try:
return data.decode("utf-8")
except UnicodeDecodeError:
try:
return data.decode("utf-8", errors="ignore")
except Exception:
return ""
def detect_config(path: Path) -> bool:
name = path.name
return any(pattern.fullmatch(name) for pattern in CONFIG_PATTERNS)
def extract_mapping_value(raw: str | None) -> str:
if not raw:
return ""
value_match = re.search(r"['\"]([^'\"]+)['\"]", raw)
if value_match:
return value_match.group(1)
return raw.strip().replace("\n", " ")[:120]
def scan(root: Path, max_files: int) -> dict:
files = list(iter_files(root, max_files))
ext_counts = Counter(path.suffix.lower() or "[none]" for path in files)
manifests = []
configs = []
docker = []
tests = []
java_endpoints = []
permission_codes = []
vue_routes = []
views = []
sql_tables = []
major_dirs = defaultdict(int)
for path in files:
r = rel(path, root)
parts = Path(r).parts
if parts:
major_dirs[parts[0]] += 1
if path.name in MANIFEST_NAMES:
manifests.append(r)
lower = path.name.lower()
if lower.startswith("dockerfile") or "docker-compose" in lower:
docker.append(r)
if detect_config(path):
configs.append(r)
if re.search(r"(^|/)(test|tests|__tests__)(/|$)", r) or re.search(r"\.(test|spec)\.[A-Za-z0-9]+$", r):
tests.append(r)
if "/src/views/" in r and path.suffix.lower() in {".vue", ".tsx", ".ts"}:
views.append(r)
suffix = path.suffix.lower()
if suffix not in {".java", ".ts", ".tsx", ".vue", ".js", ".jsx", ".sql", ".yml", ".yaml", ".properties"}:
continue
text = read_text(path)
if not text:
continue
if suffix == ".java":
lines = text.splitlines()
class_mapping = ""
class_name = ""
pending_annotations: list[tuple[int, str, str]] = []
for idx, line in enumerate(lines, start=1):
class_match = re.search(r"\bclass\s+([A-Za-z0-9_]+)", line)
if class_match:
class_name = class_match.group(1)
for match in HTTP_MAPPING_RE.finditer(line):
value = extract_mapping_value(match.group(2))
annotation = match.group(1)
pending_annotations.append((idx, annotation, value))
if annotation == "RequestMapping" and not class_mapping and ("class " not in line):
class_mapping = value
if re.search(r"\b(public|private|protected)\b.*\(", line) and pending_annotations:
method = line.strip()[:160]
for ann_line, annotation, value in pending_annotations:
java_endpoints.append(
{
"file": r,
"line": ann_line,
"class": class_name,
"annotation": annotation,
"class_mapping": class_mapping,
"mapping": value,
"method_signature": method,
}
)
pending_annotations = []
for perm in PERMISSION_RE.finditer(line):
permission_codes.append({"file": r, "line": idx, "value": perm.group(1).strip()})
if suffix in {".ts", ".tsx", ".vue", ".js", ".jsx"}:
for idx, line in enumerate(text.splitlines(), start=1):
if "path:" in line or "component:" in line or "name:" in line:
for match in VUE_ROUTE_RE.finditer(line):
vue_routes.append({"file": r, "line": idx, "key": match.group(1), "value": match.group(2)})
if suffix == ".sql":
for match in TABLE_NAME_RE.finditer(text):
sql_tables.append({"file": r, "table": match.group(1)})
return {
"root": str(root),
"file_count": len(files),
"extensions": dict(ext_counts.most_common(40)),
"major_dirs": dict(sorted(major_dirs.items(), key=lambda item: (-item[1], item[0]))),
"manifests": sorted(manifests),
"configs": sorted(configs),
"docker": sorted(docker),
"tests": sorted(tests),
"views": sorted(views),
"java_endpoints": java_endpoints,
"permission_codes": permission_codes,
"vue_routes": vue_routes,
"sql_tables": sql_tables,
}
def write_md(data: dict, out_dir: Path) -> None:
out_dir.mkdir(parents=True, exist_ok=True)
def bullet(items: list[str], limit: int | None = None) -> str:
selected = items if limit is None else items[:limit]
if not selected:
return "- None found\n"
body = "".join(f"- `{item}`\n" for item in selected)
if limit is not None and len(items) > limit:
body += f"- ... {len(items) - limit} more\n"
return body
inventory = [
"# Project Inventory\n\n",
f"Root: `{data['root']}`\n\n",
f"Files scanned: {data['file_count']}\n\n",
"## Major Directories\n\n",
]
inventory.extend(f"- `{name}`: {count} files\n" for name, count in data["major_dirs"].items())
inventory.extend(["\n## Extensions\n\n"])
inventory.extend(f"- `{name}`: {count}\n" for name, count in data["extensions"].items())
inventory.extend(["\n## Manifests\n\n", bullet(data["manifests"])])
inventory.extend(["\n## Config Files\n\n", bullet(data["configs"], 200)])
inventory.extend(["\n## Docker Files\n\n", bullet(data["docker"])])
inventory.extend(["\n## Test Files\n\n", bullet(data["tests"], 200)])
(out_dir / "project-inventory.md").write_text("".join(inventory), encoding="utf-8")
endpoints = ["# Backend Endpoints\n\n"]
if data["java_endpoints"]:
endpoints.append("| File | Line | Class | Annotation | Class Mapping | Mapping | Method |\n")
endpoints.append("| --- | ---: | --- | --- | --- | --- | --- |\n")
for item in data["java_endpoints"]:
method_signature = item["method_signature"].replace("|", "\\|")
endpoints.append(
f"| `{item['file']}` | {item['line']} | `{item['class']}` | `{item['annotation']}` | "
f"`{item['class_mapping']}` | `{item['mapping']}` | `{method_signature}` |\n"
)
else:
endpoints.append("No Java endpoint annotations found.\n")
(out_dir / "backend-endpoints.md").write_text("".join(endpoints), encoding="utf-8")
routes = ["# Frontend Routes And Views\n\n", "## Views\n\n", bullet(data["views"], 400), "\n## Route-like Literals\n\n"]
if data["vue_routes"]:
routes.append("| File | Line | Key | Value |\n| --- | ---: | --- | --- |\n")
for item in data["vue_routes"][:1000]:
routes.append(f"| `{item['file']}` | {item['line']} | `{item['key']}` | `{item['value']}` |\n")
if len(data["vue_routes"]) > 1000:
routes.append(f"\nTruncated: {len(data['vue_routes']) - 1000} more route-like literals.\n")
else:
routes.append("No route-like literals found.\n")
(out_dir / "frontend-routes.md").write_text("".join(routes), encoding="utf-8")
configs = ["# Config Reference\n\n", bullet(data["configs"], 500)]
(out_dir / "config-reference.md").write_text("".join(configs), encoding="utf-8")
tables = ["# Database Dictionary\n\n"]
if data["sql_tables"]:
tables.append("| Table | Source |\n| --- | --- |\n")
for item in sorted(data["sql_tables"], key=lambda x: (x["table"], x["file"])):
tables.append(f"| `{item['table']}` | `{item['file']}` |\n")
else:
tables.append("No SQL CREATE TABLE statements found in scanned files.\n")
(out_dir / "database-dictionary.md").write_text("".join(tables), encoding="utf-8")
perms = ["# Permission Codes\n\n"]
if data["permission_codes"]:
perms.append("| File | Line | Value |\n| --- | ---: | --- |\n")
for item in data["permission_codes"]:
permission_value = item["value"].replace("|", "\\|")
perms.append(f"| `{item['file']}` | {item['line']} | `{permission_value}` |\n")
else:
perms.append("No permission annotations found.\n")
(out_dir / "permission-codes.md").write_text("".join(perms), encoding="utf-8")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", default=".", help="Repository root to scan")
parser.add_argument("--out", required=True, help="Output directory for generated Markdown")
parser.add_argument("--json", action="store_true", help="Also write inventory.json")
parser.add_argument("--max-files", type=int, default=30000, help="Maximum files to scan")
args = parser.parse_args()
root = Path(args.root).resolve()
out_dir = Path(args.out).resolve()
data = scan(root, args.max_files)
write_md(data, out_dir)
if args.json:
(out_dir / "inventory.json").write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"Wrote project inventory to {out_dir}")
return 0
if __name__ == "__main__":
raise SystemExit(main())