Compare commits
5 Commits
5b1ca45fa5
...
b2eb475a6d
| Author | SHA1 | Date |
|---|---|---|
|
|
b2eb475a6d | |
|
|
fc230b7ff9 | |
|
|
8dc8924cbe | |
|
|
2045dd45c0 | |
|
|
872d8cf98b |
|
|
@ -137,6 +137,7 @@ jobs:
|
|||
}
|
||||
|
||||
run_bats "sync_standards" "test_sync_standards.bats"
|
||||
run_bats "sync_templates" "test_sync_templates.bats"
|
||||
run_bats "vendor_playbook" "test_vendor_playbook.bats"
|
||||
run_bats "install_codex_skills" "test_install_codex_skills.bats"
|
||||
|
||||
|
|
@ -171,6 +172,7 @@ jobs:
|
|||
run_validator "python" "validate_python_templates.sh"
|
||||
run_validator "cpp" "validate_cpp_templates.sh"
|
||||
run_validator "ci" "validate_ci_templates.sh"
|
||||
run_validator "project_templates" "validate_project_templates.sh"
|
||||
|
||||
echo "========================================"
|
||||
echo "🔗 集成测试"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"proseWrap": "preserve",
|
||||
"embeddedLanguageFormatting": "off"
|
||||
}
|
||||
12
AGENTS.md
12
AGENTS.md
|
|
@ -60,7 +60,7 @@ Do not load the whole directory. Load only the needed fragments.
|
|||
|
||||
### Scenario 1: write a simple TSL function
|
||||
|
||||
```
|
||||
```text
|
||||
1. Auto read .agents/tsl/index.md (47 lines)
|
||||
2. Trigger $tsl-guide, load SKILL.md (192 lines)
|
||||
3. Generate code
|
||||
|
|
@ -70,7 +70,7 @@ Token cost: ~6,000 tokens
|
|||
|
||||
### Scenario 2: write a TSL class
|
||||
|
||||
```
|
||||
```text
|
||||
1. Auto read .agents/tsl/index.md (47 lines)
|
||||
2. Trigger $tsl-guide, load SKILL.md + references/advanced.md
|
||||
3. Generate code
|
||||
|
|
@ -80,7 +80,7 @@ Token cost: ~10,000 tokens
|
|||
|
||||
### Scenario 3: find a TSL function library entry
|
||||
|
||||
```
|
||||
```text
|
||||
1. Auto read .agents/tsl/index.md (47 lines)
|
||||
2. Trigger $tsl-guide, load references/functions_index.md
|
||||
3. Use rg to locate the function fragment
|
||||
|
|
@ -94,7 +94,7 @@ Token cost: ~8,000 tokens
|
|||
## Performance metrics
|
||||
|
||||
| Metric | Before | Now | Improvement |
|
||||
| ----------------- | -------- | ------- | ----------- |
|
||||
| ------------------- | ---------- | --------- | ----------- |
|
||||
| .agents size | ~500 lines | 168 lines | -66% |
|
||||
| Persistent tokens | ~12,500 | ~4,200 | -66% |
|
||||
| Avg scenario tokens | ~12,500 | ~10,500 | -16% |
|
||||
|
|
@ -131,14 +131,14 @@ Do:
|
|||
|
||||
Q: Why is .agents/ so small?
|
||||
A: Because it is loaded every conversation. Keeping it under 50 lines saves
|
||||
about 71% of persistent token usage.
|
||||
about 71% of persistent token usage.
|
||||
|
||||
Q: Why does TSL need a dedicated tsl-guide skill?
|
||||
A: TSL is not pre-trained. The agent needs from-scratch teaching.
|
||||
|
||||
Q: What if my project has custom conventions?
|
||||
A: Fork playbook into the project (git subtree) and modify the project's
|
||||
`.agents/`.
|
||||
`.agents/`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
34
README.md
34
README.md
|
|
@ -41,6 +41,39 @@ Playbook:TSL(`.tsl`/`.tsf`)+ C++ + Python + Markdown(代码格式化)
|
|||
- `templates/ci/`:目标项目 CI 示例模板(如 Gitea
|
||||
Actions),用于自动化校验部分规范。
|
||||
|
||||
## templates/(项目架构模板)
|
||||
|
||||
`templates/` 目录除了语言配置模板外,还包含 AI 代理工作环境的项目架构模板:
|
||||
|
||||
- `templates/memory-bank/`:项目上下文文档模板(project-brief、tech-stack、architecture、progress、decisions、implementation-plan)
|
||||
- `templates/prompts/`:工作流程模板(agent-behavior、clarify、verify)
|
||||
- `templates/AGENTS.template.md`:路由中心模板(项目主入口)
|
||||
- `templates/AGENT_RULES.template.md`:执行流程模板
|
||||
|
||||
### 快速部署
|
||||
|
||||
使用 `sync_templates` 脚本一键部署项目架构:
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
sh scripts/sync_templates.sh /path/to/project
|
||||
|
||||
# PowerShell
|
||||
.\scripts\sync_templates.ps1 -ProjectRoot C:\path\to\project
|
||||
|
||||
# Windows CMD
|
||||
scripts\sync_templates.bat C:\path\to\project
|
||||
```
|
||||
|
||||
**部署行为**:
|
||||
|
||||
- **新项目**:创建完整的 `AGENTS.md`、`AGENT_RULES.md`、`memory-bank/`、`docs/prompts/`、`TODO.md`、`CONFIRM.md`
|
||||
- **已有 AGENTS.md**:追加路由链接(使用 `<!-- playbook:templates:start/end -->` 标记)
|
||||
- **--full 参数**:追加完整框架(规则优先级 + 新会话开始时)到已有 AGENTS.md
|
||||
- **其他文件**:如果已存在则跳过(使用 `--force` 覆盖)
|
||||
|
||||
详见:`templates/README.md`
|
||||
|
||||
## rulesets/(规则集模板库 - 三层架构)
|
||||
|
||||
> **重要说明**:playbook 仓库中的 `rulesets/` 是**规则集模板库**,不是 playbook 项目自身的代理规则。
|
||||
|
|
@ -187,6 +220,7 @@ git commit -m ":package: deps(playbook): add tsl standards"
|
|||
> 会自动生成最小版;已存在则不会覆盖。
|
||||
|
||||
3. **验收**(任意满足其一即可):
|
||||
|
||||
- 目录存在:`.agents/tsl/`
|
||||
- 规则入口可读:`.agents/tsl/index.md`
|
||||
- (可选)C++ 规则入口可读:`.agents/cpp/index.md`
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ sh docs/standards/playbook/scripts/install_codex_skills.sh
|
|||
### 通用工作流 Skills
|
||||
|
||||
- **`testing-workflow`**:跨语言测试策略
|
||||
|
||||
- 适用:TSL / Python / C++
|
||||
- 覆盖:单元测试 / 集成测试 / 回归测试
|
||||
- 108 行
|
||||
|
|
|
|||
|
|
@ -24,19 +24,23 @@ description:
|
|||
## Procedure(default)
|
||||
|
||||
1. **Baseline**
|
||||
|
||||
- 确保工作区干净:`git status --porcelain`
|
||||
- 跑一个基线验证(至少 build 或核心测试子集),避免“本来就坏”
|
||||
|
||||
2. **Enumerate**
|
||||
|
||||
- 先搜索再改:用 `rg`/`git grep` 列出全部命中
|
||||
- 分类命中:真实调用 vs 注释/文档/样例;避免误改
|
||||
|
||||
3. **Apply Mechanical Change**
|
||||
|
||||
- 优先使用确定性的机械变换(脚本/结构化编辑)而非手工逐个改
|
||||
- 每轮改动后立即做小验证(编译/单测子集)
|
||||
- 复杂迁移优先“两阶段”:先兼容旧接口(deprecated),再清理旧接口
|
||||
|
||||
4. **Format & Lint(按项目约定)**
|
||||
|
||||
- 仅在确认“会破坏 diff 可读性”前提下分批格式化(避免把重构和格式揉在一起)
|
||||
|
||||
5. **Verify & Report**
|
||||
|
|
|
|||
|
|
@ -23,22 +23,27 @@ description:
|
|||
## Procedure
|
||||
|
||||
1. **Triage**
|
||||
|
||||
- Identify touched areas, public APIs, behavior changes, data/auth paths
|
||||
- Classify risk (blast radius, rollback difficulty)
|
||||
|
||||
2. **Correctness**
|
||||
|
||||
- Invariants, edge cases, error handling, null/empty, concurrency
|
||||
- Backward compatibility (inputs/outputs, wire formats, config)
|
||||
|
||||
3. **Security**
|
||||
|
||||
- AuthZ/AuthN boundaries, least privilege
|
||||
- Input validation, injection surfaces, secrets/log redaction
|
||||
|
||||
4. **Maintainability**
|
||||
|
||||
- Naming/structure/style aligned with Playbook docs
|
||||
- Complexity hotspots, duplication, clarity of intent
|
||||
|
||||
5. **Performance**
|
||||
|
||||
- Hot paths, algorithmic complexity, allocations/IO, N+1 patterns
|
||||
|
||||
6. **Tests & Verification**
|
||||
|
|
|
|||
|
|
@ -25,22 +25,27 @@ diff)生成 1–3 条提交信息建议:`:emoji: type(scope): subject`(可
|
|||
## Procedure(default)
|
||||
|
||||
1. **收集 staged 概览(尽量小上下文)**
|
||||
|
||||
- `git diff --cached --name-status`
|
||||
- `git diff --cached --stat`
|
||||
- 必要时只看关键文件:`git diff --cached -- <path>`
|
||||
|
||||
2. **读取并遵循权威规范**
|
||||
|
||||
- 优先读取就近的
|
||||
`commit_message.md`(见上方路径),以其中的 type/emoji/格式为准。
|
||||
|
||||
3. **生成 1 条主建议 + 2 条备选**
|
||||
|
||||
- 格式固定:`:emoji: type(scope): subject`(scope 可省略)。
|
||||
- subject 用一句话描述“做了什么”,避免含糊词;尽量 ≤ 72 字符,不加句号。
|
||||
|
||||
4. **判断是否建议拆分提交**
|
||||
|
||||
- 当 staged 同时包含多个不相关模块/目的时:建议拆分,并给出拆分方式(按目录/功能点/风险)。
|
||||
|
||||
5. **可选:补充 body/footer(如需要)**
|
||||
|
||||
- body:说明 why/impact/verify(按规范建议换行)。
|
||||
- footer:任务号或 `BREAKING CHANGE:`(若有)。
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Throughout the entire workflow, operate in read-only mode. Do not write or
|
|||
update files.
|
||||
|
||||
1. **Scan context quickly**
|
||||
|
||||
- Read `README.md` and any obvious docs (`docs/`, `CONTRIBUTING.md`,
|
||||
`ARCHITECTURE.md`).
|
||||
- Skim relevant files (the ones most likely touched).
|
||||
|
|
@ -27,12 +28,14 @@ update files.
|
|||
shape).
|
||||
|
||||
2. **Ask follow-ups only if blocking**
|
||||
|
||||
- Ask **at most 1–2 questions**.
|
||||
- Only ask if you cannot responsibly plan without the answer; prefer
|
||||
multiple-choice.
|
||||
- If unsure but not blocked, make a reasonable assumption and proceed.
|
||||
|
||||
3. **Create a plan using the template below**
|
||||
|
||||
- Start with **1 short paragraph** describing the intent and approach.
|
||||
- Clearly call out what is **in scope** and what is **not in scope** in
|
||||
short.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ description:
|
|||
## Procedure(default)
|
||||
|
||||
1. **Baseline**
|
||||
|
||||
- 记录当前状态:`git status --porcelain`
|
||||
- 明确范围(默认只处理变更文件):
|
||||
- staged:`git diff --name-only --cached`
|
||||
|
|
@ -30,6 +31,7 @@ description:
|
|||
- untracked:`git ls-files -o --exclude-standard`
|
||||
|
||||
2. **Detect Toolchain(prefer repo truth)**
|
||||
|
||||
- 优先用仓库既有入口脚本 / 配置:
|
||||
- JS/TS:`package.json`
|
||||
scripts(`format`/`lint`/`lint:fix`)、prettier/biome/eslint 配置
|
||||
|
|
@ -41,6 +43,7 @@ description:
|
|||
- 禁止默认“引入新 formatter/linter 配置”;缺配置时只做最小手工调整,并先确认是否允许落地配置文件。
|
||||
|
||||
3. **Apply(format first, then lint)**
|
||||
|
||||
- 先 formatter(会改文件),再 lint(检查),再 lint
|
||||
--fix(如有),最后再跑一次 check 确认干净。
|
||||
- 默认只处理目标文件集合;避免全仓库 reformat(除非用户明确要求)。
|
||||
|
|
@ -52,6 +55,7 @@ description:
|
|||
`npx prettier -w <files...>`(以项目脚本为准)
|
||||
|
||||
4. **Guardrails**
|
||||
|
||||
- 只做风格与格式:不改变行为、不改 public API、不做重构。
|
||||
- 如格式化导致 diff 暴涨(文件数/行数过大):先停下,给出原因与两种方案让用户选:
|
||||
1. 仅格式化本次改动文件(推荐默认)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
# TSL 函数库分类索引
|
||||
|
||||
> **说明**:本文档是 `$tsl-guide` 的子文档,仅提供分类索引与检索策略。
|
||||
> **权威入口**:`docs/tsl/syntax_book/function/tsl/index.md`
|
||||
> **注意**:函数库已拆分为 `docs/tsl/syntax_book/function/` 多文件,禁止整目录加载。
|
||||
> **权威入口**:`docs/tsl/syntax_book/function/tsl/index.md` > **注意**:函数库已拆分为 `docs/tsl/syntax_book/function/` 多文件,禁止整目录加载。
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
## 格式化工具
|
||||
|
||||
- 优先使用仓库已固定的工具配置
|
||||
- 若存在 Prettier 配置,使用项目脚本或 `npx prettier -w <files...>`
|
||||
- 优先使用 Prettier(仓库已固定配置/脚本)
|
||||
- 若存在项目脚本,优先使用 `npm run format:md`;否则可用 `npx prettier -w <files...>`
|
||||
- 不引入新的 Markdown 格式化工具
|
||||
|
||||
## 关联规则
|
||||
|
|
|
|||
|
|
@ -31,10 +31,12 @@
|
|||
### 财务与基本面
|
||||
|
||||
- **[财务分析](./financial_analysis.md)** (46,778行) ⚠️ **最大文件**
|
||||
|
||||
- 资产负债表、利润表、现金流量表
|
||||
- 财务比率、财务指标、财务预测
|
||||
|
||||
- **[基本面](./fundamentals.md)** (6,139行)
|
||||
|
||||
- 公司基本信息、行业分类、股东结构
|
||||
- 分红、配股、增发等公司行为
|
||||
|
||||
|
|
@ -49,10 +51,12 @@
|
|||
### 量化分析
|
||||
|
||||
- **[金融工程](./financial_engineering.md)** (6,564行)
|
||||
|
||||
- 风险模型、因子模型、组合优化
|
||||
- 回测框架、绩效归因
|
||||
|
||||
- **[组合评价](./portfolio_evaluation.md)** (3,656行)
|
||||
|
||||
- 夏普比率、最大回撤、收益波动
|
||||
- 组合绩效评估、风险调整收益
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ TSL函数包含数学、系统、基础、图形等通用函数,适用于各
|
|||
### 系统与平台
|
||||
|
||||
- **[系统相关函数](./system.md)** (1,647行)
|
||||
|
||||
- 系统信息、环境变量、进程控制
|
||||
- 内存管理、性能监控
|
||||
|
||||
- **[平台函数](./platform.md)** (553行)
|
||||
|
||||
- 平台特定功能、系统调用
|
||||
|
||||
- **[客户端函数](./client.md)** (409行)
|
||||
|
|
@ -28,6 +30,7 @@ TSL函数包含数学、系统、基础、图形等通用函数,适用于各
|
|||
### 基础功能
|
||||
|
||||
- **[基础函数](./base.md)** (10,660行)
|
||||
|
||||
- 字符串处理、数组操作、日期时间
|
||||
- 类型转换、条件判断、数据结构
|
||||
- 文件操作、流程控制
|
||||
|
|
@ -38,6 +41,7 @@ TSL函数包含数学、系统、基础、图形等通用函数,适用于各
|
|||
### 资源与交互
|
||||
|
||||
- **[资源访问函数](./resource.md)** (4,897行)
|
||||
|
||||
- 文件读写、数据库访问、网络通信
|
||||
- 配置文件、资源管理
|
||||
|
||||
|
|
@ -47,6 +51,7 @@ TSL函数包含数学、系统、基础、图形等通用函数,适用于各
|
|||
### 工具函数
|
||||
|
||||
- **[压缩和解压函数](./compression.md)** (108行)
|
||||
|
||||
- 数据压缩、解压缩、归档
|
||||
|
||||
- **[信息摘要及编码](./digest_encoding.md)** (172行)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "playbook",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"prettier": "3.2.5"
|
||||
},
|
||||
"scripts": {
|
||||
"format:md": "prettier -w \"**/*.md\""
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
### 工具
|
||||
|
||||
- 优先使用仓库既有的格式化工具(如 Prettier)
|
||||
- 优先使用 Prettier(仓库已固定配置/脚本)
|
||||
- 不引入新的 Markdown 格式化依赖
|
||||
|
||||
### 行内代码
|
||||
|
|
|
|||
|
|
@ -0,0 +1,257 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem Sync project templates to target project.
|
||||
rem - Copies templates/memory-bank/ -> <project-root>/memory-bank/
|
||||
rem - Copies templates/prompts/ -> <project-root>/docs/prompts/
|
||||
rem - Copies templates/AGENTS.template.md -> <project-root>/AGENTS.md
|
||||
rem - Copies templates/AGENT_RULES.template.md -> <project-root>/AGENT_RULES.md
|
||||
rem Existing targets are NOT overwritten (skip if exists).
|
||||
rem
|
||||
rem Usage:
|
||||
rem sync_templates.bat # sync to current git root
|
||||
rem sync_templates.bat <project-root> # sync to specified project
|
||||
rem sync_templates.bat --force # overwrite existing files
|
||||
rem sync_templates.bat --full # append full framework to existing AGENTS.md
|
||||
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
for %%I in ("%SCRIPT_DIR%..") do set "SRC=%%~fI"
|
||||
|
||||
set "FORCE=0"
|
||||
set "FULL=0"
|
||||
set "PROJECT_ROOT="
|
||||
|
||||
:parse_args
|
||||
if "%~1"=="" goto args_done
|
||||
if /I "%~1"=="--force" (
|
||||
set "FORCE=1"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--full" (
|
||||
set "FULL=1"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="-h" goto show_help
|
||||
if /I "%~1"=="--help" goto show_help
|
||||
set "PROJECT_ROOT=%~1"
|
||||
shift
|
||||
goto parse_args
|
||||
|
||||
:show_help
|
||||
echo Usage:
|
||||
echo sync_templates.bat [options] [project-root]
|
||||
echo.
|
||||
echo Options:
|
||||
echo --force Overwrite existing files
|
||||
echo --full Append full framework (规则优先级 + 新会话开始时) to existing AGENTS.md
|
||||
echo -h, --help Show this help
|
||||
exit /b 0
|
||||
|
||||
:args_done
|
||||
|
||||
rem Determine project root
|
||||
if "%PROJECT_ROOT%"=="" (
|
||||
for /f "delims=" %%R in ('git -C "%SCRIPT_DIR%" rev-parse --show-toplevel 2^>nul') do set "PROJECT_ROOT=%%R"
|
||||
)
|
||||
if "%PROJECT_ROOT%"=="" set "PROJECT_ROOT=%cd%"
|
||||
for %%I in ("%PROJECT_ROOT%") do set "PROJECT_ROOT=%%~fI"
|
||||
|
||||
rem Source directories
|
||||
set "TEMPLATES_DIR=%SRC%\templates"
|
||||
set "MEMORY_BANK_SRC=%TEMPLATES_DIR%\memory-bank"
|
||||
set "PROMPTS_SRC=%TEMPLATES_DIR%\prompts"
|
||||
set "AGENTS_SRC=%TEMPLATES_DIR%\AGENTS.template.md"
|
||||
set "AGENT_RULES_SRC=%TEMPLATES_DIR%\AGENT_RULES.template.md"
|
||||
|
||||
rem Check source exists
|
||||
if not exist "%TEMPLATES_DIR%" (
|
||||
echo ERROR: Templates directory not found: %TEMPLATES_DIR%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
rem Skip if source equals destination
|
||||
if /I "%SRC%"=="%PROJECT_ROOT%" (
|
||||
echo Skip: playbook root equals project root.
|
||||
echo Done.
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
for /f "usebackq delims=" %%D in (`powershell -NoProfile -Command "Get-Date -Format 'yyyy-MM-dd'"`) do set "SYNC_DATE=%%D"
|
||||
if "%SYNC_DATE%"=="" set "SYNC_DATE=%date%"
|
||||
|
||||
echo Syncing templates to: %PROJECT_ROOT%
|
||||
echo.
|
||||
|
||||
rem 1. Sync memory-bank/
|
||||
set "MEMORY_BANK_DST=%PROJECT_ROOT%\memory-bank"
|
||||
if exist "%MEMORY_BANK_SRC%" (
|
||||
if exist "%MEMORY_BANK_DST%" (
|
||||
if "%FORCE%"=="0" (
|
||||
echo memory-bank/ already exists. Skip. Use --force to overwrite.
|
||||
goto sync_prompts
|
||||
)
|
||||
)
|
||||
if not exist "%MEMORY_BANK_DST%" mkdir "%MEMORY_BANK_DST%"
|
||||
xcopy "%MEMORY_BANK_SRC%\*" "%MEMORY_BANK_DST%\" /e /i /y >nul 2>nul
|
||||
|
||||
rem Rename .template.md to .md
|
||||
for %%F in ("%MEMORY_BANK_DST%\*.template.md") do (
|
||||
set "OLDNAME=%%~nxF"
|
||||
set "NEWNAME=!OLDNAME:.template.md=.md!"
|
||||
ren "%%F" "!NEWNAME!"
|
||||
)
|
||||
|
||||
rem Replace {{DATE}} placeholder
|
||||
for %%F in ("%MEMORY_BANK_DST%\*.md") do (
|
||||
powershell -NoProfile -Command "$f='%%~fF'; $c=Get-Content -Raw $f; $c=$c.Replace('{{DATE}}','%SYNC_DATE%'); Set-Content -Path $f -Value $c -Encoding UTF8 -NoNewline"
|
||||
)
|
||||
echo Synced: memory-bank/
|
||||
) else (
|
||||
echo Skip: memory-bank/ templates not found
|
||||
)
|
||||
|
||||
:sync_prompts
|
||||
rem 2. Sync docs/prompts/
|
||||
set "PROMPTS_DST=%PROJECT_ROOT%\docs\prompts"
|
||||
if exist "%PROMPTS_SRC%" (
|
||||
if exist "%PROMPTS_DST%" (
|
||||
if "%FORCE%"=="0" (
|
||||
echo docs/prompts/ already exists. Skip. Use --force to overwrite.
|
||||
goto sync_agents
|
||||
)
|
||||
)
|
||||
if not exist "%PROJECT_ROOT%\docs" mkdir "%PROJECT_ROOT%\docs"
|
||||
if not exist "%PROMPTS_DST%" mkdir "%PROMPTS_DST%"
|
||||
xcopy "%PROMPTS_SRC%\*" "%PROMPTS_DST%\" /e /i /y >nul 2>nul
|
||||
|
||||
rem Rename .template.md to .md recursively
|
||||
for /r "%PROMPTS_DST%" %%F in (*.template.md) do (
|
||||
set "OLDNAME=%%~nxF"
|
||||
set "NEWNAME=!OLDNAME:.template.md=.md!"
|
||||
ren "%%F" "!NEWNAME!"
|
||||
)
|
||||
|
||||
rem Replace {{DATE}} placeholder
|
||||
for /r "%PROMPTS_DST%" %%F in (*.md) do (
|
||||
powershell -NoProfile -Command "$f='%%~fF'; $c=Get-Content -Raw $f; $c=$c.Replace('{{DATE}}','%SYNC_DATE%'); Set-Content -Path $f -Value $c -Encoding UTF8 -NoNewline"
|
||||
)
|
||||
echo Synced: docs/prompts/
|
||||
) else (
|
||||
echo Skip: prompts/ templates not found
|
||||
)
|
||||
|
||||
:sync_agents
|
||||
rem 3. Sync AGENTS.md
|
||||
set "AGENTS_DST=%PROJECT_ROOT%\AGENTS.md"
|
||||
|
||||
rem Choose markers based on --full flag
|
||||
if "%FULL%"=="1" (
|
||||
set "MARKER_START=<!-- playbook:framework:start -->"
|
||||
set "MARKER_END=<!-- playbook:framework:end -->"
|
||||
set "SECTION_NAME=framework"
|
||||
) else (
|
||||
set "MARKER_START=<!-- playbook:templates:start -->"
|
||||
set "MARKER_END=<!-- playbook:templates:end -->"
|
||||
set "SECTION_NAME=templates"
|
||||
)
|
||||
|
||||
if exist "%AGENTS_SRC%" (
|
||||
if not exist "%AGENTS_DST%" (
|
||||
rem AGENTS.md doesn't exist: create from full template
|
||||
copy /y "%AGENTS_SRC%" "%AGENTS_DST%" >nul
|
||||
powershell -NoProfile -Command "$f='%AGENTS_DST%'; $c=Get-Content -Raw $f; $c=$c.Replace('{{DATE}}','%SYNC_DATE%'); Set-Content -Path $f -Value $c -Encoding UTF8 -NoNewline"
|
||||
echo Created: AGENTS.md
|
||||
) else (
|
||||
rem AGENTS.md exists: update or append section (extract from template)
|
||||
powershell -NoProfile -Command ^
|
||||
"$src='%AGENTS_SRC%'; $dst='%AGENTS_DST%'; $date='%SYNC_DATE%'; " ^
|
||||
"$markerStart='!MARKER_START!'; $markerEnd='!MARKER_END!'; $sectionName='!SECTION_NAME!'; " ^
|
||||
"$templateContent = Get-Content -Raw $src; " ^
|
||||
"$extractPattern = '(?s)(' + [regex]::Escape($markerStart) + '.*?' + [regex]::Escape($markerEnd) + ')'; " ^
|
||||
"if ($templateContent -match $extractPattern) { " ^
|
||||
" $snippetContent = $Matches[1]; " ^
|
||||
" $content = Get-Content -Raw $dst; " ^
|
||||
" if ($content -match [regex]::Escape($markerStart)) { " ^
|
||||
" $replacePattern = '(?s)' + [regex]::Escape($markerStart) + '.*?' + [regex]::Escape($markerEnd); " ^
|
||||
" $newContent = $content -replace $replacePattern, $snippetContent; " ^
|
||||
" $newContent = $newContent.Replace('{{DATE}}', $date); " ^
|
||||
" Set-Content -Path $dst -Value $newContent -Encoding UTF8 -NoNewline; " ^
|
||||
" Write-Host \"Updated: AGENTS.md ($sectionName section)\"; " ^
|
||||
" } else { " ^
|
||||
" $newContent = $content.TrimEnd() + \"`n`n\" + $snippetContent; " ^
|
||||
" $newContent = $newContent.Replace('{{DATE}}', $date); " ^
|
||||
" Set-Content -Path $dst -Value $newContent -Encoding UTF8 -NoNewline; " ^
|
||||
" Write-Host \"Appended: AGENTS.md ($sectionName section)\"; " ^
|
||||
" } " ^
|
||||
"} else { " ^
|
||||
" Write-Host 'Skip: markers not found in template'; " ^
|
||||
"}"
|
||||
)
|
||||
) else (
|
||||
echo Skip: AGENTS.template.md not found
|
||||
)
|
||||
|
||||
:sync_agent_rules
|
||||
rem 4. Sync AGENT_RULES.md
|
||||
set "AGENT_RULES_DST=%PROJECT_ROOT%\AGENT_RULES.md"
|
||||
if exist "%AGENT_RULES_SRC%" (
|
||||
if exist "%AGENT_RULES_DST%" (
|
||||
if "%FORCE%"=="0" (
|
||||
echo AGENT_RULES.md already exists. Skip. Use --force to overwrite.
|
||||
goto sync_todo
|
||||
)
|
||||
)
|
||||
copy /y "%AGENT_RULES_SRC%" "%AGENT_RULES_DST%" >nul
|
||||
powershell -NoProfile -Command "$f='%AGENT_RULES_DST%'; $c=Get-Content -Raw $f; $c=$c.Replace('{{DATE}}','%SYNC_DATE%'); Set-Content -Path $f -Value $c -Encoding UTF8 -NoNewline"
|
||||
echo Synced: AGENT_RULES.md
|
||||
) else (
|
||||
echo Skip: AGENT_RULES.template.md not found
|
||||
)
|
||||
|
||||
:sync_todo
|
||||
rem 5. Create TODO.md if not exist
|
||||
set "TODO_DST=%PROJECT_ROOT%\TODO.md"
|
||||
if not exist "%TODO_DST%" (
|
||||
> "%TODO_DST%" echo # TODO
|
||||
>> "%TODO_DST%" echo.
|
||||
>> "%TODO_DST%" echo ## Plan 1: [计划名称]
|
||||
>> "%TODO_DST%" echo.
|
||||
>> "%TODO_DST%" echo - [ ] 任务 1
|
||||
>> "%TODO_DST%" echo - [ ] 任务 2
|
||||
>> "%TODO_DST%" echo.
|
||||
>> "%TODO_DST%" echo ---
|
||||
>> "%TODO_DST%" echo.
|
||||
>> "%TODO_DST%" echo **最后更新**:%SYNC_DATE%
|
||||
echo Created: TODO.md
|
||||
)
|
||||
|
||||
rem 6. Create CONFIRM.md if not exist
|
||||
set "CONFIRM_DST=%PROJECT_ROOT%\CONFIRM.md"
|
||||
if not exist "%CONFIRM_DST%" (
|
||||
> "%CONFIRM_DST%" echo # 待确认事项
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo ## 待确认
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo ^<!-- 记录需要确认的事项 --^>
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo ## 已确认
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo ^<!-- 已确认的事项移到这里 --^>
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo ---
|
||||
>> "%CONFIRM_DST%" echo.
|
||||
>> "%CONFIRM_DST%" echo **最后更新**:%SYNC_DATE%
|
||||
echo Created: CONFIRM.md
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Done.
|
||||
echo.
|
||||
echo Next steps:
|
||||
echo 1. Edit memory-bank\*.md to fill in project-specific content
|
||||
echo 2. Replace remaining {{PLACEHOLDER}} values
|
||||
echo 3. Run sync_standards.bat to sync .agents\ rules
|
||||
|
||||
endlocal
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
# Sync project templates to target project.
|
||||
# - Copies templates/memory-bank/ -> <project-root>/memory-bank/
|
||||
# - Copies templates/prompts/ -> <project-root>/docs/prompts/
|
||||
# - Copies templates/AGENTS.template.md -> <project-root>/AGENTS.md
|
||||
# - Copies templates/AGENT_RULES.template.md -> <project-root>/AGENT_RULES.md
|
||||
# Existing targets are backed up before overwrite.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $false, Position = 0)]
|
||||
[string]$ProjectRoot,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ProjectName,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$Date,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$NoBackup,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$Force,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$Full
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$Src = (Resolve-Path (Join-Path $ScriptDir "..")).Path
|
||||
|
||||
# Defaults
|
||||
if (-not $Date) {
|
||||
$Date = Get-Date -Format "yyyy-MM-dd"
|
||||
}
|
||||
|
||||
# Determine project root
|
||||
if (-not $ProjectRoot) {
|
||||
$ProjectRoot = (git -C $ScriptDir rev-parse --show-toplevel 2>$null)
|
||||
if (-not $ProjectRoot) { $ProjectRoot = (Get-Location).Path }
|
||||
}
|
||||
$ProjectRoot = (Resolve-Path $ProjectRoot).Path
|
||||
|
||||
# Source directories
|
||||
$TemplatesDir = Join-Path $Src "templates"
|
||||
$MemoryBankSrc = Join-Path $TemplatesDir "memory-bank"
|
||||
$PromptsSrc = Join-Path $TemplatesDir "prompts"
|
||||
$AgentsSrc = Join-Path $TemplatesDir "AGENTS.template.md"
|
||||
$AgentRulesSrc = Join-Path $TemplatesDir "AGENT_RULES.template.md"
|
||||
|
||||
# Check source exists
|
||||
if (-not (Test-Path $TemplatesDir)) {
|
||||
throw "Templates directory not found: $TemplatesDir"
|
||||
}
|
||||
|
||||
# Skip if source equals destination
|
||||
if ($Src -ieq $ProjectRoot) {
|
||||
Write-Host "Skip: playbook root equals project root."
|
||||
Write-Host "Done."
|
||||
exit 0
|
||||
}
|
||||
|
||||
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
|
||||
|
||||
# Function: backup file/directory
|
||||
function Backup-IfExists {
|
||||
param([string]$Target)
|
||||
|
||||
if ((Test-Path $Target) -and -not $NoBackup) {
|
||||
$backup = "$Target.bak.$timestamp"
|
||||
Move-Item $Target $backup
|
||||
Write-Host "Backed up: $(Split-Path -Leaf $Target) -> $(Split-Path -Leaf $backup)"
|
||||
}
|
||||
}
|
||||
|
||||
# Function: replace placeholders in file
|
||||
function Replace-Placeholders {
|
||||
param([string]$File)
|
||||
|
||||
if (-not (Test-Path $File)) { return }
|
||||
|
||||
$content = Get-Content -Raw -Path $File
|
||||
if ($ProjectName) {
|
||||
$content = $content.Replace("{{PROJECT_NAME}}", $ProjectName)
|
||||
}
|
||||
$content = $content.Replace("{{DATE}}", $Date)
|
||||
Set-Content -Path $File -Value $content -Encoding UTF8 -NoNewline
|
||||
}
|
||||
|
||||
# Function: replace placeholders in directory
|
||||
function Replace-PlaceholdersDir {
|
||||
param([string]$Dir)
|
||||
|
||||
if (-not (Test-Path $Dir)) { return }
|
||||
|
||||
Get-ChildItem -Path $Dir -Filter "*.md" -Recurse -File | ForEach-Object {
|
||||
Replace-Placeholders -File $_.FullName
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Syncing templates to: $ProjectRoot"
|
||||
Write-Host ""
|
||||
|
||||
# 1. Sync memory-bank/
|
||||
if (Test-Path $MemoryBankSrc) {
|
||||
$MemoryBankDst = Join-Path $ProjectRoot "memory-bank"
|
||||
|
||||
if ((Test-Path $MemoryBankDst) -and -not $Force) {
|
||||
Write-Host "memory-bank/ already exists. Use -Force to overwrite."
|
||||
} else {
|
||||
Backup-IfExists -Target $MemoryBankDst
|
||||
New-Item -ItemType Directory -Path $MemoryBankDst -Force | Out-Null
|
||||
Copy-Item -Path (Join-Path $MemoryBankSrc "*") -Destination $MemoryBankDst -Recurse -Force
|
||||
|
||||
# Rename .template.md to .md
|
||||
Get-ChildItem -Path $MemoryBankDst -Filter "*.template.md" -File | ForEach-Object {
|
||||
$newName = $_.Name -replace "\.template\.md$", ".md"
|
||||
Rename-Item -Path $_.FullName -NewName $newName
|
||||
}
|
||||
|
||||
Replace-PlaceholdersDir -Dir $MemoryBankDst
|
||||
Write-Host "Synced: memory-bank/"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skip: memory-bank/ templates not found"
|
||||
}
|
||||
|
||||
# 2. Sync docs/prompts/
|
||||
if (Test-Path $PromptsSrc) {
|
||||
$PromptsDst = Join-Path $ProjectRoot "docs\prompts"
|
||||
|
||||
if ((Test-Path $PromptsDst) -and -not $Force) {
|
||||
Write-Host "docs/prompts/ already exists. Use -Force to overwrite."
|
||||
} else {
|
||||
Backup-IfExists -Target $PromptsDst
|
||||
$DocsDir = Join-Path $ProjectRoot "docs"
|
||||
New-Item -ItemType Directory -Path $DocsDir -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path $PromptsDst -Force | Out-Null
|
||||
Copy-Item -Path (Join-Path $PromptsSrc "*") -Destination $PromptsDst -Recurse -Force
|
||||
|
||||
# Rename .template.md to .md recursively
|
||||
Get-ChildItem -Path $PromptsDst -Filter "*.template.md" -Recurse -File | ForEach-Object {
|
||||
$newName = $_.Name -replace "\.template\.md$", ".md"
|
||||
Rename-Item -Path $_.FullName -NewName $newName
|
||||
}
|
||||
|
||||
Replace-PlaceholdersDir -Dir $PromptsDst
|
||||
Write-Host "Synced: docs/prompts/"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skip: prompts/ templates not found"
|
||||
}
|
||||
|
||||
# 3. Sync AGENTS.md
|
||||
# Choose markers based on -Full flag
|
||||
if ($Full) {
|
||||
$MarkerStart = "<!-- playbook:framework:start -->"
|
||||
$MarkerEnd = "<!-- playbook:framework:end -->"
|
||||
$SectionName = "framework"
|
||||
} else {
|
||||
$MarkerStart = "<!-- playbook:templates:start -->"
|
||||
$MarkerEnd = "<!-- playbook:templates:end -->"
|
||||
$SectionName = "templates"
|
||||
}
|
||||
|
||||
if (Test-Path $AgentsSrc) {
|
||||
$AgentsDst = Join-Path $ProjectRoot "AGENTS.md"
|
||||
|
||||
if (-not (Test-Path $AgentsDst)) {
|
||||
# AGENTS.md doesn't exist: create from full template
|
||||
Copy-Item -Path $AgentsSrc -Destination $AgentsDst -Force
|
||||
Replace-Placeholders -File $AgentsDst
|
||||
Write-Host "Created: AGENTS.md"
|
||||
} else {
|
||||
# AGENTS.md exists: update or append section
|
||||
# Extract snippet from template
|
||||
$templateContent = Get-Content -Raw -Path $AgentsSrc
|
||||
$extractPattern = "(?s)(" + [regex]::Escape($MarkerStart) + ".*?" + [regex]::Escape($MarkerEnd) + ")"
|
||||
if ($templateContent -match $extractPattern) {
|
||||
$snippetContent = $Matches[1]
|
||||
|
||||
$content = Get-Content -Raw -Path $AgentsDst
|
||||
|
||||
if ($content -match [regex]::Escape($MarkerStart)) {
|
||||
# Has markers: replace content between markers
|
||||
$replacePattern = "(?s)" + [regex]::Escape($MarkerStart) + ".*?" + [regex]::Escape($MarkerEnd)
|
||||
$newContent = $content -replace $replacePattern, $snippetContent
|
||||
Set-Content -Path $AgentsDst -Value $newContent -Encoding UTF8 -NoNewline
|
||||
Replace-Placeholders -File $AgentsDst
|
||||
Write-Host "Updated: AGENTS.md ($SectionName section)"
|
||||
} else {
|
||||
# No markers: append snippet at the end
|
||||
$newContent = $content.TrimEnd() + "`n`n" + $snippetContent
|
||||
Set-Content -Path $AgentsDst -Value $newContent -Encoding UTF8 -NoNewline
|
||||
Replace-Placeholders -File $AgentsDst
|
||||
Write-Host "Appended: AGENTS.md ($SectionName section)"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skip: markers not found in template"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skip: AGENTS.template.md not found"
|
||||
}
|
||||
|
||||
# 4. Sync AGENT_RULES.md
|
||||
if (Test-Path $AgentRulesSrc) {
|
||||
$AgentRulesDst = Join-Path $ProjectRoot "AGENT_RULES.md"
|
||||
|
||||
if ((Test-Path $AgentRulesDst) -and -not $Force) {
|
||||
Write-Host "AGENT_RULES.md already exists. Use -Force to overwrite."
|
||||
} else {
|
||||
Backup-IfExists -Target $AgentRulesDst
|
||||
Copy-Item -Path $AgentRulesSrc -Destination $AgentRulesDst -Force
|
||||
Replace-Placeholders -File $AgentRulesDst
|
||||
Write-Host "Synced: AGENT_RULES.md"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skip: AGENT_RULES.template.md not found"
|
||||
}
|
||||
|
||||
# 5. Create TODO.md and CONFIRM.md if not exist
|
||||
$TodoPath = Join-Path $ProjectRoot "TODO.md"
|
||||
if (-not (Test-Path $TodoPath)) {
|
||||
@"
|
||||
# TODO
|
||||
|
||||
## Plan 1: [计划名称]
|
||||
|
||||
- [ ] 任务 1
|
||||
- [ ] 任务 2
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:$Date
|
||||
"@ | Set-Content -Path $TodoPath -Encoding UTF8
|
||||
Write-Host "Created: TODO.md"
|
||||
}
|
||||
|
||||
$ConfirmPath = Join-Path $ProjectRoot "CONFIRM.md"
|
||||
if (-not (Test-Path $ConfirmPath)) {
|
||||
@"
|
||||
# 待确认事项
|
||||
|
||||
## 待确认
|
||||
|
||||
<!-- 记录需要确认的事项 -->
|
||||
|
||||
## 已确认
|
||||
|
||||
<!-- 已确认的事项移到这里 -->
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:$Date
|
||||
"@ | Set-Content -Path $ConfirmPath -Encoding UTF8
|
||||
Write-Host "Created: CONFIRM.md"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Done."
|
||||
Write-Host ""
|
||||
Write-Host "Next steps:"
|
||||
Write-Host " 1. Edit memory-bank/*.md to fill in project-specific content"
|
||||
Write-Host " 2. Replace remaining {{PLACEHOLDER}} values"
|
||||
Write-Host " 3. Run sync_standards.ps1 to sync .agents/ rules"
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
# Sync project templates to target project.
|
||||
# - Copies templates/memory-bank/ -> <project-root>/memory-bank/
|
||||
# - Copies templates/prompts/ -> <project-root>/docs/prompts/
|
||||
# - Copies templates/AGENTS.template.md -> <project-root>/AGENTS.md
|
||||
# - Copies templates/AGENT_RULES.template.md -> <project-root>/AGENT_RULES.md
|
||||
# Existing targets are backed up before overwrite.
|
||||
#
|
||||
# Usage:
|
||||
# sh scripts/sync_templates.sh # sync to current git root
|
||||
# sh scripts/sync_templates.sh <project-root> # sync to specified project
|
||||
# sh scripts/sync_templates.sh --project-name "MyProject" --date "2026-01-20"
|
||||
#
|
||||
# Options:
|
||||
# --project-name NAME Replace {{PROJECT_NAME}} placeholder
|
||||
# --date DATE Replace {{DATE}} placeholder (default: today)
|
||||
# --no-backup Skip backup of existing files
|
||||
# --force Overwrite without prompting
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"
|
||||
SRC="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd -P)"
|
||||
|
||||
# Defaults
|
||||
PROJECT_NAME=""
|
||||
SYNC_DATE="$(date +%Y-%m-%d 2>/dev/null || echo "{{DATE}}")"
|
||||
NO_BACKUP=0
|
||||
FORCE=0
|
||||
FULL=0
|
||||
PROJECT_ROOT=""
|
||||
|
||||
# Parse arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--project-name)
|
||||
PROJECT_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--date)
|
||||
SYNC_DATE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--no-backup)
|
||||
NO_BACKUP=1
|
||||
shift
|
||||
;;
|
||||
--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
--full)
|
||||
FULL=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
sh scripts/sync_templates.sh [options] [project-root]
|
||||
|
||||
Options:
|
||||
--project-name NAME Replace {{PROJECT_NAME}} placeholder
|
||||
--date DATE Replace {{DATE}} placeholder (default: today)
|
||||
--no-backup Skip backup of existing files
|
||||
--force Overwrite without prompting
|
||||
--full Append full framework (规则优先级 + 新会话开始时) to existing AGENTS.md
|
||||
-h, --help Show this help
|
||||
|
||||
Examples:
|
||||
sh scripts/sync_templates.sh
|
||||
sh scripts/sync_templates.sh /path/to/project
|
||||
sh scripts/sync_templates.sh --full /path/to/project
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "ERROR: Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
PROJECT_ROOT="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Determine project root
|
||||
if [ -z "$PROJECT_ROOT" ]; then
|
||||
PROJECT_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
fi
|
||||
PROJECT_ROOT="$(CDPATH= cd -- "$PROJECT_ROOT" && pwd -P)"
|
||||
|
||||
# Source directories
|
||||
TEMPLATES_DIR="$SRC/templates"
|
||||
MEMORY_BANK_SRC="$TEMPLATES_DIR/memory-bank"
|
||||
PROMPTS_SRC="$TEMPLATES_DIR/prompts"
|
||||
AGENTS_SRC="$TEMPLATES_DIR/AGENTS.template.md"
|
||||
AGENT_RULES_SRC="$TEMPLATES_DIR/AGENT_RULES.template.md"
|
||||
|
||||
# Check source exists
|
||||
if [ ! -d "$TEMPLATES_DIR" ]; then
|
||||
echo "ERROR: Templates directory not found: $TEMPLATES_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Skip if source equals destination (running from playbook repo itself)
|
||||
if [ "$SRC" = "$PROJECT_ROOT" ]; then
|
||||
echo "Skip: playbook root equals project root."
|
||||
echo "Done."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
timestamp="$(date +%Y%m%d%H%M%S 2>/dev/null || echo bak)"
|
||||
|
||||
# Function: backup file/directory
|
||||
backup_if_exists() {
|
||||
target="$1"
|
||||
if [ -e "$target" ] && [ "$NO_BACKUP" -eq 0 ]; then
|
||||
backup="${target}.bak.$timestamp"
|
||||
mv "$target" "$backup"
|
||||
echo "Backed up: $(basename "$target") -> $(basename "$backup")"
|
||||
fi
|
||||
}
|
||||
|
||||
escape_sed_replacement() {
|
||||
printf '%s' "$1" | sed 's/[&/|\\]/\\&/g'
|
||||
}
|
||||
|
||||
# Function: replace placeholders in file
|
||||
replace_placeholders() {
|
||||
file="$1"
|
||||
[ -f "$file" ] || return 0
|
||||
|
||||
tmp="$(mktemp 2>/dev/null || echo "$file.tmp.$timestamp")"
|
||||
date_repl="$(escape_sed_replacement "$SYNC_DATE")"
|
||||
if [ -n "$PROJECT_NAME" ]; then
|
||||
project_repl="$(escape_sed_replacement "$PROJECT_NAME")"
|
||||
sed -e "s/{{PROJECT_NAME}}/$project_repl/g" -e "s/{{DATE}}/$date_repl/g" "$file" > "$tmp"
|
||||
else
|
||||
sed -e "s/{{DATE}}/$date_repl/g" "$file" > "$tmp"
|
||||
fi
|
||||
mv "$tmp" "$file"
|
||||
}
|
||||
|
||||
# Function: replace placeholders in directory
|
||||
replace_placeholders_dir() {
|
||||
dir="$1"
|
||||
[ -d "$dir" ] || return 0
|
||||
|
||||
find "$dir" -type f -name '*.md' -print | while IFS= read -r file; do
|
||||
replace_placeholders "$file"
|
||||
done
|
||||
}
|
||||
|
||||
echo "Syncing templates to: $PROJECT_ROOT"
|
||||
echo ""
|
||||
|
||||
# 1. Sync memory-bank/
|
||||
if [ -d "$MEMORY_BANK_SRC" ]; then
|
||||
MEMORY_BANK_DST="$PROJECT_ROOT/memory-bank"
|
||||
|
||||
if [ -e "$MEMORY_BANK_DST" ] && [ "$FORCE" -eq 0 ]; then
|
||||
echo "memory-bank/ already exists. Use --force to overwrite."
|
||||
else
|
||||
backup_if_exists "$MEMORY_BANK_DST"
|
||||
mkdir -p "$MEMORY_BANK_DST"
|
||||
cp -R "$MEMORY_BANK_SRC"/* "$MEMORY_BANK_DST/" 2>/dev/null || true
|
||||
|
||||
# Rename .template.md to .md
|
||||
for f in "$MEMORY_BANK_DST"/*.template.md; do
|
||||
[ -f "$f" ] || continue
|
||||
newname="$(echo "$f" | sed 's/\.template\.md$/.md/')"
|
||||
mv "$f" "$newname"
|
||||
done
|
||||
|
||||
replace_placeholders_dir "$MEMORY_BANK_DST"
|
||||
echo "Synced: memory-bank/"
|
||||
fi
|
||||
else
|
||||
echo "Skip: memory-bank/ templates not found"
|
||||
fi
|
||||
|
||||
# 2. Sync docs/prompts/
|
||||
if [ -d "$PROMPTS_SRC" ]; then
|
||||
PROMPTS_DST="$PROJECT_ROOT/docs/prompts"
|
||||
|
||||
if [ -e "$PROMPTS_DST" ] && [ "$FORCE" -eq 0 ]; then
|
||||
echo "docs/prompts/ already exists. Use --force to overwrite."
|
||||
else
|
||||
backup_if_exists "$PROMPTS_DST"
|
||||
mkdir -p "$PROJECT_ROOT/docs"
|
||||
mkdir -p "$PROMPTS_DST"
|
||||
cp -R "$PROMPTS_SRC"/* "$PROMPTS_DST/" 2>/dev/null || true
|
||||
|
||||
# Rename .template.md to .md (recursive)
|
||||
find "$PROMPTS_DST" -type f -name '*.template.md' -print | while IFS= read -r f; do
|
||||
newname="$(echo "$f" | sed 's/\.template\.md$/.md/')"
|
||||
mv "$f" "$newname"
|
||||
done
|
||||
|
||||
replace_placeholders_dir "$PROMPTS_DST"
|
||||
echo "Synced: docs/prompts/"
|
||||
fi
|
||||
else
|
||||
echo "Skip: prompts/ templates not found"
|
||||
fi
|
||||
|
||||
# 3. Sync AGENTS.md
|
||||
# Choose markers based on --full flag
|
||||
if [ "$FULL" -eq 1 ]; then
|
||||
MARKER_START="<!-- playbook:framework:start -->"
|
||||
MARKER_END="<!-- playbook:framework:end -->"
|
||||
SECTION_NAME="framework"
|
||||
else
|
||||
MARKER_START="<!-- playbook:templates:start -->"
|
||||
MARKER_END="<!-- playbook:templates:end -->"
|
||||
SECTION_NAME="templates"
|
||||
fi
|
||||
|
||||
if [ -f "$AGENTS_SRC" ]; then
|
||||
AGENTS_DST="$PROJECT_ROOT/AGENTS.md"
|
||||
|
||||
if [ ! -e "$AGENTS_DST" ]; then
|
||||
# AGENTS.md doesn't exist: create from full template
|
||||
cp "$AGENTS_SRC" "$AGENTS_DST"
|
||||
replace_placeholders "$AGENTS_DST"
|
||||
echo "Created: AGENTS.md"
|
||||
else
|
||||
# AGENTS.md exists: update or append section
|
||||
# Extract snippet from template
|
||||
snippet_content="$(awk -v start="$MARKER_START" -v end="$MARKER_END" '
|
||||
$0 ~ start { found=1 }
|
||||
found { print }
|
||||
$0 ~ end { found=0 }
|
||||
' "$AGENTS_SRC")"
|
||||
|
||||
if [ -z "$snippet_content" ]; then
|
||||
echo "Skip: markers not found in template"
|
||||
elif grep -q "$MARKER_START" "$AGENTS_DST"; then
|
||||
# Has markers: replace content between markers in place
|
||||
snippet_tmp="$(mktemp 2>/dev/null || echo "$AGENTS_DST.snippet.$timestamp")"
|
||||
printf "%s\n" "$snippet_content" > "$snippet_tmp"
|
||||
tmp="$(mktemp 2>/dev/null || echo "$AGENTS_DST.tmp.$timestamp")"
|
||||
awk -v start="$MARKER_START" -v end="$MARKER_END" -v snippet="$snippet_tmp" '
|
||||
BEGIN {
|
||||
while ((getline line < snippet) > 0) { block[++n] = line }
|
||||
close(snippet)
|
||||
inblock = 0
|
||||
replaced = 0
|
||||
}
|
||||
{
|
||||
if (!replaced && $0 ~ start) {
|
||||
for (i=1; i<=n; i++) print block[i]
|
||||
inblock = 1
|
||||
replaced = 1
|
||||
next
|
||||
}
|
||||
if (inblock) {
|
||||
if ($0 ~ end) { inblock = 0 }
|
||||
next
|
||||
}
|
||||
print
|
||||
}
|
||||
' "$AGENTS_DST" > "$tmp"
|
||||
mv "$tmp" "$AGENTS_DST"
|
||||
rm -f "$snippet_tmp"
|
||||
replace_placeholders "$AGENTS_DST"
|
||||
echo "Updated: AGENTS.md ($SECTION_NAME section)"
|
||||
else
|
||||
# No markers: append snippet at the end
|
||||
echo "" >> "$AGENTS_DST"
|
||||
echo "$snippet_content" >> "$AGENTS_DST"
|
||||
replace_placeholders "$AGENTS_DST"
|
||||
echo "Appended: AGENTS.md ($SECTION_NAME section)"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Skip: AGENTS.template.md not found"
|
||||
fi
|
||||
|
||||
# 4. Sync AGENT_RULES.md
|
||||
if [ -f "$AGENT_RULES_SRC" ]; then
|
||||
AGENT_RULES_DST="$PROJECT_ROOT/AGENT_RULES.md"
|
||||
|
||||
if [ -e "$AGENT_RULES_DST" ] && [ "$FORCE" -eq 0 ]; then
|
||||
echo "AGENT_RULES.md already exists. Use --force to overwrite."
|
||||
else
|
||||
backup_if_exists "$AGENT_RULES_DST"
|
||||
cp "$AGENT_RULES_SRC" "$AGENT_RULES_DST"
|
||||
replace_placeholders "$AGENT_RULES_DST"
|
||||
echo "Synced: AGENT_RULES.md"
|
||||
fi
|
||||
else
|
||||
echo "Skip: AGENT_RULES.template.md not found"
|
||||
fi
|
||||
|
||||
# 5. Create TODO.md and CONFIRM.md if not exist
|
||||
if [ ! -f "$PROJECT_ROOT/TODO.md" ]; then
|
||||
cat > "$PROJECT_ROOT/TODO.md" <<'EOF'
|
||||
# TODO
|
||||
|
||||
## Plan 1: [计划名称]
|
||||
|
||||
- [ ] 任务 1
|
||||
- [ ] 任务 2
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
EOF
|
||||
date_repl="$(escape_sed_replacement "$SYNC_DATE")"
|
||||
if ! sed -i "s/{{DATE}}/$date_repl/g" "$PROJECT_ROOT/TODO.md" 2>/dev/null; then
|
||||
sed "s/{{DATE}}/$date_repl/g" "$PROJECT_ROOT/TODO.md" > "$PROJECT_ROOT/TODO.md.tmp"
|
||||
mv "$PROJECT_ROOT/TODO.md.tmp" "$PROJECT_ROOT/TODO.md"
|
||||
fi
|
||||
echo "Created: TODO.md"
|
||||
fi
|
||||
|
||||
if [ ! -f "$PROJECT_ROOT/CONFIRM.md" ]; then
|
||||
cat > "$PROJECT_ROOT/CONFIRM.md" <<'EOF'
|
||||
# 待确认事项
|
||||
|
||||
## 待确认
|
||||
|
||||
<!-- 记录需要确认的事项 -->
|
||||
|
||||
## 已确认
|
||||
|
||||
<!-- 已确认的事项移到这里 -->
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
EOF
|
||||
date_repl="$(escape_sed_replacement "$SYNC_DATE")"
|
||||
if ! sed -i "s/{{DATE}}/$date_repl/g" "$PROJECT_ROOT/CONFIRM.md" 2>/dev/null; then
|
||||
sed "s/{{DATE}}/$date_repl/g" "$PROJECT_ROOT/CONFIRM.md" > "$PROJECT_ROOT/CONFIRM.md.tmp"
|
||||
mv "$PROJECT_ROOT/CONFIRM.md.tmp" "$PROJECT_ROOT/CONFIRM.md"
|
||||
fi
|
||||
echo "Created: CONFIRM.md"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done."
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Edit memory-bank/*.md to fill in project-specific content"
|
||||
echo " 2. Replace remaining {{PLACEHOLDER}} values"
|
||||
echo " 3. Run sync_standards.sh to sync .agents/ rules"
|
||||
|
|
@ -2,17 +2,22 @@
|
|||
setlocal enabledelayedexpansion
|
||||
|
||||
rem Vendor a trimmed Playbook snapshot into a target project (offline copy),
|
||||
rem then run sync_standards to materialize rulesets\<lang>\ and .gitattributes in
|
||||
rem then run sync_standards to materialize .agents\<lang>\ and .gitattributes in
|
||||
rem the target project root.
|
||||
rem
|
||||
rem Usage:
|
||||
rem scripts\vendor_playbook.bat <project-root> (default: tsl)
|
||||
rem scripts\vendor_playbook.bat <project-root> tsl cpp
|
||||
rem scripts\vendor_playbook.bat <project-root> --langs tsl,cpp
|
||||
rem scripts\vendor_playbook.bat <project-root> tsl cpp --apply-templates
|
||||
rem
|
||||
rem Options:
|
||||
rem --apply-templates Apply CI/lang templates to project root (skip if exists)
|
||||
rem
|
||||
rem Notes:
|
||||
rem - Snapshot is written to: <project-root>\docs\standards\playbook\
|
||||
rem - Existing snapshot is backed up before overwrite.
|
||||
rem - With --apply-templates, CI and lang templates are copied to project root.
|
||||
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
for %%I in ("%SCRIPT_DIR%..") do set "SRC=%%~fI"
|
||||
|
|
@ -25,13 +30,30 @@ set "DEST_ROOT=%~1"
|
|||
shift /1
|
||||
|
||||
set "LANGS="
|
||||
set "APPLY_TEMPLATES=0"
|
||||
|
||||
rem Parse arguments
|
||||
:parse_args
|
||||
if "%~1"=="" goto args_done
|
||||
if "%~1"=="--langs" (
|
||||
set "LANGS=%~2"
|
||||
shift /1
|
||||
shift /1
|
||||
) else (
|
||||
set "LANGS=%1 %2 %3 %4 %5 %6 %7 %8 %9"
|
||||
goto parse_args
|
||||
)
|
||||
if "%~1"=="--apply-templates" (
|
||||
set "APPLY_TEMPLATES=1"
|
||||
shift /1
|
||||
goto parse_args
|
||||
)
|
||||
if "%LANGS%"=="" (
|
||||
set "LANGS=%~1"
|
||||
) else (
|
||||
set "LANGS=%LANGS% %~1"
|
||||
)
|
||||
shift /1
|
||||
goto parse_args
|
||||
:args_done
|
||||
|
||||
if "%LANGS%"=="" set "LANGS=tsl"
|
||||
set "LANGS=%LANGS:,= %"
|
||||
|
|
@ -191,24 +213,24 @@ set "SOURCE=%DEST_PREFIX%\\SOURCE.md"
|
|||
|
||||
echo Vendored snapshot -^> %DEST_PREFIX%
|
||||
|
||||
set "PROJECT_AGENTS_ROOT=%DEST_ROOT_ABS%\\rulesets"
|
||||
set "PROJECT_AGENTS_ROOT=%DEST_ROOT_ABS%\\.agents"
|
||||
set "PROJECT_AGENTS_INDEX=%PROJECT_AGENTS_ROOT%\\index.md"
|
||||
if not exist "%PROJECT_AGENTS_ROOT%" mkdir "%PROJECT_AGENTS_ROOT%"
|
||||
if not exist "%PROJECT_AGENTS_INDEX%" (
|
||||
> "%PROJECT_AGENTS_INDEX%" echo # rulesets(多语言)
|
||||
> "%PROJECT_AGENTS_INDEX%" echo # .agents(多语言)
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo.
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo 本目录用于存放仓库级/语言级的代理规则集。
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo.
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo 本项目已启用的规则集:
|
||||
for %%L in (%LANGS%) do (
|
||||
if /I "%%~L"=="tsl" >> "%PROJECT_AGENTS_INDEX%" echo - rulesets/tsl/:TSL 相关规则集(适用于 .tsl/.tsf)
|
||||
if /I "%%~L"=="cpp" >> "%PROJECT_AGENTS_INDEX%" echo - rulesets/cpp/:C++ 相关规则集(C++23,含 Modules)
|
||||
if /I "%%~L"=="python" >> "%PROJECT_AGENTS_INDEX%" echo - rulesets/python/:Python 相关规则集
|
||||
if /I "%%~L"=="markdown" >> "%PROJECT_AGENTS_INDEX%" echo - rulesets/markdown/:Markdown 相关规则集(仅代码格式化)
|
||||
if /I "%%~L"=="tsl" >> "%PROJECT_AGENTS_INDEX%" echo - .agents/tsl/:TSL 相关规则集(适用于 .tsl/.tsf)
|
||||
if /I "%%~L"=="cpp" >> "%PROJECT_AGENTS_INDEX%" echo - .agents/cpp/:C++ 相关规则集(C++23,含 Modules)
|
||||
if /I "%%~L"=="python" >> "%PROJECT_AGENTS_INDEX%" echo - .agents/python/:Python 相关规则集
|
||||
if /I "%%~L"=="markdown" >> "%PROJECT_AGENTS_INDEX%" echo - .agents/markdown/:Markdown 相关规则集(仅代码格式化)
|
||||
)
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo.
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo 入口建议从:
|
||||
for %%L in (%LANGS%) do >> "%PROJECT_AGENTS_INDEX%" echo - rulesets/%%~L/index.md
|
||||
for %%L in (%LANGS%) do >> "%PROJECT_AGENTS_INDEX%" echo - .agents/%%~L/index.md
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo.
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo 标准快照文档入口:
|
||||
>> "%PROJECT_AGENTS_INDEX%" echo.
|
||||
|
|
@ -222,6 +244,62 @@ call "%DEST_PREFIX%\\scripts\\sync_standards.bat" %LANGS%
|
|||
popd
|
||||
set "SYNC_ROOT=%OLD_SYNC_ROOT%"
|
||||
|
||||
rem Apply templates to project root if requested
|
||||
if "%APPLY_TEMPLATES%"=="1" (
|
||||
echo.
|
||||
echo Applying templates to project root...
|
||||
|
||||
rem Apply CI templates ^(Gitea workflows^)
|
||||
set "CI_SRC=%DEST_PREFIX%\templates\ci\gitea\.gitea"
|
||||
if exist "!CI_SRC!" (
|
||||
if exist "%DEST_ROOT_ABS%\.gitea" (
|
||||
echo Skip ^(exists^): .gitea\
|
||||
) else (
|
||||
xcopy "!CI_SRC!\*" "%DEST_ROOT_ABS%\.gitea\" /e /i /y >nul 2>nul
|
||||
echo Applied: .gitea\
|
||||
)
|
||||
)
|
||||
|
||||
rem Apply lang-specific templates
|
||||
for %%L in (%LANGS%) do (
|
||||
set "LANG_SRC=%DEST_PREFIX%\templates\%%~L"
|
||||
if exist "!LANG_SRC!" (
|
||||
if /I "%%~L"=="cpp" (
|
||||
call :CopyIfNotExists "!LANG_SRC!\.clang-format" "%DEST_ROOT_ABS%\.clang-format"
|
||||
call :CopyIfNotExists "!LANG_SRC!\.clangd" "%DEST_ROOT_ABS%\.clangd"
|
||||
call :CopyIfNotExists "!LANG_SRC!\CMakeLists.txt" "%DEST_ROOT_ABS%\CMakeLists.txt"
|
||||
call :CopyIfNotExists "!LANG_SRC!\CMakeUserPresets.json" "%DEST_ROOT_ABS%\CMakeUserPresets.json"
|
||||
call :CopyIfNotExists "!LANG_SRC!\conanfile.txt" "%DEST_ROOT_ABS%\conanfile.txt"
|
||||
if exist "!LANG_SRC!\conan" (
|
||||
if exist "%DEST_ROOT_ABS%\conan" (
|
||||
echo Skip ^(exists^): conan\
|
||||
) else (
|
||||
xcopy "!LANG_SRC!\conan\*" "%DEST_ROOT_ABS%\conan\" /e /i /y >nul 2>nul
|
||||
echo Applied: conan\
|
||||
)
|
||||
)
|
||||
)
|
||||
if /I "%%~L"=="python" (
|
||||
call :CopyIfNotExists "!LANG_SRC!\.editorconfig" "%DEST_ROOT_ABS%\.editorconfig"
|
||||
call :CopyIfNotExists "!LANG_SRC!\.flake8" "%DEST_ROOT_ABS%\.flake8"
|
||||
call :CopyIfNotExists "!LANG_SRC!\.pre-commit-config.yaml" "%DEST_ROOT_ABS%\.pre-commit-config.yaml"
|
||||
call :CopyIfNotExists "!LANG_SRC!\.pylintrc" "%DEST_ROOT_ABS%\.pylintrc"
|
||||
call :CopyIfNotExists "!LANG_SRC!\pyproject.toml" "%DEST_ROOT_ABS%\pyproject.toml"
|
||||
if exist "!LANG_SRC!\.vscode" (
|
||||
if exist "%DEST_ROOT_ABS%\.vscode" (
|
||||
echo Skip ^(exists^): .vscode\
|
||||
) else (
|
||||
xcopy "!LANG_SRC!\.vscode\*" "%DEST_ROOT_ABS%\.vscode\" /e /i /y >nul 2>nul
|
||||
echo Applied: .vscode\
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo Templates applied.
|
||||
)
|
||||
|
||||
echo Done.
|
||||
endlocal
|
||||
exit /b 0
|
||||
|
|
@ -263,9 +341,26 @@ if /I "%LANG%"=="markdown" (
|
|||
)
|
||||
exit /b 0
|
||||
|
||||
:CopyIfNotExists
|
||||
set "SRC_FILE=%~1"
|
||||
set "DST_FILE=%~2"
|
||||
if exist "%SRC_FILE%" (
|
||||
if exist "%DST_FILE%" (
|
||||
for %%F in ("%DST_FILE%") do echo Skip ^(exists^): %%~nxF
|
||||
) else (
|
||||
copy /y "%SRC_FILE%" "%DST_FILE%" >nul
|
||||
for %%F in ("%DST_FILE%") do echo Applied: %%~nxF
|
||||
)
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:Usage
|
||||
echo Usage:
|
||||
echo scripts\vendor_playbook.bat ^<project-root^> ^(default: tsl^)
|
||||
echo scripts\vendor_playbook.bat ^<project-root^> tsl cpp
|
||||
echo scripts\vendor_playbook.bat ^<project-root^> --langs tsl,cpp
|
||||
echo scripts\vendor_playbook.bat ^<project-root^> tsl cpp --apply-templates
|
||||
echo.
|
||||
echo Options:
|
||||
echo --apply-templates Apply CI/lang templates to project root ^(skip if exists^)
|
||||
exit /b 1
|
||||
|
|
|
|||
|
|
@ -5,11 +5,15 @@
|
|||
# Usage:
|
||||
# powershell -File scripts/vendor_playbook.ps1 -DestRoot <project-root>
|
||||
# powershell -File scripts/vendor_playbook.ps1 -DestRoot <project-root> -Langs tsl,cpp
|
||||
# powershell -File scripts/vendor_playbook.ps1 -DestRoot <project-root> -Langs @("tsl","cpp")
|
||||
# powershell -File scripts/vendor_playbook.ps1 -DestRoot <project-root> -Langs @("tsl","cpp") -ApplyTemplates
|
||||
#
|
||||
# Options:
|
||||
# -ApplyTemplates Apply CI/lang templates to project root (skip if exists)
|
||||
#
|
||||
# Notes:
|
||||
# - Snapshot is written to: <project-root>\docs\standards\playbook\
|
||||
# - Existing snapshot is backed up before overwrite.
|
||||
# - With -ApplyTemplates, CI and lang templates are copied to project root.
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
|
|
@ -17,7 +21,10 @@ param(
|
|||
[string]$DestRoot,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string[]]$Langs
|
||||
[string[]]$Langs,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$ApplyTemplates
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
@ -247,4 +254,78 @@ try {
|
|||
$env:SYNC_ROOT = $oldSyncRoot
|
||||
}
|
||||
|
||||
# Apply templates to project root if requested
|
||||
if ($ApplyTemplates) {
|
||||
Write-Host ""
|
||||
Write-Host "Applying templates to project root..."
|
||||
|
||||
# Helper function: copy file if not exists
|
||||
function Copy-IfNotExists {
|
||||
param([string]$SrcFile, [string]$DstFile)
|
||||
if (Test-Path $SrcFile) {
|
||||
if (Test-Path $DstFile) {
|
||||
Write-Host " Skip (exists): $(Split-Path -Leaf $DstFile)"
|
||||
} else {
|
||||
Copy-Item $SrcFile $DstFile -Force
|
||||
Write-Host " Applied: $(Split-Path -Leaf $DstFile)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Apply CI templates (Gitea workflows)
|
||||
$ciSrc = Join-Path $DestPrefix "templates/ci/gitea/.gitea"
|
||||
if (Test-Path $ciSrc) {
|
||||
$ciDst = Join-Path $DestRootAbs ".gitea"
|
||||
if (Test-Path $ciDst) {
|
||||
Write-Host " Skip (exists): .gitea/"
|
||||
} else {
|
||||
Copy-Item $ciSrc $ciDst -Recurse -Force
|
||||
Write-Host " Applied: .gitea/"
|
||||
}
|
||||
}
|
||||
|
||||
# Apply lang-specific templates
|
||||
foreach ($lang in $Langs) {
|
||||
$langSrc = Join-Path $DestPrefix "templates/$lang"
|
||||
if (-not (Test-Path $langSrc)) { continue }
|
||||
|
||||
switch ($lang) {
|
||||
"cpp" {
|
||||
Copy-IfNotExists (Join-Path $langSrc ".clang-format") (Join-Path $DestRootAbs ".clang-format")
|
||||
Copy-IfNotExists (Join-Path $langSrc ".clangd") (Join-Path $DestRootAbs ".clangd")
|
||||
Copy-IfNotExists (Join-Path $langSrc "CMakeLists.txt") (Join-Path $DestRootAbs "CMakeLists.txt")
|
||||
Copy-IfNotExists (Join-Path $langSrc "CMakeUserPresets.json") (Join-Path $DestRootAbs "CMakeUserPresets.json")
|
||||
Copy-IfNotExists (Join-Path $langSrc "conanfile.txt") (Join-Path $DestRootAbs "conanfile.txt")
|
||||
$conanSrc = Join-Path $langSrc "conan"
|
||||
$conanDst = Join-Path $DestRootAbs "conan"
|
||||
if ((Test-Path $conanSrc) -and -not (Test-Path $conanDst)) {
|
||||
Copy-Item $conanSrc $conanDst -Recurse -Force
|
||||
Write-Host " Applied: conan/"
|
||||
} elseif (Test-Path $conanDst) {
|
||||
Write-Host " Skip (exists): conan/"
|
||||
}
|
||||
break
|
||||
}
|
||||
"python" {
|
||||
Copy-IfNotExists (Join-Path $langSrc ".editorconfig") (Join-Path $DestRootAbs ".editorconfig")
|
||||
Copy-IfNotExists (Join-Path $langSrc ".flake8") (Join-Path $DestRootAbs ".flake8")
|
||||
Copy-IfNotExists (Join-Path $langSrc ".pre-commit-config.yaml") (Join-Path $DestRootAbs ".pre-commit-config.yaml")
|
||||
Copy-IfNotExists (Join-Path $langSrc ".pylintrc") (Join-Path $DestRootAbs ".pylintrc")
|
||||
Copy-IfNotExists (Join-Path $langSrc "pyproject.toml") (Join-Path $DestRootAbs "pyproject.toml")
|
||||
$vscodeSrc = Join-Path $langSrc ".vscode"
|
||||
$vscodeDst = Join-Path $DestRootAbs ".vscode"
|
||||
if ((Test-Path $vscodeSrc) -and -not (Test-Path $vscodeDst)) {
|
||||
Copy-Item $vscodeSrc $vscodeDst -Recurse -Force
|
||||
Write-Host " Applied: .vscode/"
|
||||
} elseif (Test-Path $vscodeDst) {
|
||||
Write-Host " Skip (exists): .vscode/"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Templates applied."
|
||||
}
|
||||
|
||||
Write-Host "Done."
|
||||
|
|
|
|||
|
|
@ -9,11 +9,16 @@ set -eu
|
|||
# sh scripts/vendor_playbook.sh <project-root> # default: tsl
|
||||
# sh scripts/vendor_playbook.sh <project-root> tsl cpp
|
||||
# sh scripts/vendor_playbook.sh <project-root> --langs tsl,cpp
|
||||
# sh scripts/vendor_playbook.sh <project-root> tsl cpp --apply-templates
|
||||
#
|
||||
# Options:
|
||||
# --apply-templates Apply CI/lang templates to project root (skip if exists)
|
||||
#
|
||||
# Notes:
|
||||
# - Snapshot is written to: <project-root>/docs/standards/playbook/
|
||||
# - Existing snapshot is backed up before overwrite.
|
||||
# - Ruleset templates from rulesets/ will be copied to snapshot for sync_standards use.
|
||||
# - With --apply-templates, CI and lang templates are copied to project root.
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"
|
||||
SRC="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd -P)"
|
||||
|
|
@ -24,6 +29,11 @@ Usage:
|
|||
sh scripts/vendor_playbook.sh <project-root> # default: tsl
|
||||
sh scripts/vendor_playbook.sh <project-root> tsl cpp
|
||||
sh scripts/vendor_playbook.sh <project-root> --langs tsl,cpp
|
||||
sh scripts/vendor_playbook.sh <project-root> tsl cpp --apply-templates
|
||||
|
||||
Options:
|
||||
--apply-templates Apply CI/lang templates to project root (skip if exists)
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
|
|
@ -41,13 +51,33 @@ PROJECT_ROOT="$1"
|
|||
shift
|
||||
|
||||
langs=""
|
||||
if [ "${1:-}" = "--langs" ]; then
|
||||
APPLY_TEMPLATES=0
|
||||
|
||||
# Parse arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--langs)
|
||||
langs="${2:-}"
|
||||
shift 2 || true
|
||||
fi
|
||||
if [ -z "${langs:-}" ] && [ "$#" -gt 0 ]; then
|
||||
langs="$*"
|
||||
fi
|
||||
;;
|
||||
--apply-templates)
|
||||
APPLY_TEMPLATES=1
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
echo "ERROR: Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
if [ -z "$langs" ]; then
|
||||
langs="$1"
|
||||
else
|
||||
langs="$langs $1"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "${langs:-}" ]; then
|
||||
langs="tsl"
|
||||
|
|
@ -278,4 +308,74 @@ EOF
|
|||
fi
|
||||
|
||||
SYNC_ROOT="$PROJECT_ROOT_ABS" sh "$DEST_PREFIX/scripts/sync_standards.sh" "$@"
|
||||
|
||||
# Apply templates to project root if requested
|
||||
if [ "$APPLY_TEMPLATES" -eq 1 ]; then
|
||||
echo ""
|
||||
echo "Applying templates to project root..."
|
||||
|
||||
# Helper function: copy file if not exists
|
||||
copy_if_not_exists() {
|
||||
src_file="$1"
|
||||
dst_file="$2"
|
||||
if [ -f "$src_file" ]; then
|
||||
if [ -f "$dst_file" ]; then
|
||||
echo " Skip (exists): $(basename "$dst_file")"
|
||||
else
|
||||
cp "$src_file" "$dst_file"
|
||||
echo " Applied: $(basename "$dst_file")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Apply CI templates (Gitea workflows)
|
||||
CI_SRC="$DEST_PREFIX/templates/ci/gitea"
|
||||
if [ -d "$CI_SRC/.gitea" ]; then
|
||||
if [ -d "$PROJECT_ROOT_ABS/.gitea" ]; then
|
||||
echo " Skip (exists): .gitea/"
|
||||
else
|
||||
cp -R "$CI_SRC/.gitea" "$PROJECT_ROOT_ABS/"
|
||||
echo " Applied: .gitea/"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Apply lang-specific templates
|
||||
for lang in "$@"; do
|
||||
[ -n "$lang" ] || continue
|
||||
LANG_SRC="$DEST_PREFIX/templates/$lang"
|
||||
[ -d "$LANG_SRC" ] || continue
|
||||
|
||||
case "$lang" in
|
||||
cpp)
|
||||
copy_if_not_exists "$LANG_SRC/.clang-format" "$PROJECT_ROOT_ABS/.clang-format"
|
||||
copy_if_not_exists "$LANG_SRC/.clangd" "$PROJECT_ROOT_ABS/.clangd"
|
||||
copy_if_not_exists "$LANG_SRC/CMakeLists.txt" "$PROJECT_ROOT_ABS/CMakeLists.txt"
|
||||
copy_if_not_exists "$LANG_SRC/CMakeUserPresets.json" "$PROJECT_ROOT_ABS/CMakeUserPresets.json"
|
||||
copy_if_not_exists "$LANG_SRC/conanfile.txt" "$PROJECT_ROOT_ABS/conanfile.txt"
|
||||
if [ -d "$LANG_SRC/conan" ] && [ ! -d "$PROJECT_ROOT_ABS/conan" ]; then
|
||||
cp -R "$LANG_SRC/conan" "$PROJECT_ROOT_ABS/"
|
||||
echo " Applied: conan/"
|
||||
elif [ -d "$PROJECT_ROOT_ABS/conan" ]; then
|
||||
echo " Skip (exists): conan/"
|
||||
fi
|
||||
;;
|
||||
python)
|
||||
copy_if_not_exists "$LANG_SRC/.editorconfig" "$PROJECT_ROOT_ABS/.editorconfig"
|
||||
copy_if_not_exists "$LANG_SRC/.flake8" "$PROJECT_ROOT_ABS/.flake8"
|
||||
copy_if_not_exists "$LANG_SRC/.pre-commit-config.yaml" "$PROJECT_ROOT_ABS/.pre-commit-config.yaml"
|
||||
copy_if_not_exists "$LANG_SRC/.pylintrc" "$PROJECT_ROOT_ABS/.pylintrc"
|
||||
copy_if_not_exists "$LANG_SRC/pyproject.toml" "$PROJECT_ROOT_ABS/pyproject.toml"
|
||||
if [ -d "$LANG_SRC/.vscode" ] && [ ! -d "$PROJECT_ROOT_ABS/.vscode" ]; then
|
||||
cp -R "$LANG_SRC/.vscode" "$PROJECT_ROOT_ABS/"
|
||||
echo " Applied: .vscode/"
|
||||
elif [ -d "$PROJECT_ROOT_ABS/.vscode" ]; then
|
||||
echo " Skip (exists): .vscode/"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Templates applied."
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# Agent Instructions
|
||||
|
||||
<!-- playbook:framework:start -->
|
||||
|
||||
## 规则优先级
|
||||
|
||||
1. 系统/开发者指令与安全约束
|
||||
2. 仓库规则:`.agents/` 与本文件
|
||||
3. `AGENT_RULES.md` - 执行流程
|
||||
4. `TODO.md` - 任务队列
|
||||
|
||||
---
|
||||
|
||||
## 快速导航
|
||||
|
||||
<!-- playbook:agents:start -->
|
||||
|
||||
请以 `.agents/` 下的规则为准:
|
||||
|
||||
- 入口:`.agents/index.md`
|
||||
- 语言规则:`.agents/{{MAIN_LANGUAGE}}/index.md`
|
||||
<!-- playbook:agents:end -->
|
||||
|
||||
<!-- playbook:templates:start -->
|
||||
|
||||
### 核心规则
|
||||
|
||||
- **执行流程**:[AGENT_RULES.md](./AGENT_RULES.md)
|
||||
- **AI 行为规范**:[docs/prompts/system/agent-behavior.md](docs/prompts/system/agent-behavior.md)
|
||||
|
||||
### 项目上下文
|
||||
|
||||
- **项目定位**:[memory-bank/project-brief.md](memory-bank/project-brief.md)
|
||||
- **技术栈**:[memory-bank/tech-stack.md](memory-bank/tech-stack.md)
|
||||
- **架构设计**:[memory-bank/architecture.md](memory-bank/architecture.md)
|
||||
- **进度追踪**:[memory-bank/progress.md](memory-bank/progress.md)
|
||||
- **架构决策**:[memory-bank/decisions.md](memory-bank/decisions.md)
|
||||
- **实施计划**:[memory-bank/implementation-plan.md](memory-bank/implementation-plan.md)
|
||||
|
||||
### 工作流程
|
||||
|
||||
- **需求澄清**:[docs/prompts/coding/clarify.md](docs/prompts/coding/clarify.md)
|
||||
- **验证检查**:[docs/prompts/coding/verify.md](docs/prompts/coding/verify.md)
|
||||
<!-- playbook:templates:end -->
|
||||
|
||||
---
|
||||
|
||||
## 新会话开始时
|
||||
|
||||
**AI 应该做的**:
|
||||
|
||||
1. 读取 [AGENT_RULES.md](./AGENT_RULES.md)
|
||||
2. 读取 [memory-bank/](memory-bank/) 核心文档
|
||||
3. 读取 [docs/prompts/system/agent-behavior.md](docs/prompts/system/agent-behavior.md)
|
||||
4. 查看 [TODO.md](./TODO.md) 和 [CONFIRM.md](./CONFIRM.md)
|
||||
<!-- playbook:framework:end -->
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# AGENT_RULES
|
||||
|
||||
目的:为本仓库提供稳定的执行流程。
|
||||
|
||||
## 优先级
|
||||
|
||||
1. 系统/开发者指令与安全约束
|
||||
2. 仓库规则:`.agents/` 与 `AGENTS.md`
|
||||
3. 本文件
|
||||
4. `TODO.md`
|
||||
|
||||
## 上下文加载(每次会话开始)
|
||||
|
||||
**必读文档**(按顺序):
|
||||
|
||||
1. `memory-bank/project-brief.md` - 项目定位、边界、约束
|
||||
2. `memory-bank/tech-stack.md` - 技术栈、工具链
|
||||
3. `memory-bank/architecture.md` - 架构设计、模块职责
|
||||
4. `TODO.md` - 当前任务队列
|
||||
5. `CONFIRM.md` - 待确认事项
|
||||
|
||||
**目的**:让 AI 快速理解项目全貌,避免重复解释。
|
||||
|
||||
## 主循环
|
||||
|
||||
1. 读取 `TODO.md`
|
||||
2. 选择最上方的 Plan
|
||||
3. **读取 `memory-bank/implementation-plan.md`**(若该 Plan 有对应说明)
|
||||
4. 执行该 Plan 内所有可执行子任务
|
||||
5. 校验输出结果(运行测试/检查日志)
|
||||
6. **更新 `memory-bank/progress.md`**(记录已完成事项)
|
||||
7. 如存在歧义/风险/决策点,记录到 `CONFIRM.md`
|
||||
8. 若 Plan 已全部完成,则从 `TODO.md` 移除
|
||||
9. 若 Plan 因缺少信息而阻塞,标记为 `BLOCKED` 并移到 `TODO.md` 末尾
|
||||
10. 重新读取 `TODO.md`,继续下一个 Plan
|
||||
|
||||
## Plan 规则
|
||||
|
||||
- 不因等待确认而中断;记录到 `CONFIRM.md` 后继续
|
||||
- 执行并验证该 Plan 中所有可执行的子任务
|
||||
- 若因缺少信息/决策而阻塞:记录 `CONFIRM.md`,标记为 `BLOCKED`,移到末尾(不移除)
|
||||
- 每轮只处理一个 Plan
|
||||
- **小步快跑**:每个 Plan 应该可快速完成
|
||||
- **可验证**:每个 Plan 必须包含验证步骤
|
||||
|
||||
## 执行约束
|
||||
|
||||
### 代码修改约束
|
||||
|
||||
- **必须先读文件再修改**:不读文件就提议修改是禁止的
|
||||
- **必须运行测试验证**:相关测试必须通过
|
||||
- **遵循换行规则**:遵循 `.gitattributes` 规则
|
||||
|
||||
### 决策记录约束
|
||||
|
||||
- **重要决策**:记录到 `memory-bank/decisions.md`(ADR 格式)
|
||||
- **临时确认**:记录到 `CONFIRM.md`(会话级)
|
||||
- **进度留痕**:记录到 `memory-bank/progress.md`(持久化)
|
||||
|
||||
## CONFIRM.md 触发条件
|
||||
|
||||
- 需求不明确或存在多种可行方案
|
||||
- 需要行为/兼容性取舍
|
||||
- 风险或约束冲突
|
||||
- **架构变更**:影响多个模块的修改
|
||||
- **性能权衡**:需要在性能和可维护性之间选择
|
||||
- **兼容性问题**:可能破坏现有用户代码
|
||||
|
||||
## 验证清单
|
||||
|
||||
每个 Plan 完成后,必须验证:
|
||||
|
||||
- [ ] 代码修改符合 `.agents/` 下的规则
|
||||
- [ ] 相关测试通过
|
||||
- [ ] 换行符正确
|
||||
- [ ] 无语法错误
|
||||
- [ ] 更新了 `memory-bank/progress.md`
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
# 项目架构模板
|
||||
|
||||
本目录包含项目架构的模板文件,用于快速初始化新项目的 AI 代理工作环境。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
templates/
|
||||
├── README.md # 本文件
|
||||
├── AGENTS.template.md # 路由中心模板
|
||||
├── AGENT_RULES.template.md # 执行流程模板
|
||||
├── memory-bank/ # 项目上下文模板
|
||||
│ ├── project-brief.template.md
|
||||
│ ├── tech-stack.template.md
|
||||
│ ├── architecture.template.md
|
||||
│ ├── progress.template.md
|
||||
│ ├── decisions.template.md
|
||||
│ └── implementation-plan.template.md
|
||||
├── prompts/ # 提示词库模板
|
||||
│ ├── README.md
|
||||
│ ├── system/
|
||||
│ │ └── agent-behavior.template.md
|
||||
│ └── coding/
|
||||
│ ├── clarify.template.md
|
||||
│ └── verify.template.md
|
||||
├── ci/ # CI 模板
|
||||
│ └── gitea/
|
||||
│ └── .gitea/workflows/
|
||||
├── cpp/ # C++ 配置模板
|
||||
│ ├── .clang-format
|
||||
│ ├── .clangd
|
||||
│ └── ...
|
||||
└── python/ # Python 配置模板
|
||||
├── .editorconfig
|
||||
├── pyproject.toml
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 快速部署
|
||||
|
||||
使用 `sync_templates` 脚本一键部署:
|
||||
|
||||
**Linux/macOS**:
|
||||
|
||||
```bash
|
||||
# 基础部署
|
||||
sh scripts/sync_templates.sh /path/to/project
|
||||
|
||||
# 追加完整框架到已有 AGENTS.md
|
||||
sh scripts/sync_templates.sh --full /path/to/project
|
||||
```
|
||||
|
||||
**Windows PowerShell**:
|
||||
|
||||
```powershell
|
||||
# 基础部署
|
||||
.\scripts\sync_templates.ps1 -ProjectRoot C:\path\to\project
|
||||
|
||||
# 追加完整框架
|
||||
.\scripts\sync_templates.ps1 -ProjectRoot C:\path\to\project -Full
|
||||
```
|
||||
|
||||
**Windows CMD**:
|
||||
|
||||
```cmd
|
||||
scripts\sync_templates.bat C:\path\to\project
|
||||
scripts\sync_templates.bat --full C:\path\to\project
|
||||
```
|
||||
|
||||
### 部署行为
|
||||
|
||||
- **新项目**:创建完整的 AGENTS.md、AGENT_RULES.md、memory-bank/、docs/prompts/
|
||||
- **已有 AGENTS.md**:
|
||||
- 默认:追加路由链接(`<!-- playbook:templates:start/end -->`)
|
||||
- `--full`:追加完整框架(规则优先级 + 路由 + 新会话开始时)
|
||||
- **其他文件**:如果已存在则跳过(使用 `--force` 覆盖)
|
||||
- **自动创建**:TODO.md 和 CONFIRM.md(如果不存在)
|
||||
- **占位符替换**:自动替换 `{{DATE}}` 为当前日期
|
||||
|
||||
### 部署后的目录结构
|
||||
|
||||
```text
|
||||
project/
|
||||
├── AGENTS.md # 路由中心(主入口)
|
||||
├── AGENT_RULES.md # 执行流程
|
||||
├── TODO.md # 任务队列
|
||||
├── CONFIRM.md # 待确认事项
|
||||
├── memory-bank/ # 项目上下文
|
||||
│ ├── project-brief.md
|
||||
│ ├── tech-stack.md
|
||||
│ ├── architecture.md
|
||||
│ ├── progress.md
|
||||
│ ├── decisions.md
|
||||
│ └── implementation-plan.md
|
||||
└── docs/prompts/ # 提示词库
|
||||
├── README.md
|
||||
├── system/agent-behavior.md
|
||||
└── coding/
|
||||
├── clarify.md
|
||||
└── verify.md
|
||||
```
|
||||
|
||||
## 占位符说明
|
||||
|
||||
模板中使用 `{{PLACEHOLDER}}` 格式的占位符,需要替换为实际值:
|
||||
|
||||
| 占位符 | 说明 | 自动替换 |
|
||||
| ------------------------- | ------------ | -------- |
|
||||
| `{{DATE}}` | 日期 | ✅ 是 |
|
||||
| `{{PROJECT_NAME}}` | 项目名称 | ❌ 手动 |
|
||||
| `{{PROJECT_GOAL}}` | 项目目标 | ❌ 手动 |
|
||||
| `{{PROJECT_DESCRIPTION}}` | 项目描述 | ❌ 手动 |
|
||||
| `{{MAIN_LANGUAGE}}` | 主语言 | ❌ 手动 |
|
||||
| 其他 `{{...}}` | 项目特定内容 | ❌ 手动 |
|
||||
|
||||
## 模板说明
|
||||
|
||||
### memory-bank/
|
||||
|
||||
项目上下文文档,用于让 AI 快速理解项目:
|
||||
|
||||
| 文件 | 用途 |
|
||||
| --------------------------------- | -------------------- |
|
||||
| `project-brief.template.md` | 项目定位、边界、约束 |
|
||||
| `tech-stack.template.md` | 技术栈、工具链、环境 |
|
||||
| `architecture.template.md` | 架构设计、模块职责 |
|
||||
| `progress.template.md` | 开发进度追踪 |
|
||||
| `decisions.template.md` | 架构决策记录(ADR) |
|
||||
| `implementation-plan.template.md` | 当前实施计划 |
|
||||
|
||||
### prompts/
|
||||
|
||||
工作流程模板:
|
||||
|
||||
| 文件 | 用途 |
|
||||
| ----------------------------------- | ------------ |
|
||||
| `system/agent-behavior.template.md` | AI 行为规范 |
|
||||
| `coding/clarify.template.md` | 需求澄清模板 |
|
||||
| `coding/verify.template.md` | 验证检查清单 |
|
||||
|
||||
### AGENT_RULES.template.md
|
||||
|
||||
执行流程规范,定义 AI 的工作循环和约束。
|
||||
|
||||
### AGENTS.template.md
|
||||
|
||||
路由中心模板,作为项目的主入口。
|
||||
|
||||
**设计理念**:
|
||||
|
||||
- **最小化内容**:只包含导航链接,不包含详细规则
|
||||
- **结构化导航**:分为核心规则、项目上下文、工作流程三个板块
|
||||
|
||||
**playbook 标记**(用于自动更新):
|
||||
|
||||
| 标记 | 用途 | 管理脚本 |
|
||||
| --------------------------------------- | ----------------------- | -------------- |
|
||||
| `<!-- playbook:agents:start/end -->` | 语言规则链接 | sync_standards |
|
||||
| `<!-- playbook:templates:start/end -->` | 路由链接(默认追加) | sync_templates |
|
||||
| `<!-- playbook:framework:start/end -->` | 完整框架(--full 追加) | sync_templates |
|
||||
|
||||
### ci/、cpp/、python/
|
||||
|
||||
语言和 CI 配置模板。通过 `vendor_playbook --apply-templates` 部署:
|
||||
|
||||
| 目录 | 内容 | 部署位置 |
|
||||
| ----------- | ----------------------------------------- | ---------- |
|
||||
| `ci/gitea/` | Gitea Actions 工作流 | `.gitea/` |
|
||||
| `cpp/` | .clang-format, .clangd, CMakeLists.txt 等 | 项目根目录 |
|
||||
| `python/` | pyproject.toml, .editorconfig 等 | 项目根目录 |
|
||||
|
||||
**使用方式**:
|
||||
|
||||
```bash
|
||||
# vendor_playbook 时一并部署
|
||||
sh scripts/vendor_playbook.sh /path/to/project tsl cpp --apply-templates
|
||||
```
|
||||
|
||||
## 与 playbook 其他部分的关系
|
||||
|
||||
```text
|
||||
playbook/
|
||||
├── rulesets/ # 语言级硬规则 → 部署到 .agents/
|
||||
├── codex/skills/ # 按需加载的技能
|
||||
├── docs/ # 权威静态文档
|
||||
├── templates/ # 本目录:项目架构模板 → 部署到 memory-bank/ 等
|
||||
└── scripts/
|
||||
├── sync_standards.* # 同步 .agents/ 和 .gitattributes
|
||||
└── sync_templates.* # 同步 memory-bank/、docs/prompts/、AGENT_RULES.md
|
||||
```
|
||||
|
||||
## 完整部署流程
|
||||
|
||||
```bash
|
||||
# 1. 部署项目架构模板
|
||||
sh scripts/sync_templates.sh /path/to/project
|
||||
|
||||
# 2. 部署语言规则
|
||||
sh scripts/sync_standards.sh tsl # 或其他语言
|
||||
|
||||
# 3. 编辑 memory-bank/*.md 填写项目信息
|
||||
|
||||
# 4. 替换剩余的 {{PLACEHOLDER}} 占位符
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-01-21
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
# 架构设计
|
||||
|
||||
## 整体架构
|
||||
|
||||
```txt
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ {{LAYER_1}} │
|
||||
└─────────────────────┬───────────────────────────────────────┘
|
||||
│
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ {{LAYER_2}} │
|
||||
└─────────────────────┬───────────────────────────────────────┘
|
||||
│
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ {{LAYER_3}} │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 核心模块
|
||||
|
||||
### 1. {{MODULE_1}}
|
||||
|
||||
**职责**:{{MODULE_1_DESC}}
|
||||
|
||||
**主要组件**:
|
||||
|
||||
- {{COMPONENT_1}}
|
||||
- {{COMPONENT_2}}
|
||||
|
||||
**核心方法**:
|
||||
|
||||
- {{METHOD_1}}
|
||||
- {{METHOD_2}}
|
||||
|
||||
---
|
||||
|
||||
### 2. {{MODULE_2}}
|
||||
|
||||
**职责**:{{MODULE_2_DESC}}
|
||||
|
||||
**主要组件**:
|
||||
|
||||
- {{COMPONENT_3}}
|
||||
- {{COMPONENT_4}}
|
||||
|
||||
---
|
||||
|
||||
### 3. {{MODULE_3}}
|
||||
|
||||
**职责**:{{MODULE_3_DESC}}
|
||||
|
||||
---
|
||||
|
||||
## 设计模式
|
||||
|
||||
### {{PATTERN_1}}
|
||||
|
||||
**应用**:{{PATTERN_1_USAGE}}
|
||||
|
||||
**目的**:{{PATTERN_1_PURPOSE}}
|
||||
|
||||
**优点**:
|
||||
|
||||
- {{PATTERN_1_ADVANTAGE_1}}
|
||||
- {{PATTERN_1_ADVANTAGE_2}}
|
||||
|
||||
### {{PATTERN_2}}
|
||||
|
||||
**应用**:{{PATTERN_2_USAGE}}
|
||||
|
||||
**目的**:{{PATTERN_2_PURPOSE}}
|
||||
|
||||
---
|
||||
|
||||
## 关键约束
|
||||
|
||||
### 1. {{CONSTRAINT_CATEGORY_1}}
|
||||
|
||||
- {{CONSTRAINT_1}}
|
||||
- {{CONSTRAINT_2}}
|
||||
|
||||
### 2. {{CONSTRAINT_CATEGORY_2}}
|
||||
|
||||
- {{CONSTRAINT_3}}
|
||||
- {{CONSTRAINT_4}}
|
||||
|
||||
---
|
||||
|
||||
## 扩展点
|
||||
|
||||
### 1. {{EXTENSION_1}}
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. {{STEP_1}}
|
||||
2. {{STEP_2}}
|
||||
3. {{STEP_3}}
|
||||
|
||||
### 2. {{EXTENSION_2}}
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. {{STEP_4}}
|
||||
2. {{STEP_5}}
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# 架构决策记录
|
||||
|
||||
本文档记录项目中的重要架构决策,使用 ADR (Architecture Decision Record) 格式。
|
||||
|
||||
---
|
||||
|
||||
## ADR-001: {{DECISION_1_TITLE}}
|
||||
|
||||
**日期**: {{DATE}}
|
||||
**状态**: 已采纳
|
||||
|
||||
### 决策
|
||||
|
||||
{{DECISION_1_CONTENT}}
|
||||
|
||||
### 理由
|
||||
|
||||
{{DECISION_1_REASON}}
|
||||
|
||||
### 影响
|
||||
|
||||
{{DECISION_1_IMPACT}}
|
||||
|
||||
### 实施细节
|
||||
|
||||
{{DECISION_1_IMPLEMENTATION}}
|
||||
|
||||
---
|
||||
|
||||
## ADR-002: {{DECISION_2_TITLE}}
|
||||
|
||||
**日期**: {{DATE}}
|
||||
**状态**: 已采纳
|
||||
|
||||
### 决策
|
||||
|
||||
{{DECISION_2_CONTENT}}
|
||||
|
||||
### 理由
|
||||
|
||||
{{DECISION_2_REASON}}
|
||||
|
||||
### 影响
|
||||
|
||||
{{DECISION_2_IMPACT}}
|
||||
|
||||
---
|
||||
|
||||
## ADR 模板
|
||||
|
||||
```markdown
|
||||
## ADR-XXX: 决策标题
|
||||
|
||||
**日期**: YYYY-MM-DD
|
||||
**状态**: 已采纳 / 已废弃 / 待讨论
|
||||
|
||||
### 决策
|
||||
|
||||
简要描述决策内容
|
||||
|
||||
### 理由
|
||||
|
||||
为什么做出这个决策
|
||||
|
||||
### 影响
|
||||
|
||||
对项目的影响
|
||||
|
||||
### 替代方案(可选)
|
||||
|
||||
考虑过但未采纳的方案
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
# 当前实施计划
|
||||
|
||||
## 计划状态
|
||||
|
||||
**计划名称**: {{PLAN_NAME}}
|
||||
**开始时间**: {{START_DATE}}
|
||||
**当前状态**: 进行中 / 已完成 / 已暂停
|
||||
|
||||
---
|
||||
|
||||
## 目标
|
||||
|
||||
{{PLAN_GOAL}}
|
||||
|
||||
**成功标准**:
|
||||
|
||||
- [ ] {{SUCCESS_CRITERIA_1}}
|
||||
- [ ] {{SUCCESS_CRITERIA_2}}
|
||||
- [ ] {{SUCCESS_CRITERIA_3}}
|
||||
|
||||
---
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 阶段 1: {{PHASE_1_NAME}}
|
||||
|
||||
#### 步骤 1.1: {{STEP_1_1}}
|
||||
|
||||
- [ ] {{TASK_1_1_1}}
|
||||
- [ ] {{TASK_1_1_2}}
|
||||
|
||||
**验证**: {{VERIFICATION_1_1}}
|
||||
|
||||
#### 步骤 1.2: {{STEP_1_2}}
|
||||
|
||||
- [ ] {{TASK_1_2_1}}
|
||||
- [ ] {{TASK_1_2_2}}
|
||||
|
||||
**验证**: {{VERIFICATION_1_2}}
|
||||
|
||||
---
|
||||
|
||||
### 阶段 2: {{PHASE_2_NAME}}
|
||||
|
||||
#### 步骤 2.1: {{STEP_2_1}}
|
||||
|
||||
- [ ] {{TASK_2_1_1}}
|
||||
- [ ] {{TASK_2_1_2}}
|
||||
|
||||
**验证**: {{VERIFICATION_2_1}}
|
||||
|
||||
---
|
||||
|
||||
## 当前进度
|
||||
|
||||
### 已完成
|
||||
|
||||
- {{COMPLETED_PHASE}}
|
||||
|
||||
### 进行中
|
||||
|
||||
- {{IN_PROGRESS_STEP}}
|
||||
|
||||
### 待开始
|
||||
|
||||
- {{PENDING_STEP}}
|
||||
|
||||
---
|
||||
|
||||
## 风险与问题
|
||||
|
||||
### 风险
|
||||
|
||||
1. **{{RISK_1}}**
|
||||
- 风险:{{RISK_1_DESC}}
|
||||
- 缓解:{{RISK_1_MITIGATION}}
|
||||
|
||||
### 已解决的问题
|
||||
|
||||
1. {{RESOLVED_ISSUE_1}}
|
||||
|
||||
---
|
||||
|
||||
## 下一步行动
|
||||
|
||||
- [ ] {{NEXT_ACTION_1}}
|
||||
- [ ] {{NEXT_ACTION_2}}
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# 开发进度追踪
|
||||
|
||||
## 当前阶段:{{CURRENT_PHASE}}
|
||||
|
||||
### 最近完成
|
||||
|
||||
#### {{DATE}}
|
||||
|
||||
- [x] {{COMPLETED_1}}
|
||||
- [x] {{COMPLETED_2}}
|
||||
|
||||
### 进行中
|
||||
|
||||
- [ ] {{IN_PROGRESS_1}}
|
||||
- [ ] {{IN_PROGRESS_2}}
|
||||
|
||||
### 待办
|
||||
|
||||
#### {{CATEGORY_1}}
|
||||
|
||||
- [ ] {{TODO_1}}
|
||||
- [ ] {{TODO_2}}
|
||||
|
||||
#### {{CATEGORY_2}}
|
||||
|
||||
- [ ] {{TODO_3}}
|
||||
- [ ] {{TODO_4}}
|
||||
|
||||
### 已知问题
|
||||
|
||||
#### {{ISSUE_CATEGORY_1}}
|
||||
|
||||
- {{ISSUE_1}}
|
||||
- **临时方案**:{{WORKAROUND_1}}
|
||||
- **长期方案**:{{SOLUTION_1}}
|
||||
|
||||
### 里程碑
|
||||
|
||||
#### M1: {{MILESTONE_1}}(目标:{{TARGET_DATE_1}})
|
||||
|
||||
- [ ] {{MILESTONE_1_TASK_1}}
|
||||
- [ ] {{MILESTONE_1_TASK_2}}
|
||||
|
||||
#### M2: {{MILESTONE_2}}(目标:{{TARGET_DATE_2}})
|
||||
|
||||
- [ ] {{MILESTONE_2_TASK_1}}
|
||||
- [ ] {{MILESTONE_2_TASK_2}}
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
### {{DATE}}
|
||||
|
||||
- {{LOG_1}}
|
||||
- {{LOG_2}}
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
# {{PROJECT_NAME}} 项目简介
|
||||
|
||||
## 项目定位
|
||||
|
||||
**核心目标**:{{PROJECT_GOAL}}
|
||||
|
||||
**一句话描述**:{{PROJECT_DESCRIPTION}}
|
||||
|
||||
## 为什么做这个项目?
|
||||
|
||||
### 问题
|
||||
|
||||
- {{PROBLEM_1}}
|
||||
- {{PROBLEM_2}}
|
||||
- {{PROBLEM_3}}
|
||||
|
||||
### 解决方案
|
||||
|
||||
- {{SOLUTION_1}}
|
||||
- {{SOLUTION_2}}
|
||||
- {{SOLUTION_3}}
|
||||
|
||||
## 项目边界
|
||||
|
||||
### 做什么
|
||||
|
||||
- {{DO_1}}
|
||||
- {{DO_2}}
|
||||
- {{DO_3}}
|
||||
|
||||
### 不做什么
|
||||
|
||||
- {{DONT_1}}
|
||||
- {{DONT_2}}
|
||||
- {{DONT_3}}
|
||||
|
||||
### 约束条件
|
||||
|
||||
- {{CONSTRAINT_1}}
|
||||
- {{CONSTRAINT_2}}
|
||||
- {{CONSTRAINT_3}}
|
||||
|
||||
## 核心概念
|
||||
|
||||
<!-- 根据项目需要填写核心概念 -->
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **主语言**:{{MAIN_LANGUAGE}}
|
||||
- **外部依赖**:{{DEPENDENCIES}}
|
||||
- **测试环境**:{{TEST_ENV}}
|
||||
|
||||
## 参考资料
|
||||
|
||||
- {{REFERENCE_1}}
|
||||
- {{REFERENCE_2}}
|
||||
|
||||
## 当前状态
|
||||
|
||||
- {{STATUS_1}}
|
||||
- {{STATUS_2}}
|
||||
- {{STATUS_3}}
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
# 技术栈与工具链
|
||||
|
||||
## 核心技术
|
||||
|
||||
### 主语言:{{MAIN_LANGUAGE}}
|
||||
|
||||
**文件类型**:
|
||||
|
||||
- {{FILE_TYPE_1}}
|
||||
- {{FILE_TYPE_2}}
|
||||
|
||||
**特点**:
|
||||
|
||||
- {{FEATURE_1}}
|
||||
- {{FEATURE_2}}
|
||||
- {{FEATURE_3}}
|
||||
|
||||
**运行方式**:
|
||||
|
||||
- {{RUN_METHOD_1}}
|
||||
- {{RUN_METHOD_2}}
|
||||
|
||||
## 项目结构
|
||||
|
||||
```text
|
||||
{{PROJECT_NAME}}/
|
||||
├── {{DIR_1}}/ # {{DIR_1_DESC}}
|
||||
├── {{DIR_2}}/ # {{DIR_2_DESC}}
|
||||
├── {{DIR_3}}/ # {{DIR_3_DESC}}
|
||||
└── memory-bank/ # 项目上下文
|
||||
```
|
||||
|
||||
## 开发环境
|
||||
|
||||
### {{ENV_1}}
|
||||
|
||||
**必需工具**:
|
||||
|
||||
- {{TOOL_1}}
|
||||
- {{TOOL_2}}
|
||||
|
||||
**运行测试**:
|
||||
|
||||
```bash
|
||||
{{TEST_CMD_1}}
|
||||
```
|
||||
|
||||
### {{ENV_2}}(如有)
|
||||
|
||||
**必需工具**:
|
||||
|
||||
- {{TOOL_3}}
|
||||
- {{TOOL_4}}
|
||||
|
||||
## 版本控制
|
||||
|
||||
### Git 配置
|
||||
|
||||
**换行规则**(`.gitattributes`):
|
||||
|
||||
- 遵循 `.gitattributes` 文件定义
|
||||
|
||||
**忽略规则**(`.gitignore`):
|
||||
|
||||
- 以 `.gitignore` 实际内容为准
|
||||
|
||||
### 分支策略
|
||||
|
||||
- `master`/`main`:主分支(稳定版本)
|
||||
- 功能分支:按需创建
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 测试类型
|
||||
|
||||
- {{TEST_TYPE_1}}
|
||||
- {{TEST_TYPE_2}}
|
||||
|
||||
### 验证标准
|
||||
|
||||
**测试通过条件**:
|
||||
|
||||
1. {{PASS_CONDITION_1}}
|
||||
2. {{PASS_CONDITION_2}}
|
||||
3. {{PASS_CONDITION_3}}
|
||||
|
||||
**常见失败原因**:
|
||||
|
||||
- {{FAIL_REASON_1}}
|
||||
- {{FAIL_REASON_2}}
|
||||
|
||||
## 依赖管理
|
||||
|
||||
### 外部依赖
|
||||
|
||||
- {{EXTERNAL_DEP_1}}
|
||||
- {{EXTERNAL_DEP_2}}
|
||||
|
||||
### 内部依赖
|
||||
|
||||
- {{INTERNAL_DEP_1}}
|
||||
- {{INTERNAL_DEP_2}}
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 当前瓶颈
|
||||
|
||||
- {{BOTTLENECK_1}}
|
||||
- {{BOTTLENECK_2}}
|
||||
|
||||
### 优化方向
|
||||
|
||||
- {{OPTIMIZATION_1}}
|
||||
- {{OPTIMIZATION_2}}
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# 提示词库
|
||||
|
||||
本目录包含 AI 代理的工作流程模板和参考文档。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
prompts/
|
||||
├── README.md # 本文件
|
||||
├── system/ # 系统级规范
|
||||
│ └── agent-behavior.md
|
||||
├── coding/ # 编码流程
|
||||
│ ├── clarify.md # 需求澄清模板
|
||||
│ └── verify.md # 验证检查清单
|
||||
└── user/ # 用户快捷命令
|
||||
└── quick-test.md # 快速测试命令
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
### AI 代理
|
||||
|
||||
- 新会话时读取 `system/agent-behavior.md`
|
||||
- 需要澄清需求时参考 `coding/clarify.md`
|
||||
- 完成任务前检查 `coding/verify.md`
|
||||
|
||||
### 用户
|
||||
|
||||
- 使用 `user/quick-test.md` 中的命令快速执行测试
|
||||
|
||||
## 文档说明
|
||||
|
||||
| 文件 | 用途 |
|
||||
| -------------------------- | ------------------------------- |
|
||||
| `system/agent-behavior.md` | AI 行为规范、工作模式、禁止行为 |
|
||||
| `coding/clarify.md` | 需求澄清步骤和问题模板 |
|
||||
| `coding/verify.md` | 代码、测试、文档验证清单 |
|
||||
| `user/quick-test.md` | 常用测试命令参考 |
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# 需求澄清模板
|
||||
|
||||
## 何时使用
|
||||
|
||||
- 需求描述不明确
|
||||
- 存在多种理解方式
|
||||
- 缺少关键信息
|
||||
|
||||
---
|
||||
|
||||
## 澄清步骤
|
||||
|
||||
### 1. 理解当前需求
|
||||
|
||||
**复述需求**:
|
||||
|
||||
```text
|
||||
我理解你的需求是:[用自己的话复述]
|
||||
```
|
||||
|
||||
**识别歧义点**:
|
||||
|
||||
- 歧义 1:[描述不明确的地方]
|
||||
- 歧义 2:[可能有多种理解的地方]
|
||||
|
||||
---
|
||||
|
||||
### 2. 提出澄清问题
|
||||
|
||||
**问题模板**:
|
||||
|
||||
> 只问阻塞问题,最多 1–2 个;优先给出选项让用户选择。
|
||||
|
||||
#### 功能范围
|
||||
|
||||
- 这个功能是否包括 [场景 A]?
|
||||
- 是否需要支持 [边界情况 B]?
|
||||
- 优先级如何?必须有 vs 可选
|
||||
|
||||
#### 行为细节
|
||||
|
||||
- 当 [条件 X] 时,应该 [行为 Y] 还是 [行为 Z]?
|
||||
- 如果 [异常情况],如何处理?
|
||||
- 是否需要与 [现有功能] 保持一致?
|
||||
|
||||
#### 技术约束
|
||||
|
||||
- 是否有性能要求?
|
||||
- 是否有兼容性要求?
|
||||
- 是否有安全要求?
|
||||
|
||||
---
|
||||
|
||||
### 3. 提供选项
|
||||
|
||||
**选项格式**:
|
||||
|
||||
**选项 A**:[方案描述]
|
||||
|
||||
- 优点:[列出优点]
|
||||
- 缺点:[列出缺点]
|
||||
- 适用场景:[什么情况下选这个]
|
||||
|
||||
**选项 B**:[方案描述]
|
||||
|
||||
- 优点:[列出优点]
|
||||
- 缺点:[列出缺点]
|
||||
- 适用场景:[什么情况下选这个]
|
||||
|
||||
**推荐**:[推荐哪个选项,为什么]
|
||||
|
||||
---
|
||||
|
||||
### 4. 确认理解
|
||||
|
||||
**确认清单**:
|
||||
|
||||
- [ ] 功能范围明确
|
||||
- [ ] 行为细节清晰
|
||||
- [ ] 技术约束已知
|
||||
- [ ] 优先级确定
|
||||
- [ ] 验收标准明确
|
||||
|
||||
---
|
||||
|
||||
## 示例
|
||||
|
||||
### 需求
|
||||
|
||||
```text
|
||||
实现 XXX 功能
|
||||
```
|
||||
|
||||
### 澄清过程
|
||||
|
||||
**复述需求**:
|
||||
|
||||
```text
|
||||
我理解你的需求是:为 YYY 添加 XXX 功能,
|
||||
用于 ZZZ。
|
||||
```
|
||||
|
||||
**识别歧义点**:
|
||||
|
||||
- 歧义 1:XXX 是只读还是可写?
|
||||
- 歧义 2:是否需要支持所有场景?
|
||||
|
||||
**澄清问题**:
|
||||
|
||||
- 是否需要支持 [场景 A]?
|
||||
- 当 [条件 X] 时,应该如何处理?
|
||||
|
||||
**提供选项**:
|
||||
|
||||
**选项 A**:完整实现
|
||||
|
||||
- 优点:功能完整
|
||||
- 缺点:开发周期长
|
||||
|
||||
**选项 B**:核心功能
|
||||
|
||||
- 优点:快速交付
|
||||
- 缺点:功能有限
|
||||
|
||||
**推荐**:选项 A,因为 [原因]。
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
# 验证检查清单
|
||||
|
||||
## 代码修改验证
|
||||
|
||||
### 语法检查
|
||||
|
||||
- [ ] 代码可正常运行(无语法错误)
|
||||
- [ ] 无未定义的变量或函数
|
||||
- [ ] 依赖引用正确
|
||||
|
||||
### 风格检查
|
||||
|
||||
- [ ] 命名符合规范
|
||||
- [ ] 缩进正确
|
||||
- [ ] 换行符正确(遵循 .gitattributes)
|
||||
- [ ] 无冗余注释
|
||||
|
||||
---
|
||||
|
||||
## 测试验证
|
||||
|
||||
### 单元测试
|
||||
|
||||
- [ ] 相关测试脚本存在
|
||||
- [ ] 测试可正常运行
|
||||
- [ ] 测试通过(无失败)
|
||||
|
||||
### 回归测试
|
||||
|
||||
- [ ] 现有测试仍然通过
|
||||
- [ ] 未破坏其他功能
|
||||
|
||||
---
|
||||
|
||||
## 文档验证
|
||||
|
||||
### 代码文档
|
||||
|
||||
- [ ] 复杂逻辑有注释说明
|
||||
- [ ] 公开 API 有使用示例(如需)
|
||||
|
||||
### 项目文档
|
||||
|
||||
- [ ] `memory-bank/progress.md` 已更新
|
||||
- [ ] 重要决策记录到 `memory-bank/decisions.md`
|
||||
- [ ] `CONFIRM.md` 中需讨论事项已记录
|
||||
|
||||
---
|
||||
|
||||
## Git 验证
|
||||
|
||||
### 提交前检查
|
||||
|
||||
- [ ] 只包含相关修改(无无关文件)
|
||||
- [ ] 提交信息清晰
|
||||
- [ ] 无临时文件或调试代码
|
||||
|
||||
### 分支检查
|
||||
|
||||
- [ ] 在正确的分支上工作
|
||||
|
||||
---
|
||||
|
||||
## 性能验证(如果涉及)
|
||||
|
||||
### 性能测试
|
||||
|
||||
- [ ] 处理时间可接受
|
||||
- [ ] 内存使用正常
|
||||
- [ ] 无明显性能退化
|
||||
|
||||
---
|
||||
|
||||
## 安全验证(如果涉及)
|
||||
|
||||
### 安全检查
|
||||
|
||||
- [ ] 无注入风险
|
||||
- [ ] 敏感信息已脱敏
|
||||
|
||||
---
|
||||
|
||||
## 快速检查清单(最小集)
|
||||
|
||||
**每次修改必须检查**:
|
||||
|
||||
- [ ] 代码可运行(无语法错误)
|
||||
- [ ] 相关测试通过
|
||||
- [ ] 换行符正确
|
||||
- [ ] `memory-bank/progress.md` 已更新
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
# AI 代理行为规范
|
||||
|
||||
## 工作模式
|
||||
|
||||
### 模式 1: 探索模式(Explore)
|
||||
|
||||
**目的**:理解代码库、分析问题、收集信息
|
||||
|
||||
**行为规范**:
|
||||
|
||||
- 使用搜索工具探索代码
|
||||
- 输出分析报告和发现
|
||||
- 提出问题和建议
|
||||
- 不修改任何代码
|
||||
- 不运行测试(除非明确要求)
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 理解某个模块的实现
|
||||
- 分析 bug 的根本原因
|
||||
- 评估功能实现的可行性
|
||||
|
||||
---
|
||||
|
||||
### 模式 2: 开发模式(Develop)
|
||||
|
||||
**目的**:实现功能、修复 bug、重构代码
|
||||
|
||||
**行为规范**:
|
||||
|
||||
- 先读取相关文件,理解现有逻辑
|
||||
- 进行精确修改
|
||||
- 修改后运行对应测试验证
|
||||
- 更新 `memory-bank/progress.md`
|
||||
- 不读文件就提议修改
|
||||
- 不跳过测试直接提交
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 实现新功能
|
||||
- 修复已知 bug
|
||||
- 优化性能
|
||||
|
||||
---
|
||||
|
||||
### 模式 3: 调试模式(Debug)
|
||||
|
||||
**目的**:诊断问题、对比差异、验证行为
|
||||
|
||||
**行为规范**:
|
||||
|
||||
- 收集相关日志和输出
|
||||
- 分析差异原因
|
||||
- 记录到 `CONFIRM.md` 或直接修复
|
||||
- 重新验证
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 测试失败
|
||||
- 输出不符合预期
|
||||
- 性能问题诊断
|
||||
|
||||
---
|
||||
|
||||
## 代码风格要求
|
||||
|
||||
### 通用规范
|
||||
|
||||
**命名规范**:
|
||||
|
||||
- 遵循项目现有的命名风格
|
||||
- 保持一致性
|
||||
|
||||
**缩进**:
|
||||
|
||||
- 遵循项目现有的缩进风格
|
||||
|
||||
**换行**:
|
||||
|
||||
- 遵循 `.gitattributes` 规则
|
||||
|
||||
**注释**:
|
||||
|
||||
- 只在逻辑不自明时添加注释
|
||||
- 不添加冗余注释
|
||||
|
||||
---
|
||||
|
||||
## 禁止行为清单
|
||||
|
||||
### 代码修改
|
||||
|
||||
- **不读文件就提议修改**
|
||||
|
||||
- 必须先读取文件
|
||||
- 理解现有逻辑后再提出修改建议
|
||||
|
||||
- **破坏现有架构**
|
||||
|
||||
- 不随意移动目录结构
|
||||
- 不随意重构核心模块
|
||||
|
||||
- **随意改动换行符**
|
||||
- 遵循 `.gitattributes` 规则
|
||||
- 不混用 LF 和 CRLF
|
||||
|
||||
### 测试流程
|
||||
|
||||
- **跳过测试直接提交**
|
||||
- 修改后必须运行相关测试
|
||||
- 测试失败必须分析原因
|
||||
|
||||
### Git 操作
|
||||
|
||||
- **使用 `git commit --amend`**
|
||||
|
||||
- 除非用户明确要求
|
||||
- 总是创建新提交
|
||||
|
||||
- **使用 `git push --force`**
|
||||
|
||||
- 特别是推送到 main/master 分支
|
||||
- 如果用户要求,必须警告风险
|
||||
|
||||
- **跳过 hooks**
|
||||
- 不使用 `--no-verify`
|
||||
|
||||
### 过度工程
|
||||
|
||||
- **添加未要求的功能**
|
||||
|
||||
- 只做用户要求的修改
|
||||
- 不主动重构周边代码
|
||||
|
||||
- **添加不必要的注释**
|
||||
|
||||
- 不给自明的代码添加注释
|
||||
|
||||
- **过度抽象**
|
||||
- 不为一次性操作创建工具函数
|
||||
- 不为假设的未来需求设计
|
||||
|
||||
---
|
||||
|
||||
## 决策原则
|
||||
|
||||
### 何时记录到 CONFIRM.md
|
||||
|
||||
**必须记录**:
|
||||
|
||||
- 需求有歧义,存在多种理解
|
||||
- 有多个技术方案,需要权衡
|
||||
- 可能破坏兼容性
|
||||
- 涉及架构变更
|
||||
|
||||
**可以不记录**:
|
||||
|
||||
- 明显的 bug 修复
|
||||
- 符合现有模式的小改动
|
||||
- 测试用例补充
|
||||
|
||||
### 何时记录到 decisions.md
|
||||
|
||||
**必须记录**(ADR 格式):
|
||||
|
||||
- 影响多个模块的架构决策
|
||||
- 技术栈选择
|
||||
- 设计模式选择
|
||||
- 重要的约束条件
|
||||
|
||||
---
|
||||
|
||||
## 沟通原则
|
||||
|
||||
### 输出风格
|
||||
|
||||
- 简洁明确,避免冗长
|
||||
- 使用纯文本结构化输出,必要时用 Markdown 代码块
|
||||
- 代码块标注语言
|
||||
- 不使用 emoji(除非用户明确要求)
|
||||
- 不使用过度的赞美或验证
|
||||
|
||||
### 技术准确性
|
||||
|
||||
- 优先技术准确性,而非迎合用户
|
||||
- 发现用户理解有误时,礼貌纠正
|
||||
- 不确定时,先调查再回答
|
||||
|
||||
### 时间估算
|
||||
|
||||
- 不给出时间估算
|
||||
- 专注于任务本身,让用户自己判断时间
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:{{DATE}}
|
||||
|
|
@ -9,12 +9,14 @@ tests/
|
|||
├── README.md # 本文件:测试文档
|
||||
├── scripts/ # Shell 脚本测试(bats)
|
||||
│ ├── test_sync_standards.bats # sync_standards.sh 测试
|
||||
│ ├── test_sync_templates.bats # sync_templates.sh 测试
|
||||
│ ├── test_vendor_playbook.bats # vendor_playbook.sh 测试
|
||||
│ └── test_install_codex_skills.bats # install_codex_skills.sh 测试
|
||||
├── templates/ # 模板验证测试
|
||||
│ ├── validate_python_templates.sh # Python 模板验证
|
||||
│ ├── validate_cpp_templates.sh # C++ 模板验证
|
||||
│ └── validate_ci_templates.sh # CI 模板验证
|
||||
│ ├── validate_ci_templates.sh # CI 模板验证
|
||||
│ └── validate_project_templates.sh # 项目模板验证
|
||||
└── integration/ # 集成测试
|
||||
└── check_doc_links.sh # 文档链接有效性检查
|
||||
```
|
||||
|
|
@ -31,6 +33,7 @@ cd /path/to/playbook
|
|||
sudo apt-get install bats # Ubuntu/Debian
|
||||
cd tests/scripts
|
||||
bats test_sync_standards.bats
|
||||
bats test_sync_templates.bats
|
||||
bats test_vendor_playbook.bats
|
||||
bats test_install_codex_skills.bats
|
||||
|
||||
|
|
@ -39,6 +42,7 @@ cd tests/templates
|
|||
sh validate_python_templates.sh
|
||||
sh validate_cpp_templates.sh
|
||||
sh validate_ci_templates.sh
|
||||
sh validate_project_templates.sh
|
||||
|
||||
# 3. 运行集成测试
|
||||
cd tests/integration
|
||||
|
|
@ -88,6 +92,21 @@ sh check_doc_links.sh
|
|||
- **幂等性**:
|
||||
- 多次执行结果一致
|
||||
|
||||
#### test_sync_templates.bats
|
||||
|
||||
测试 `scripts/sync_templates.sh` 脚本的功能:
|
||||
|
||||
- **基础同步**:
|
||||
- 同步 memory-bank/ 与 docs/prompts/
|
||||
- 创建 AGENTS.md / AGENT_RULES.md / TODO.md / CONFIRM.md
|
||||
- **占位符替换**:
|
||||
- `{{PROJECT_NAME}}` 与 `{{DATE}}`
|
||||
- **目录覆盖策略**:
|
||||
- 无 `--force` 时不覆盖已有目录
|
||||
- `--force` 时覆盖并备份
|
||||
- **AGENTS.md 更新**:
|
||||
- `--full` 更新 framework 区块
|
||||
|
||||
#### test_vendor_playbook.bats
|
||||
|
||||
测试 `scripts/vendor_playbook.sh` 脚本的功能:
|
||||
|
|
@ -227,6 +246,22 @@ sh check_doc_links.sh
|
|||
- 包含 README 说明文档
|
||||
- 包含使用说明
|
||||
|
||||
#### validate_project_templates.sh
|
||||
|
||||
验证项目通用模板:
|
||||
|
||||
- **核心模板**:
|
||||
- `templates/AGENTS.template.md`
|
||||
- `templates/AGENT_RULES.template.md`
|
||||
- `templates/README.md`
|
||||
- **memory-bank 模板**:
|
||||
- 项目定位/技术栈/架构/进度/决策/实施计划
|
||||
- **prompts 模板**:
|
||||
- `prompts/README.md`
|
||||
- `prompts/system/agent-behavior.template.md`
|
||||
- `prompts/coding/clarify.template.md`
|
||||
- `prompts/coding/verify.template.md`
|
||||
|
||||
### 3. 集成测试 (integration/)
|
||||
|
||||
端到端测试,验证整体功能。
|
||||
|
|
@ -236,7 +271,7 @@ sh check_doc_links.sh
|
|||
检查所有 Markdown 文档中的链接有效性:
|
||||
|
||||
- **扫描范围**:
|
||||
- 所有 `*.md` 文件
|
||||
- 所有 `*.md` 文件(排除 `*.template.md`)
|
||||
- 排除 node_modules, .git, build, dist 等目录
|
||||
- **链接类型**:
|
||||
- Markdown 链接:`[text](link)`
|
||||
|
|
@ -296,6 +331,7 @@ pip3 install yamllint
|
|||
# Shell 脚本测试
|
||||
cd tests/scripts
|
||||
bats test_sync_standards.bats --tap # TAP 格式输出
|
||||
bats test_sync_templates.bats
|
||||
bats test_vendor_playbook.bats --formatter junit # JUnit 格式
|
||||
|
||||
# 模板验证测试
|
||||
|
|
@ -303,6 +339,7 @@ cd tests/templates
|
|||
sh validate_python_templates.sh
|
||||
sh validate_cpp_templates.sh
|
||||
sh validate_ci_templates.sh
|
||||
sh validate_project_templates.sh
|
||||
|
||||
# 集成测试
|
||||
cd tests/integration
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ echo "🔍 扫描 Markdown 文件..."
|
|||
cd "$PLAYBOOK_ROOT"
|
||||
|
||||
MD_FILES=$(find . -name "*.md" \
|
||||
-not -name "*.template.md" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-not -path "*/.git/*" \
|
||||
-not -path "*/build/*" \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bats
|
||||
# sync_templates.sh 测试套件
|
||||
|
||||
setup() {
|
||||
export PLAYBOOK_ROOT="$(cd "$BATS_TEST_DIRNAME/../.." && pwd)"
|
||||
export SCRIPT_PATH="$PLAYBOOK_ROOT/scripts/sync_templates.sh"
|
||||
export TARGET_DIR="$(mktemp -d)"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
if [ -n "$TARGET_DIR" ] && [ -d "$TARGET_DIR" ]; then
|
||||
chmod -R u+w "$TARGET_DIR" 2>/dev/null || true
|
||||
rm -rf "$TARGET_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================
|
||||
# 基础功能测试
|
||||
# ==============================================
|
||||
|
||||
@test "sync_templates.sh 脚本存在且可执行" {
|
||||
[ -f "$SCRIPT_PATH" ]
|
||||
}
|
||||
|
||||
@test "sync_templates.sh - 基础同步与占位符替换" {
|
||||
sh "$SCRIPT_PATH" --project-name "DemoProject" --date "2026-02-03" "$TARGET_DIR"
|
||||
|
||||
[ -d "$TARGET_DIR/memory-bank" ]
|
||||
[ -f "$TARGET_DIR/memory-bank/project-brief.md" ]
|
||||
[ -f "$TARGET_DIR/docs/prompts/coding/clarify.md" ]
|
||||
[ -f "$TARGET_DIR/AGENTS.md" ]
|
||||
[ -f "$TARGET_DIR/AGENT_RULES.md" ]
|
||||
[ -f "$TARGET_DIR/TODO.md" ]
|
||||
[ -f "$TARGET_DIR/CONFIRM.md" ]
|
||||
|
||||
grep -q "DemoProject" "$TARGET_DIR/memory-bank/project-brief.md"
|
||||
! grep -q "{{DATE}}" "$TARGET_DIR/TODO.md"
|
||||
|
||||
[ -z "$(find "$TARGET_DIR" -name '*.template.md' -print -quit)" ]
|
||||
}
|
||||
|
||||
@test "sync_templates.sh - 已存在目录不覆盖 (无 --force)" {
|
||||
mkdir -p "$TARGET_DIR/memory-bank"
|
||||
mkdir -p "$TARGET_DIR/docs/prompts"
|
||||
echo "keep" > "$TARGET_DIR/memory-bank/keep.md"
|
||||
echo "keep" > "$TARGET_DIR/docs/prompts/keep.md"
|
||||
|
||||
sh "$SCRIPT_PATH" "$TARGET_DIR"
|
||||
|
||||
[ -f "$TARGET_DIR/memory-bank/keep.md" ]
|
||||
[ ! -f "$TARGET_DIR/memory-bank/project-brief.md" ]
|
||||
[ -f "$TARGET_DIR/docs/prompts/keep.md" ]
|
||||
[ ! -f "$TARGET_DIR/docs/prompts/README.md" ]
|
||||
}
|
||||
|
||||
@test "sync_templates.sh - --force 覆盖并备份" {
|
||||
mkdir -p "$TARGET_DIR/memory-bank"
|
||||
echo "marker" > "$TARGET_DIR/memory-bank/marker.txt"
|
||||
|
||||
sh "$SCRIPT_PATH" --force "$TARGET_DIR"
|
||||
|
||||
[ -f "$TARGET_DIR/memory-bank/project-brief.md" ]
|
||||
[ ! -f "$TARGET_DIR/memory-bank/marker.txt" ]
|
||||
|
||||
backup_dir="$(ls -d "$TARGET_DIR"/memory-bank.bak.* 2>/dev/null | head -n 1)"
|
||||
[ -n "$backup_dir" ]
|
||||
[ -f "$backup_dir/marker.txt" ]
|
||||
}
|
||||
|
||||
@test "sync_templates.sh - --full 更新 framework 区块" {
|
||||
cat > "$TARGET_DIR/AGENTS.md" << 'EOF'
|
||||
# Agent Instructions
|
||||
|
||||
<!-- playbook:framework:start -->
|
||||
OLD_FRAMEWORK
|
||||
<!-- playbook:framework:end -->
|
||||
|
||||
Footer
|
||||
EOF
|
||||
|
||||
sh "$SCRIPT_PATH" --full "$TARGET_DIR"
|
||||
|
||||
! grep -q "OLD_FRAMEWORK" "$TARGET_DIR/AGENTS.md"
|
||||
grep -q "<!-- playbook:framework:start -->" "$TARGET_DIR/AGENTS.md"
|
||||
grep -q "Footer" "$TARGET_DIR/AGENTS.md"
|
||||
}
|
||||
|
|
@ -176,6 +176,20 @@ teardown() {
|
|||
[ -d "docs/standards/playbook/templates/ci" ]
|
||||
}
|
||||
|
||||
@test "vendor_playbook.sh - --apply-templates 应用模板到项目根目录" {
|
||||
cd "$TARGET_DIR"
|
||||
|
||||
sh "$SCRIPT_PATH" "$TARGET_DIR" cpp --apply-templates
|
||||
|
||||
if [ -f "$PLAYBOOK_ROOT/templates/cpp/.clang-format" ]; then
|
||||
[ -f ".clang-format" ]
|
||||
fi
|
||||
|
||||
if [ -f "$PLAYBOOK_ROOT/templates/ci/gitea/.gitea/workflows/standards-check.yml" ]; then
|
||||
[ -f ".gitea/workflows/standards-check.yml" ]
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================
|
||||
# 目标目录处理测试
|
||||
# ==============================================
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
#!/usr/bin/env sh
|
||||
# 项目模板验证脚本
|
||||
|
||||
set -eu
|
||||
|
||||
echo "========================================"
|
||||
echo "🧩 项目模板验证"
|
||||
echo "========================================"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PLAYBOOK_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
TEMPLATES_DIR="$PLAYBOOK_ROOT/templates"
|
||||
|
||||
VALIDATION_PASSED=0
|
||||
VALIDATION_FAILED=0
|
||||
ERRORS_FILE="/tmp/project_template_validation_errors.txt"
|
||||
REPORT_FILE="$SCRIPT_DIR/project_templates_report.txt"
|
||||
|
||||
> "$ERRORS_FILE"
|
||||
> "$REPORT_FILE"
|
||||
|
||||
echo "📁 模板目录: $TEMPLATES_DIR"
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# 辅助函数
|
||||
# ============================================
|
||||
|
||||
validate_file_exists() {
|
||||
local file="$1"
|
||||
local description="$2"
|
||||
|
||||
if [ -f "$file" ]; then
|
||||
echo " ✅ $description: $(basename "$file")"
|
||||
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
|
||||
return 0
|
||||
else
|
||||
echo " ❌ $description: $(basename "$file") - 文件不存在"
|
||||
echo "文件不存在: $file" >> "$ERRORS_FILE"
|
||||
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_contains() {
|
||||
local file="$1"
|
||||
local needle="$2"
|
||||
local description="$3"
|
||||
|
||||
if grep -Fq "$needle" "$file"; then
|
||||
echo " ✓ $description"
|
||||
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
|
||||
else
|
||||
echo " ✗ $description"
|
||||
echo "缺少内容: $needle in $file" >> "$ERRORS_FILE"
|
||||
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "🔍 验证核心模板文件"
|
||||
AGENTS_TEMPLATE="$TEMPLATES_DIR/AGENTS.template.md"
|
||||
AGENT_RULES_TEMPLATE="$TEMPLATES_DIR/AGENT_RULES.template.md"
|
||||
README_TEMPLATE="$TEMPLATES_DIR/README.md"
|
||||
|
||||
if validate_file_exists "$AGENTS_TEMPLATE" "AGENTS.template.md"; then
|
||||
validate_contains "$AGENTS_TEMPLATE" "<!-- playbook:templates:start -->" "包含 templates 标记"
|
||||
validate_contains "$AGENTS_TEMPLATE" "<!-- playbook:framework:start -->" "包含 framework 标记"
|
||||
validate_contains "$AGENTS_TEMPLATE" "{{DATE}}" "包含 {{DATE}} 占位符"
|
||||
fi
|
||||
|
||||
if validate_file_exists "$AGENT_RULES_TEMPLATE" "AGENT_RULES.template.md"; then
|
||||
validate_contains "$AGENT_RULES_TEMPLATE" "AGENT_RULES" "包含 AGENT_RULES 标题"
|
||||
validate_contains "$AGENT_RULES_TEMPLATE" "{{DATE}}" "包含 {{DATE}} 占位符"
|
||||
fi
|
||||
|
||||
validate_file_exists "$README_TEMPLATE" "templates/README.md"
|
||||
|
||||
echo ""
|
||||
echo "🔍 验证 memory-bank 模板"
|
||||
|
||||
MEMORY_BANK_DIR="$TEMPLATES_DIR/memory-bank"
|
||||
for name in project-brief tech-stack architecture progress decisions implementation-plan; do
|
||||
validate_file_exists "$MEMORY_BANK_DIR/$name.template.md" "memory-bank/$name.template.md"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "🔍 验证 prompts 模板"
|
||||
|
||||
PROMPTS_DIR="$TEMPLATES_DIR/prompts"
|
||||
validate_file_exists "$PROMPTS_DIR/README.md" "prompts/README.md"
|
||||
validate_file_exists "$PROMPTS_DIR/system/agent-behavior.template.md" "prompts/system/agent-behavior.template.md"
|
||||
validate_file_exists "$PROMPTS_DIR/coding/clarify.template.md" "prompts/coding/clarify.template.md"
|
||||
validate_file_exists "$PROMPTS_DIR/coding/verify.template.md" "prompts/coding/verify.template.md"
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# 生成验证报告
|
||||
# ============================================
|
||||
|
||||
echo "========================================"
|
||||
echo "📊 验证结果统计"
|
||||
echo "========================================"
|
||||
echo "✅ 通过: $VALIDATION_PASSED"
|
||||
echo "❌ 失败: $VALIDATION_FAILED"
|
||||
|
||||
if [ $((VALIDATION_PASSED + VALIDATION_FAILED)) -gt 0 ]; then
|
||||
echo "📈 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
|
||||
else
|
||||
echo "📈 通过率: N/A (无测试项)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
{
|
||||
echo "项目模板验证报告"
|
||||
echo "===================="
|
||||
echo ""
|
||||
echo "验证时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo "模板目录: $TEMPLATES_DIR"
|
||||
echo ""
|
||||
echo "统计结果:"
|
||||
echo " 通过: $VALIDATION_PASSED"
|
||||
echo " 失败: $VALIDATION_FAILED"
|
||||
if [ $((VALIDATION_PASSED + VALIDATION_FAILED)) -gt 0 ]; then
|
||||
echo " 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
|
||||
fi
|
||||
echo ""
|
||||
if [ -s "$ERRORS_FILE" ]; then
|
||||
echo "错误详情:"
|
||||
cat "$ERRORS_FILE"
|
||||
fi
|
||||
} > "$REPORT_FILE"
|
||||
|
||||
echo "📄 详细报告: $REPORT_FILE"
|
||||
echo "========================================"
|
||||
|
||||
rm -f "$ERRORS_FILE"
|
||||
|
||||
if [ "$VALIDATION_FAILED" -eq 0 ]; then
|
||||
echo "✅ 所有项目模板验证通过"
|
||||
exit 0
|
||||
else
|
||||
echo "❌ 项目模板验证失败 ($VALIDATION_FAILED 个错误)"
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Reference in New Issue