mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-11 03:43:30 +08:00
docs(zh-CN): update
This commit is contained in:
173
docs/zh-CN/commands/aside.md
Normal file
173
docs/zh-CN/commands/aside.md
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
description: 在不打断或丢失当前任务上下文的情况下,快速回答一个附带问题。回答后自动恢复工作。
|
||||
---
|
||||
|
||||
# 旁述指令
|
||||
|
||||
在任务进行中提问,获得即时、聚焦的回答——然后立即从暂停处继续。当前任务、文件和上下文绝不会被修改。
|
||||
|
||||
## 何时使用
|
||||
|
||||
* 你在 Claude 工作时对某事感到好奇,但又不想打断工作节奏
|
||||
* 你需要快速解释 Claude 当前正在编辑的代码
|
||||
* 你想就某个决定征求第二意见或进行澄清,而不会使任务偏离方向
|
||||
* 在 Claude 继续之前,你需要理解一个错误、概念或模式
|
||||
* 你想询问与当前任务无关的事情,而无需开启新会话
|
||||
|
||||
## 使用方法
|
||||
|
||||
```
|
||||
/aside <your question>
|
||||
/aside what does this function actually return?
|
||||
/aside is this pattern thread-safe?
|
||||
/aside why are we using X instead of Y here?
|
||||
/aside what's the difference between foo() and bar()?
|
||||
/aside should we be worried about the N+1 query we just added?
|
||||
```
|
||||
|
||||
## 流程
|
||||
|
||||
### 步骤 1:冻结当前任务状态
|
||||
|
||||
在回答任何问题之前,先在心里记下:
|
||||
|
||||
* 当前活动任务是什么?(正在处理哪个文件、功能或问题)
|
||||
* 在调用 `/aside` 时,进行到哪一步了?
|
||||
* 接下来原本要发生什么?
|
||||
|
||||
在旁述期间,**不要**触碰、编辑、创建或删除任何文件。
|
||||
|
||||
### 步骤 2:直接回答问题
|
||||
|
||||
以最简洁但仍完整有用的形式回答问题。
|
||||
|
||||
* 先说答案,再说推理过程
|
||||
* 保持简短——如果需要完整解释,请在任务结束后再提供
|
||||
* 如果问题涉及当前正在处理的文件或代码,请精确引用(相关时包括文件路径和行号)
|
||||
* 如果回答问题需要读取文件,就读它——但只读不写
|
||||
|
||||
将响应格式化为:
|
||||
|
||||
```
|
||||
ASIDE: [restate the question briefly]
|
||||
|
||||
[Your answer here]
|
||||
|
||||
— Back to task: [one-line description of what was being done]
|
||||
```
|
||||
|
||||
### 步骤 3:恢复主任务
|
||||
|
||||
在给出答案后,立即从暂停的确切点继续执行活动任务。除非旁述回答揭示了阻碍或需要重新考虑当前方法的理由(见边缘情况),否则不要请求恢复许可。
|
||||
|
||||
***
|
||||
|
||||
## 边缘情况
|
||||
|
||||
**未提供问题(`/aside` 后面没有内容):**
|
||||
回复:
|
||||
|
||||
```
|
||||
ASIDE: no question provided
|
||||
|
||||
What would you like to know? (ask your question and I'll answer without losing the current task context)
|
||||
|
||||
— Back to task: [one-line description of what was being done]
|
||||
```
|
||||
|
||||
**问题揭示了当前任务的潜在问题:**
|
||||
在恢复之前清楚地标记出来:
|
||||
|
||||
```
|
||||
ASIDE: [answer]
|
||||
|
||||
⚠️ Note: This answer suggests [issue] with the current approach. Want to address this before continuing, or proceed as planned?
|
||||
```
|
||||
|
||||
等待用户的决定后再恢复。
|
||||
|
||||
**问题实际上是任务重定向(而非旁述问题):**
|
||||
如果问题暗示要改变正在构建的内容(例如,`/aside actually, let's use Redis instead`),请澄清:
|
||||
|
||||
```
|
||||
ASIDE: That sounds like a direction change, not just a side question.
|
||||
Do you want to:
|
||||
(a) Answer this as information only and keep the current plan
|
||||
(b) Pause the current task and change approach
|
||||
```
|
||||
|
||||
等待用户的回答——不要自行假设。
|
||||
|
||||
**问题涉及当前打开的文件或代码:**
|
||||
根据实时上下文回答。如果该文件在会话早期已被读取,直接引用它。如果尚未读取,现在读取它(只读)并在回答时附带文件:行号引用。
|
||||
|
||||
**无活动任务(调用 `/aside` 时没有进行中的任务):**
|
||||
仍然使用标准包装器,以保持响应格式一致:
|
||||
|
||||
```
|
||||
ASIDE: [restate the question briefly]
|
||||
|
||||
[Your answer here]
|
||||
|
||||
— Back to task: no active task to resume
|
||||
```
|
||||
|
||||
**问题需要长篇回答:**
|
||||
简洁地给出核心答案,然后提供:
|
||||
|
||||
```
|
||||
That's the short version. Want a deeper explanation after we finish [current task]?
|
||||
```
|
||||
|
||||
**连续多个 `/aside` 问题:**
|
||||
依次回答每个问题。在回答完最后一个问题后,恢复主任务。不要在一连串旁述中丢失任务状态。
|
||||
|
||||
**旁述回答暗示需要进行代码更改:**
|
||||
记下所需的更改,但不要在旁述期间进行更改:
|
||||
|
||||
```
|
||||
ASIDE: [answer]
|
||||
|
||||
📝 Worth fixing: [what should be changed]. I'll flag this after the current task unless you want to address it now.
|
||||
```
|
||||
|
||||
**问题含糊不清或过于笼统:**
|
||||
提出一个澄清性问题——一个能获取回答所需信息的最简短问题。不要提出多个问题。
|
||||
|
||||
***
|
||||
|
||||
## 示例输出
|
||||
|
||||
```
|
||||
User: /aside what does fetchWithRetry() actually do?
|
||||
|
||||
ASIDE: what does fetchWithRetry() do?
|
||||
|
||||
fetchWithRetry() (src/api/retry.ts:12) attempts the request up to 3 times with
|
||||
exponential backoff (250ms → 500ms → 1s). It only retries on 5xx responses and
|
||||
network errors — 4xx errors are treated as final and not retried.
|
||||
|
||||
— Back to task: refactoring the auth middleware in src/middleware/auth.ts
|
||||
```
|
||||
|
||||
```
|
||||
User: /aside is the approach we're taking thread-safe?
|
||||
|
||||
ASIDE: is the current approach thread-safe?
|
||||
|
||||
No — the shared cache object in src/cache/store.ts:34 is mutated without locking.
|
||||
Under concurrent requests this is a race condition. It's low risk in a single-process
|
||||
Node.js server but would be a real problem with worker threads or clustering.
|
||||
|
||||
⚠️ Note: This could affect the feature we're building. Want to address this now or continue and fix it in a follow-up?
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 注意事项
|
||||
|
||||
* 在旁述期间**绝不**修改文件——仅限只读访问
|
||||
* 旁述是对话暂停,不是新任务——必须始终恢复原始任务
|
||||
* 保持回答聚焦:目标是快速为用户扫清障碍,而不是进行长篇大论
|
||||
* 如果旁述引发了更广泛的讨论,请先完成当前任务,除非旁述揭示了阻碍
|
||||
* 除非明确与任务结果相关,否则旁述内容不会保存到会话文件中
|
||||
@@ -345,7 +345,10 @@ Quarantine recommendation: Mark as test.fixme() until fixed
|
||||
|
||||
## 相关代理
|
||||
|
||||
此命令调用位于 `~/.claude/agents/e2e-runner.md` 的 `e2e-runner` 代理。
|
||||
此命令调用由 ECC 提供的 `e2e-runner` 代理。
|
||||
|
||||
对于手动安装,源文件位于:
|
||||
`agents/e2e-runner.md`
|
||||
|
||||
## 快速命令
|
||||
|
||||
|
||||
72
docs/zh-CN/commands/gradle-build.md
Normal file
72
docs/zh-CN/commands/gradle-build.md
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
description: 修复 Android 和 KMP 项目的 Gradle 构建错误
|
||||
---
|
||||
|
||||
# Gradle 构建修复
|
||||
|
||||
逐步修复 Android 和 Kotlin 多平台项目的 Gradle 构建和编译错误。
|
||||
|
||||
## 步骤 1:检测构建配置
|
||||
|
||||
识别项目类型并运行相应的构建:
|
||||
|
||||
| 指示符 | 构建命令 |
|
||||
|-----------|---------------|
|
||||
| `build.gradle.kts` + `composeApp/` (KMP) | `./gradlew composeApp:compileKotlinMetadata 2>&1` |
|
||||
| `build.gradle.kts` + `app/` (Android) | `./gradlew app:compileDebugKotlin 2>&1` |
|
||||
| `settings.gradle.kts` 包含模块 | `./gradlew assemble 2>&1` |
|
||||
| 配置了 Detekt | `./gradlew detekt 2>&1` |
|
||||
|
||||
同时检查 `gradle.properties` 和 `local.properties` 以获取配置信息。
|
||||
|
||||
## 步骤 2:解析并分组错误
|
||||
|
||||
1. 运行构建命令并捕获输出
|
||||
2. 将 Kotlin 编译错误与 Gradle 配置错误分开
|
||||
3. 按模块和文件路径分组
|
||||
4. 排序:先处理配置错误,然后按依赖顺序处理编译错误
|
||||
|
||||
## 步骤 3:修复循环
|
||||
|
||||
针对每个错误:
|
||||
|
||||
1. **读取文件** — 错误行周围的完整上下文
|
||||
2. **诊断** — 常见类别:
|
||||
* 缺少导入或无法解析的引用
|
||||
* 类型不匹配或不兼容的类型
|
||||
* `build.gradle.kts` 中缺少依赖项
|
||||
* Expect/actual 不匹配 (KMP)
|
||||
* Compose 编译器错误
|
||||
3. **最小化修复** — 解决错误所需的最小改动
|
||||
4. **重新运行构建** — 验证修复并检查新错误
|
||||
5. **继续** — 处理下一个错误
|
||||
|
||||
## 步骤 4:防护措施
|
||||
|
||||
如果出现以下情况,请停止并询问用户:
|
||||
|
||||
* 修复引入的错误比解决的错误多
|
||||
* 同一错误在 3 次尝试后仍然存在
|
||||
* 错误需要添加新的依赖项或更改模块结构
|
||||
* Gradle 同步本身失败(配置阶段错误)
|
||||
* 错误出现在生成的代码中(Room、SQLDelight、KSP)
|
||||
|
||||
## 步骤 5:总结
|
||||
|
||||
报告:
|
||||
|
||||
* 已修复的错误(模块、文件、描述)
|
||||
* 剩余的错误
|
||||
* 引入的新错误(应为零)
|
||||
* 建议的后续步骤
|
||||
|
||||
## 常见的 Gradle/KMP 修复方案
|
||||
|
||||
| 错误 | 修复方法 |
|
||||
|-------|-----|
|
||||
| `commonMain` 中无法解析的引用 | 检查依赖项是否在 `commonMain.dependencies {}` 中 |
|
||||
| Expect 声明没有 actual 实现 | 在每个平台源码集中添加 `actual` 实现 |
|
||||
| Compose 编译器版本不匹配 | 在 `libs.versions.toml` 中统一 Kotlin 和 Compose 编译器版本 |
|
||||
| 重复类 | 使用 `./gradlew dependencies` 检查是否存在冲突的依赖项 |
|
||||
| KSP 错误 | 运行 `./gradlew kspCommonMainKotlinMetadata` 重新生成 |
|
||||
| 配置缓存问题 | 检查是否存在不可序列化的任务输入 |
|
||||
176
docs/zh-CN/commands/kotlin-build.md
Normal file
176
docs/zh-CN/commands/kotlin-build.md
Normal file
@@ -0,0 +1,176 @@
|
||||
---
|
||||
description: 逐步修复 Kotlin/Gradle 构建错误、编译器警告和依赖项问题。调用 kotlin-build-resolver 代理进行最小化、精准的修复。
|
||||
---
|
||||
|
||||
# Kotlin 构建与修复
|
||||
|
||||
此命令调用 **kotlin-build-resolver** 代理,以最小的改动增量修复 Kotlin 构建错误。
|
||||
|
||||
## 此命令的作用
|
||||
|
||||
1. **运行诊断**:执行 `./gradlew build`、`detekt`、`ktlintCheck`
|
||||
2. **解析错误**:按文件分组并按严重性排序
|
||||
3. **增量修复**:每次修复一个错误
|
||||
4. **验证每次修复**:每次更改后重新运行构建
|
||||
5. **报告摘要**:显示已修复的内容和剩余问题
|
||||
|
||||
## 何时使用
|
||||
|
||||
在以下情况使用 `/kotlin-build`:
|
||||
|
||||
* `./gradlew build` 因错误而失败
|
||||
* Kotlin 编译器报告错误
|
||||
* `./gradlew detekt` 报告违规
|
||||
* Gradle 依赖项解析失败
|
||||
* 拉取更改后导致构建失败
|
||||
|
||||
## 运行的诊断命令
|
||||
|
||||
```bash
|
||||
# Primary build check
|
||||
./gradlew build 2>&1
|
||||
|
||||
# Static analysis
|
||||
./gradlew detekt 2>&1 || echo "detekt not configured"
|
||||
./gradlew ktlintCheck 2>&1 || echo "ktlint not configured"
|
||||
|
||||
# Dependency issues
|
||||
./gradlew dependencies --configuration runtimeClasspath 2>&1 | head -100
|
||||
|
||||
# Optional deep refresh when caches or dependency metadata are suspect
|
||||
./gradlew build --refresh-dependencies
|
||||
```
|
||||
|
||||
## 示例会话
|
||||
|
||||
````text
|
||||
User: /kotlin-build
|
||||
|
||||
Agent:
|
||||
# Kotlin Build Resolution
|
||||
|
||||
## Initial Diagnostics
|
||||
|
||||
```bash
|
||||
$ ./gradlew build
|
||||
e: src/main/kotlin/com/example/service/UserService.kt:25:15 Unresolved reference: UserRepository
|
||||
e: src/main/kotlin/com/example/routes/UserRoutes.kt:42:9 Type mismatch: inferred type is String but Int was expected
|
||||
e: src/main/kotlin/com/example/routes/UserRoutes.kt:58:5 'when' expression must be exhaustive
|
||||
```
|
||||
|
||||
Errors found: 3
|
||||
|
||||
## Fix 1: Unresolved Reference
|
||||
|
||||
File: src/main/kotlin/com/example/service/UserService.kt:25
|
||||
Error: Unresolved reference: UserRepository
|
||||
Cause: Missing import
|
||||
|
||||
```kotlin
|
||||
// Added import
|
||||
import com.example.repository.UserRepository
|
||||
```
|
||||
|
||||
```bash
|
||||
$ ./gradlew build
|
||||
# 2 errors remaining
|
||||
```
|
||||
|
||||
## Fix 2: Type Mismatch
|
||||
|
||||
File: src/main/kotlin/com/example/routes/UserRoutes.kt:42
|
||||
Error: Type mismatch: inferred type is String but Int was expected
|
||||
|
||||
```kotlin
|
||||
// Changed
|
||||
val count = call.parameters["count"]
|
||||
// To
|
||||
val count = call.parameters["count"]?.toIntOrNull()
|
||||
?: return@get call.respond(HttpStatusCode.BadRequest, "Invalid count")
|
||||
```
|
||||
|
||||
```bash
|
||||
$ ./gradlew build
|
||||
# 1 error remaining
|
||||
```
|
||||
|
||||
## Fix 3: Non-Exhaustive When
|
||||
|
||||
File: src/main/kotlin/com/example/routes/UserRoutes.kt:58
|
||||
Error: 'when' expression must be exhaustive
|
||||
|
||||
```kotlin
|
||||
// Added missing branch
|
||||
when (user.role) {
|
||||
Role.ADMIN -> handleAdmin(user)
|
||||
Role.USER -> handleUser(user)
|
||||
Role.MODERATOR -> handleModerator(user) // Added
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
$ ./gradlew build
|
||||
# Build successful!
|
||||
```
|
||||
|
||||
## Final Verification
|
||||
|
||||
```bash
|
||||
$ ./gradlew detekt
|
||||
# No issues
|
||||
|
||||
$ ./gradlew test
|
||||
# All tests passed
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
| Metric | Count |
|
||||
|--------|-------|
|
||||
| Build errors fixed | 3 |
|
||||
| Detekt issues fixed | 0 |
|
||||
| Files modified | 2 |
|
||||
| Remaining issues | 0 |
|
||||
|
||||
Build Status: ✅ SUCCESS
|
||||
````
|
||||
|
||||
## 常见的已修复错误
|
||||
|
||||
| 错误 | 典型修复方法 |
|
||||
|-------|-------------|
|
||||
| `Unresolved reference: X` | 添加导入或依赖项 |
|
||||
| `Type mismatch` | 修复类型转换或赋值 |
|
||||
| `'when' must be exhaustive` | 添加缺失的密封类分支 |
|
||||
| `Suspend function can only be called from coroutine` | 添加 `suspend` 修饰符 |
|
||||
| `Smart cast impossible` | 使用局部 `val` 或 `let` |
|
||||
| `None of the following candidates is applicable` | 修复参数类型 |
|
||||
| `Could not resolve dependency` | 修复版本或添加仓库 |
|
||||
|
||||
## 修复策略
|
||||
|
||||
1. **首先修复构建错误** - 代码必须能够编译
|
||||
2. **其次修复 Detekt 违规** - 修复代码质量问题
|
||||
3. **再次修复 ktlint 警告** - 修复格式问题
|
||||
4. **一次修复一个** - 验证每次更改
|
||||
5. **最小化改动** - 不进行重构,仅修复问题
|
||||
|
||||
## 停止条件
|
||||
|
||||
代理将在以下情况下停止并报告:
|
||||
|
||||
* 同一错误尝试修复 3 次后仍然存在
|
||||
* 修复引入了更多错误
|
||||
* 需要进行架构性更改
|
||||
* 缺少外部依赖项
|
||||
|
||||
## 相关命令
|
||||
|
||||
* `/kotlin-test` - 构建成功后运行测试
|
||||
* `/kotlin-review` - 审查代码质量
|
||||
* `/verify` - 完整的验证循环
|
||||
|
||||
## 相关
|
||||
|
||||
* 代理:`agents/kotlin-build-resolver.md`
|
||||
* 技能:`skills/kotlin-patterns/`
|
||||
144
docs/zh-CN/commands/kotlin-review.md
Normal file
144
docs/zh-CN/commands/kotlin-review.md
Normal file
@@ -0,0 +1,144 @@
|
||||
---
|
||||
description: 全面的Kotlin代码审查,涵盖惯用模式、空安全、协程安全和安全性。调用kotlin-reviewer代理。
|
||||
---
|
||||
|
||||
# Kotlin 代码审查
|
||||
|
||||
此命令调用 **kotlin-reviewer** 代理进行全面的 Kotlin 专项代码审查。
|
||||
|
||||
## 此命令的功能
|
||||
|
||||
1. **识别 Kotlin 变更**:通过 `git diff` 查找修改过的 `.kt` 和 `.kts` 文件
|
||||
2. **运行构建与静态分析**:执行 `./gradlew build`、`detekt`、`ktlintCheck`
|
||||
3. **安全扫描**:检查 SQL 注入、命令注入、硬编码的密钥
|
||||
4. **空安全审查**:分析 `!!` 的使用、平台类型处理、不安全的转换
|
||||
5. **协程审查**:检查结构化并发、调度器使用、取消操作
|
||||
6. **生成报告**:按严重性对问题分类
|
||||
|
||||
## 使用时机
|
||||
|
||||
在以下情况使用 `/kotlin-review`:
|
||||
|
||||
* 编写或修改 Kotlin 代码后
|
||||
* 提交 Kotlin 变更前
|
||||
* 审查包含 Kotlin 代码的拉取请求时
|
||||
* 接手新的 Kotlin 代码库时
|
||||
* 学习 Kotlin 惯用模式时
|
||||
|
||||
## 审查类别
|
||||
|
||||
### 严重(必须修复)
|
||||
|
||||
* SQL/命令注入漏洞
|
||||
* 无正当理由强制解包 `!!`
|
||||
* 平台类型空安全违规
|
||||
* 使用 GlobalScope(违反结构化并发)
|
||||
* 硬编码的凭证
|
||||
* 不安全的反序列化
|
||||
|
||||
### 高(应该修复)
|
||||
|
||||
* 可变状态,而不可变状态即可满足
|
||||
* 在协程上下文中进行阻塞调用
|
||||
* 长循环中缺少取消检查
|
||||
* 对密封类型使用非穷举的 `when`
|
||||
* 函数过大(>50 行)
|
||||
* 嵌套过深(>4 层)
|
||||
|
||||
### 中(考虑修复)
|
||||
|
||||
* 非 Kotlin 惯用写法(Java 风格模式)
|
||||
* 缺少尾随逗号
|
||||
* 误用或嵌套作用域函数
|
||||
* 大型集合链中缺少序列化
|
||||
* 冗余的显式类型声明
|
||||
|
||||
## 运行的自动化检查
|
||||
|
||||
```bash
|
||||
# Build check
|
||||
./gradlew build
|
||||
|
||||
# Static analysis
|
||||
./gradlew detekt
|
||||
|
||||
# Formatting check
|
||||
./gradlew ktlintCheck
|
||||
|
||||
# Tests
|
||||
./gradlew test
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
````text
|
||||
User: /kotlin-review
|
||||
|
||||
Agent:
|
||||
# Kotlin Code Review Report
|
||||
|
||||
## Files Reviewed
|
||||
- src/main/kotlin/com/example/service/UserService.kt (modified)
|
||||
- src/main/kotlin/com/example/routes/UserRoutes.kt (modified)
|
||||
|
||||
## Static Analysis Results
|
||||
✓ Build: Successful
|
||||
✓ detekt: No issues
|
||||
⚠ ktlint: 2 formatting warnings
|
||||
|
||||
## Issues Found
|
||||
|
||||
[CRITICAL] Force-Unwrap Null Safety
|
||||
File: src/main/kotlin/com/example/service/UserService.kt:28
|
||||
Issue: Using !! on nullable repository result
|
||||
```kotlin
|
||||
val user = repository.findById(id)!! // NPE risk
|
||||
```
|
||||
Fix: Use safe call with error handling
|
||||
```kotlin
|
||||
val user = repository.findById(id)
|
||||
?: throw UserNotFoundException("User $id not found")
|
||||
```
|
||||
|
||||
[HIGH] GlobalScope Usage
|
||||
File: src/main/kotlin/com/example/routes/UserRoutes.kt:45
|
||||
Issue: Using GlobalScope breaks structured concurrency
|
||||
```kotlin
|
||||
GlobalScope.launch {
|
||||
notificationService.sendWelcome(user)
|
||||
}
|
||||
```
|
||||
Fix: Use the call's coroutine scope
|
||||
```kotlin
|
||||
launch {
|
||||
notificationService.sendWelcome(user)
|
||||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
- CRITICAL: 1
|
||||
- HIGH: 1
|
||||
- MEDIUM: 0
|
||||
|
||||
Recommendation: ❌ Block merge until CRITICAL issue is fixed
|
||||
````
|
||||
|
||||
## 批准标准
|
||||
|
||||
| 状态 | 条件 |
|
||||
|--------|-----------|
|
||||
| ✅ 批准 | 无严重或高优先级问题 |
|
||||
| ⚠️ 警告 | 仅存在中优先级问题(谨慎合并) |
|
||||
| ❌ 阻止 | 发现严重或高优先级问题 |
|
||||
|
||||
## 与其他命令的集成
|
||||
|
||||
* 首先使用 `/kotlin-test` 确保测试通过
|
||||
* 如果构建出错,使用 `/kotlin-build`
|
||||
* 提交前使用 `/kotlin-review`
|
||||
* 对于非 Kotlin 专项问题,使用 `/code-review`
|
||||
|
||||
## 相关
|
||||
|
||||
* 代理:`agents/kotlin-reviewer.md`
|
||||
* 技能:`skills/kotlin-patterns/`、`skills/kotlin-testing/`
|
||||
315
docs/zh-CN/commands/kotlin-test.md
Normal file
315
docs/zh-CN/commands/kotlin-test.md
Normal file
@@ -0,0 +1,315 @@
|
||||
---
|
||||
description: 为Kotlin强制执行TDD工作流程。首先编写Kotest测试,然后实施。使用Kover验证80%以上的覆盖率。
|
||||
---
|
||||
|
||||
# Kotlin TDD 命令
|
||||
|
||||
此命令使用 Kotest、MockK 和 Kover 为 Kotlin 代码强制执行测试驱动开发方法。
|
||||
|
||||
## 此命令的作用
|
||||
|
||||
1. **定义类型/接口**:首先搭建函数签名
|
||||
2. **编写 Kotest 测试**:创建全面的测试规范(RED)
|
||||
3. **运行测试**:验证测试因正确原因而失败
|
||||
4. **实现代码**:编写最少的代码以通过测试(GREEN)
|
||||
5. **重构**:在保持测试通过的同时进行改进
|
||||
6. **检查覆盖率**:确保使用 Kover 达到 80% 以上的覆盖率
|
||||
|
||||
## 何时使用
|
||||
|
||||
在以下情况下使用 `/kotlin-test`:
|
||||
|
||||
* 实现新的 Kotlin 函数或类
|
||||
* 为现有的 Kotlin 代码添加测试覆盖率
|
||||
* 修复错误(首先编写失败的测试)
|
||||
* 构建关键业务逻辑
|
||||
* 学习 Kotlin 中的 TDD 工作流程
|
||||
|
||||
## TDD 循环
|
||||
|
||||
```
|
||||
RED -> Write failing Kotest test
|
||||
GREEN -> Implement minimal code to pass
|
||||
REFACTOR -> Improve code, tests stay green
|
||||
REPEAT -> Next test case
|
||||
```
|
||||
|
||||
## 示例会话
|
||||
|
||||
````text
|
||||
User: /kotlin-test I need a function to validate user registration requests
|
||||
|
||||
Agent:
|
||||
# TDD Session: Registration Validator
|
||||
|
||||
## Step 1: Define Interface
|
||||
|
||||
```kotlin
|
||||
// validator/RegistrationValidator.kt
|
||||
package com.example.validator
|
||||
|
||||
data class RegistrationRequest(
|
||||
val name: String,
|
||||
val email: String,
|
||||
val password: String,
|
||||
)
|
||||
|
||||
sealed class ValidationResult {
|
||||
data object Valid : ValidationResult()
|
||||
data class Invalid(val errors: List<String>) : ValidationResult()
|
||||
}
|
||||
|
||||
fun validateRegistration(request: RegistrationRequest): ValidationResult {
|
||||
TODO("not implemented")
|
||||
}
|
||||
```
|
||||
|
||||
## Step 2: Write Kotest Tests (RED)
|
||||
|
||||
```kotlin
|
||||
// validator/RegistrationValidatorTest.kt
|
||||
package com.example.validator
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.types.shouldBeInstanceOf
|
||||
|
||||
class RegistrationValidatorTest : FunSpec({
|
||||
test("valid registration returns Valid") {
|
||||
val request = RegistrationRequest(
|
||||
name = "Alice",
|
||||
email = "alice@example.com",
|
||||
password = "SecureP@ss1",
|
||||
)
|
||||
|
||||
val result = validateRegistration(request)
|
||||
|
||||
result.shouldBeInstanceOf<ValidationResult.Valid>()
|
||||
}
|
||||
|
||||
test("blank name returns Invalid") {
|
||||
val request = RegistrationRequest(
|
||||
name = "",
|
||||
email = "alice@example.com",
|
||||
password = "SecureP@ss1",
|
||||
)
|
||||
|
||||
val result = validateRegistration(request)
|
||||
|
||||
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
|
||||
invalid.errors shouldBe listOf("Name is required")
|
||||
}
|
||||
|
||||
test("invalid email returns Invalid") {
|
||||
val request = RegistrationRequest(
|
||||
name = "Alice",
|
||||
email = "not-an-email",
|
||||
password = "SecureP@ss1",
|
||||
)
|
||||
|
||||
val result = validateRegistration(request)
|
||||
|
||||
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
|
||||
invalid.errors shouldBe listOf("Invalid email format")
|
||||
}
|
||||
|
||||
test("short password returns Invalid") {
|
||||
val request = RegistrationRequest(
|
||||
name = "Alice",
|
||||
email = "alice@example.com",
|
||||
password = "short",
|
||||
)
|
||||
|
||||
val result = validateRegistration(request)
|
||||
|
||||
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
|
||||
invalid.errors shouldBe listOf("Password must be at least 8 characters")
|
||||
}
|
||||
|
||||
test("multiple errors returns all errors") {
|
||||
val request = RegistrationRequest(
|
||||
name = "",
|
||||
email = "bad",
|
||||
password = "short",
|
||||
)
|
||||
|
||||
val result = validateRegistration(request)
|
||||
|
||||
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
|
||||
invalid.errors.size shouldBe 3
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 3: Run Tests - Verify FAIL
|
||||
|
||||
```bash
|
||||
$ ./gradlew test
|
||||
|
||||
RegistrationValidatorTest > valid registration returns Valid FAILED
|
||||
kotlin.NotImplementedError: An operation is not implemented
|
||||
|
||||
FAILED (5 tests, 0 passed, 5 failed)
|
||||
```
|
||||
|
||||
✓ Tests fail as expected (NotImplementedError).
|
||||
|
||||
## Step 4: Implement Minimal Code (GREEN)
|
||||
|
||||
```kotlin
|
||||
// validator/RegistrationValidator.kt
|
||||
package com.example.validator
|
||||
|
||||
private val EMAIL_REGEX = Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")
|
||||
private const val MIN_PASSWORD_LENGTH = 8
|
||||
|
||||
fun validateRegistration(request: RegistrationRequest): ValidationResult {
|
||||
val errors = buildList {
|
||||
if (request.name.isBlank()) add("Name is required")
|
||||
if (!EMAIL_REGEX.matches(request.email)) add("Invalid email format")
|
||||
if (request.password.length < MIN_PASSWORD_LENGTH) add("Password must be at least $MIN_PASSWORD_LENGTH characters")
|
||||
}
|
||||
|
||||
return if (errors.isEmpty()) ValidationResult.Valid
|
||||
else ValidationResult.Invalid(errors)
|
||||
}
|
||||
```
|
||||
|
||||
## Step 5: Run Tests - Verify PASS
|
||||
|
||||
```bash
|
||||
$ ./gradlew test
|
||||
|
||||
RegistrationValidatorTest > valid registration returns Valid PASSED
|
||||
RegistrationValidatorTest > blank name returns Invalid PASSED
|
||||
RegistrationValidatorTest > invalid email returns Invalid PASSED
|
||||
RegistrationValidatorTest > short password returns Invalid PASSED
|
||||
RegistrationValidatorTest > multiple errors returns all errors PASSED
|
||||
|
||||
PASSED (5 tests, 5 passed, 0 failed)
|
||||
```
|
||||
|
||||
✓ All tests passing!
|
||||
|
||||
## Step 6: Check Coverage
|
||||
|
||||
```bash
|
||||
$ ./gradlew koverHtmlReport
|
||||
|
||||
Coverage: 100.0% of statements
|
||||
```
|
||||
|
||||
✓ Coverage: 100%
|
||||
|
||||
## TDD Complete!
|
||||
````
|
||||
|
||||
## 测试模式
|
||||
|
||||
### StringSpec(最简单)
|
||||
|
||||
```kotlin
|
||||
class CalculatorTest : StringSpec({
|
||||
"add two positive numbers" {
|
||||
Calculator.add(2, 3) shouldBe 5
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### BehaviorSpec(BDD)
|
||||
|
||||
```kotlin
|
||||
class OrderServiceTest : BehaviorSpec({
|
||||
Given("a valid order") {
|
||||
When("placed") {
|
||||
Then("should be confirmed") { /* ... */ }
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 数据驱动测试
|
||||
|
||||
```kotlin
|
||||
class ParserTest : FunSpec({
|
||||
context("valid inputs") {
|
||||
withData("2026-01-15", "2026-12-31", "2000-01-01") { input ->
|
||||
parseDate(input).shouldNotBeNull()
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 协程测试
|
||||
|
||||
```kotlin
|
||||
class AsyncServiceTest : FunSpec({
|
||||
test("concurrent fetch completes") {
|
||||
runTest {
|
||||
val result = service.fetchAll()
|
||||
result.shouldNotBeEmpty()
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 覆盖率命令
|
||||
|
||||
```bash
|
||||
# Run tests with coverage
|
||||
./gradlew koverHtmlReport
|
||||
|
||||
# Verify coverage thresholds
|
||||
./gradlew koverVerify
|
||||
|
||||
# XML report for CI
|
||||
./gradlew koverXmlReport
|
||||
|
||||
# Open HTML report
|
||||
open build/reports/kover/html/index.html
|
||||
|
||||
# Run specific test class
|
||||
./gradlew test --tests "com.example.UserServiceTest"
|
||||
|
||||
# Run with verbose output
|
||||
./gradlew test --info
|
||||
```
|
||||
|
||||
## 覆盖率目标
|
||||
|
||||
| 代码类型 | 目标 |
|
||||
|-----------|--------|
|
||||
| 关键业务逻辑 | 100% |
|
||||
| 公共 API | 90%+ |
|
||||
| 通用代码 | 80%+ |
|
||||
| 生成的代码 | 排除 |
|
||||
|
||||
## TDD 最佳实践
|
||||
|
||||
**应做:**
|
||||
|
||||
* 首先编写测试,在任何实现之前
|
||||
* 每次更改后运行测试
|
||||
* 使用 Kotest 匹配器进行表达性断言
|
||||
* 使用 MockK 的 `coEvery`/`coVerify` 来处理挂起函数
|
||||
* 测试行为,而非实现细节
|
||||
* 包含边界情况(空值、null、最大值)
|
||||
|
||||
**不应做:**
|
||||
|
||||
* 在测试之前编写实现
|
||||
* 跳过 RED 阶段
|
||||
* 直接测试私有函数
|
||||
* 在协程测试中使用 `Thread.sleep()`
|
||||
* 忽略不稳定的测试
|
||||
|
||||
## 相关命令
|
||||
|
||||
* `/kotlin-build` - 修复构建错误
|
||||
* `/kotlin-review` - 在实现后审查代码
|
||||
* `/verify` - 运行完整的验证循环
|
||||
|
||||
## 相关
|
||||
|
||||
* 技能:`skills/kotlin-testing/`
|
||||
* 技能:`skills/tdd-workflow/`
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
description: 从会话中提取可重用模式,在保存前自我评估质量,并确定正确的保存位置(全局与项目)。
|
||||
description: "从会话中提取可重用模式,在保存前自我评估质量,并确定正确的保存位置(全局与项目)。"
|
||||
---
|
||||
|
||||
# /learn-eval - 提取、评估、然后保存
|
||||
|
||||
扩展 `/learn`,在写入任何技能文件之前加入质量门和保存位置决策。
|
||||
扩展 `/learn`,在编写任何技能文件之前,加入质量门控、保存位置决策和知识放置意识。
|
||||
|
||||
## 提取内容
|
||||
|
||||
@@ -52,41 +52,66 @@ origin: auto-extracted
|
||||
[触发条件]
|
||||
```
|
||||
|
||||
5. **在保存前自我评估**,使用此评分标准:
|
||||
5. **质量门控 — 清单 + 整体裁决**
|
||||
|
||||
| 维度 | 1 | 3 | 5 |
|
||||
|-----------|---|---|---|
|
||||
| 具体性 | 仅抽象原则,无代码示例 | 有代表性代码示例 | 包含所有使用模式的丰富示例 |
|
||||
| 可操作性 | 不清楚要做什么 | 主要步骤可理解 | 立即可操作,涵盖边界情况 |
|
||||
| 范围契合度 | 过于宽泛或过于狭窄 | 基本合适,存在一些边界模糊 | 名称、触发器和内容完美匹配 |
|
||||
| 非冗余性 | 几乎与另一技能相同 | 存在一些重叠但有独特视角 | 完全独特的价值 |
|
||||
| 覆盖率 | 仅涵盖目标任务的一小部分 | 涵盖主要情况,缺少常见变体 | 涵盖主要情况、边界情况和陷阱 |
|
||||
### 5a. 必需清单(通过实际阅读文件进行验证)
|
||||
|
||||
* 为每个维度评分 1–5
|
||||
* 如果任何维度评分为 1–2,改进草案并重新评分,直到所有维度 ≥ 3
|
||||
* 向用户展示评分表和最终草案
|
||||
在评估草案**之前**,执行以下所有操作:
|
||||
|
||||
6. 请求用户确认:
|
||||
* 展示:提议的保存路径 + 评分表 + 最终草案
|
||||
* 在写入前等待明确确认
|
||||
* \[ ] 使用关键字在 `~/.claude/skills/` 和相关项目的 `.claude/skills/` 文件中进行 grep 搜索,检查内容重叠
|
||||
* \[ ] 检查 MEMORY.md(项目级和全局级)以查找重叠内容
|
||||
* \[ ] 考虑是否追加到现有技能即可满足需求
|
||||
* \[ ] 确认这是一个可复用的模式,而非一次性修复
|
||||
|
||||
7. 保存到确定的位置
|
||||
### 5b. 整体裁决
|
||||
|
||||
## 第 5 步的输出格式(评分表)
|
||||
综合清单结果和草案质量,然后选择**以下一项**:
|
||||
|
||||
| 维度 | 评分 | 理由 |
|
||||
|-----------|-------|-----------|
|
||||
| 具体性 | N/5 | ... |
|
||||
| 可操作性 | N/5 | ... |
|
||||
| 范围契合度 | N/5 | ... |
|
||||
| 非冗余性 | N/5 | ... |
|
||||
| 覆盖率 | N/5 | ... |
|
||||
| **总计** | **N/25** | |
|
||||
| 裁决 | 含义 | 下一步行动 |
|
||||
|---------|---------|-------------|
|
||||
| **保存** | 独特、具体、范围明确 | 进行到步骤 6 |
|
||||
| **改进后保存** | 有价值但需要改进 | 列出改进项 → 修订 → 重新评估(一次) |
|
||||
| **吸收到 \[X]** | 应追加到现有技能 | 显示目标技能和添加内容 → 步骤 6 |
|
||||
| **放弃** | 琐碎、冗余或过于抽象 | 解释原因并停止 |
|
||||
|
||||
**指导维度**(用于告知裁决,不进行评分):
|
||||
|
||||
* **具体性和可操作性**:包含可立即使用的代码示例或命令
|
||||
* **范围契合度**:名称、触发条件和内容保持一致,并专注于单一模式
|
||||
* **独特性**:提供现有技能未涵盖的价值(基于清单结果)
|
||||
* **可复用性**:在未来的会话中存在现实的触发场景
|
||||
|
||||
6. **裁决特定的确认流程**
|
||||
|
||||
* **改进后保存**:呈现必需的改进项 + 修订后的草案 + 一次重新评估后的更新清单/裁决;如果修订后的裁决是**保存**,则在用户确认后保存,否则遵循新的裁决
|
||||
* **保存**:呈现保存路径 + 清单结果 + 1行裁决理由 + 完整草案 → 在用户确认后保存
|
||||
* **吸收到 \[X]**:呈现目标路径 + 添加内容(diff格式) + 清单结果 + 裁决理由 → 在用户确认后追加
|
||||
* **放弃**:仅显示清单结果 + 推理(无需确认)
|
||||
|
||||
7. 保存 / 吸收到确定的位置
|
||||
|
||||
## 步骤 5 的输出格式
|
||||
|
||||
```
|
||||
### Checklist
|
||||
- [x] skills/ grep: no overlap (or: overlap found → details)
|
||||
- [x] MEMORY.md: no overlap (or: overlap found → details)
|
||||
- [x] Existing skill append: new file appropriate (or: should append to [X])
|
||||
- [x] Reusability: confirmed (or: one-off → Drop)
|
||||
|
||||
### Verdict: Save / Improve then Save / Absorb into [X] / Drop
|
||||
|
||||
**Rationale:** (1-2 sentences explaining the verdict)
|
||||
```
|
||||
|
||||
## 设计原理
|
||||
|
||||
此版本用基于清单的整体裁决系统取代了之前的 5 维度数字评分标准(具体性、可操作性、范围契合度、非冗余性、覆盖度,评分 1-5)。现代前沿模型(Opus 4.6+)具有强大的情境判断能力 —— 将丰富的定性信号强行压缩为数字评分会丢失细微差别,并可能产生误导性的总分。整体方法让模型自然地权衡所有因素,产生更准确的保存/放弃决策,同时明确的清单确保不会跳过任何关键检查。
|
||||
|
||||
## 注意事项
|
||||
|
||||
* 不要提取琐碎的修复(拼写错误、简单的语法错误)
|
||||
* 不要提取一次性问题(特定的 API 中断等)
|
||||
* 专注于能在未来会话中节省时间的模式
|
||||
* 保持技能聚焦 — 每个技能一个模式
|
||||
* 如果覆盖率评分低,在保存前添加相关变体
|
||||
* 专注于那些将在未来会话中节省时间的模式
|
||||
* 保持技能聚焦 —— 每个技能一个模式
|
||||
* 当裁决为“吸收”时,追加到现有技能,而不是创建新文件
|
||||
|
||||
@@ -104,6 +104,14 @@ TaskOutput({ task_id: "<task_id>", block: true, timeout: 600000 })
|
||||
4. 当评分 < 7 或用户不批准时强制停止。
|
||||
5. 需要时(例如确认/选择/批准)使用 `AskUserQuestion` 工具进行用户交互。
|
||||
|
||||
## 何时使用外部编排
|
||||
|
||||
当工作必须拆分给需要隔离的 git 状态、独立终端或独立构建/测试执行的并行工作器时,请使用外部 tmux/工作树编排。对于轻量级分析、规划或审查(其中主会话是唯一的写入者),请使用进程内子代理。
|
||||
|
||||
```bash
|
||||
node scripts/orchestrate-worktrees.js .claude/plan/workflow-e2e-test.json --execute
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 执行工作流程
|
||||
|
||||
@@ -158,6 +158,61 @@ RECOMMENDATION
|
||||
|
||||
```
|
||||
|
||||
对于使用独立 git worktree 的外部 tmux-pane 工作器,请使用 `node scripts/orchestrate-worktrees.js plan.json --execute`。内置的编排模式保持进程内运行;此辅助工具适用于长时间运行或跨测试框架的会话。
|
||||
|
||||
当工作器需要查看主检出目录中的脏文件或未跟踪的本地文件时,请在计划文件中添加 `seedPaths`。ECC 仅在 `git worktree add` 之后,将那些选定的路径覆盖到每个工作器的工作树中,这既能保持分支隔离,又能暴露正在处理的本地脚本、计划或文档。
|
||||
|
||||
```json
|
||||
{
|
||||
"sessionName": "workflow-e2e",
|
||||
"seedPaths": [
|
||||
"scripts/orchestrate-worktrees.js",
|
||||
"scripts/lib/tmux-worktree-orchestrator.js",
|
||||
".claude/plan/workflow-e2e-test.json"
|
||||
],
|
||||
"workers": [
|
||||
{ "name": "docs", "task": "Update orchestration docs." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
要导出实时 tmux/worktree 会话的控制平面快照,请运行:
|
||||
|
||||
```bash
|
||||
node scripts/orchestration-status.js .claude/plan/workflow-visual-proof.json
|
||||
```
|
||||
|
||||
快照包含会话活动、tmux 窗格元数据、工作器状态、目标、已播种的覆盖层以及最近的交接摘要,均以 JSON 格式保存。
|
||||
|
||||
## 操作员指挥中心交接
|
||||
|
||||
当工作流跨越多个会话、工作树或 tmux 窗格时,请在最终交接内容中附加一个控制平面块:
|
||||
|
||||
```markdown
|
||||
控制平面
|
||||
-------------
|
||||
会话:
|
||||
- 活动会话 ID 或别名
|
||||
- 每个活动工作线程的分支 + 工作树路径
|
||||
- 适用时的 tmux 窗格或分离会话名称
|
||||
|
||||
差异:
|
||||
- git 状态摘要
|
||||
- 已修改文件的 git diff --stat
|
||||
- 合并/冲突风险说明
|
||||
|
||||
审批:
|
||||
- 待处理的用户审批
|
||||
- 等待确认的受阻步骤
|
||||
|
||||
遥测:
|
||||
- 最后活动时间戳或空闲信号
|
||||
- 预估的令牌或成本漂移
|
||||
- 由钩子或审查器引发的策略事件
|
||||
```
|
||||
|
||||
这使得规划者、实施者、审查者和循环工作器在操作员界面上保持清晰可辨。
|
||||
|
||||
## 参数
|
||||
|
||||
$ARGUMENTS:
|
||||
|
||||
@@ -112,4 +112,7 @@ Agent (planner):
|
||||
|
||||
## 相关代理
|
||||
|
||||
此命令调用位于 `~/.claude/agents/planner.md` 的 `planner` 代理。
|
||||
此命令调用由 ECC 提供的 `planner` 代理。
|
||||
|
||||
对于手动安装,源文件位于:
|
||||
`agents/planner.md`
|
||||
|
||||
37
docs/zh-CN/commands/prompt-optimize.md
Normal file
37
docs/zh-CN/commands/prompt-optimize.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
description: 分析一个草稿提示,输出一个经过优化、富含ECC的版本,准备粘贴并运行。不执行任务——仅输出咨询分析。
|
||||
---
|
||||
|
||||
# /prompt-optimize
|
||||
|
||||
分析并优化以下提示语,以实现最大化的ECC杠杆效应。
|
||||
|
||||
## 你的任务
|
||||
|
||||
对下方用户的输入应用 **prompt-optimizer** 技能。遵循6阶段分析流程:
|
||||
|
||||
0. **项目检测** — 读取 CLAUDE.md,从项目文件(package.json, go.mod, pyproject.toml 等)检测技术栈
|
||||
1. **意图检测** — 对任务类型进行分类(新功能、错误修复、重构、研究、测试、评审、文档、基础设施、设计)
|
||||
2. **范围评估** — 评估复杂度(简单 / 低 / 中 / 高 / 史诗级),如果检测到代码库,则使用其大小作为信号
|
||||
3. **ECC组件匹配** — 映射到特定的技能、命令、代理和模型层级
|
||||
4. **缺失上下文检测** — 识别信息缺口。如果缺少3个以上关键项,请在生成前请用户澄清
|
||||
5. **工作流与模型** — 确定生命周期阶段,推荐模型层级,如果复杂度为高/史诗级,则将其拆分为多个提示语
|
||||
|
||||
## 输出要求
|
||||
|
||||
* 呈现诊断结果、推荐的ECC组件以及使用 prompt-optimizer 技能中输出格式的优化后提示语
|
||||
* 提供 **完整版本**(详细)和 **快速版本**(紧凑,根据意图类型变化)
|
||||
* 使用与用户输入相同的语言进行回复
|
||||
* 优化后的提示语必须完整且可复制粘贴到新会话中直接使用
|
||||
* 以提供调整选项或明确下一步操作(用于启动单独的执行请求)的页脚结束
|
||||
|
||||
## 关键
|
||||
|
||||
请勿执行用户的任务。仅输出分析结果和优化后的提示语。
|
||||
如果用户要求直接执行,请说明 `/prompt-optimize` 仅产生咨询性输出,并告诉他们应启动一个常规的任务请求。
|
||||
|
||||
注意:`blueprint` 是一个**技能**,而非斜杠命令。请写作“使用蓝图技能”,而不是将其呈现为 `/...` 命令。
|
||||
|
||||
## 用户输入
|
||||
|
||||
$ARGUMENTS
|
||||
@@ -315,6 +315,6 @@ result = "".join(str(item) for item in items)
|
||||
| 海象运算符 (`:=`) | 3.8+ |
|
||||
| 仅限位置参数 | 3.8+ |
|
||||
| Match 语句 | 3.10+ |
|
||||
| 类型联合 (\`x \| None\`) | 3.10+ |
|
||||
| 类型联合 (\`x | None\`) | 3.10+ |
|
||||
|
||||
确保你的项目 `pyproject.toml` 或 `setup.py` 指定了正确的最低 Python 版本。
|
||||
|
||||
155
docs/zh-CN/commands/resume-session.md
Normal file
155
docs/zh-CN/commands/resume-session.md
Normal file
@@ -0,0 +1,155 @@
|
||||
---
|
||||
description: 从 ~/.claude/sessions/ 加载最新的会话文件,并从上次会话结束的地方恢复工作,保留完整上下文。
|
||||
---
|
||||
|
||||
# 恢复会话命令
|
||||
|
||||
加载最后保存的会话状态,并在开始任何工作前完全熟悉情况。
|
||||
此命令是 `/save-session` 的对应命令。
|
||||
|
||||
## 何时使用
|
||||
|
||||
* 开始新会话以继续前一天的工作时
|
||||
* 因上下文限制而开始全新会话后
|
||||
* 当从其他来源移交会话文件时(只需提供文件路径)
|
||||
* 任何拥有会话文件并希望 Claude 在继续前完全吸收其内容的时候
|
||||
|
||||
## 用法
|
||||
|
||||
```
|
||||
/resume-session # loads most recent file in ~/.claude/sessions/
|
||||
/resume-session 2024-01-15 # loads most recent session for that date
|
||||
/resume-session ~/.claude/sessions/2024-01-15-session.tmp # loads a specific legacy-format file
|
||||
/resume-session ~/.claude/sessions/2024-01-15-abc123de-session.tmp # loads a current short-id session file
|
||||
```
|
||||
|
||||
## 流程
|
||||
|
||||
### 步骤 1:查找会话文件
|
||||
|
||||
如果未提供参数:
|
||||
|
||||
1. 检查 `~/.claude/sessions/`
|
||||
2. 选择最近修改的 `*-session.tmp` 文件
|
||||
3. 如果文件夹不存在或没有匹配的文件,告知用户:
|
||||
```
|
||||
在 ~/.claude/sessions/ 中未找到会话文件。
|
||||
请在会话结束时运行 /save-session 来创建一个。
|
||||
```
|
||||
然后停止。
|
||||
|
||||
如果提供了参数:
|
||||
|
||||
* 如果看起来像日期 (`YYYY-MM-DD`),则在 `~/.claude/sessions/` 中搜索匹配
|
||||
`YYYY-MM-DD-session.tmp`(旧格式)或 `YYYY-MM-DD-<shortid>-session.tmp`(当前格式)的文件,
|
||||
并加载该日期最近修改的版本
|
||||
* 如果看起来像文件路径,则直接读取该文件
|
||||
* 如果未找到,清晰报告并停止
|
||||
|
||||
### 步骤 2:读取整个会话文件
|
||||
|
||||
读取完整的文件。暂时不要总结。
|
||||
|
||||
### 步骤 3:确认理解
|
||||
|
||||
使用以下确切格式回复一份结构化简报:
|
||||
|
||||
```
|
||||
SESSION LOADED: [actual resolved path to the file]
|
||||
════════════════════════════════════════════════
|
||||
|
||||
PROJECT: [project name / topic from file]
|
||||
|
||||
WHAT WE'RE BUILDING:
|
||||
[2-3 sentence summary in your own words]
|
||||
|
||||
CURRENT STATE:
|
||||
✅ Working: [count] items confirmed
|
||||
🔄 In Progress: [list files that are in progress]
|
||||
🗒️ Not Started: [list planned but untouched]
|
||||
|
||||
WHAT NOT TO RETRY:
|
||||
[list every failed approach with its reason — this is critical]
|
||||
|
||||
OPEN QUESTIONS / BLOCKERS:
|
||||
[list any blockers or unanswered questions]
|
||||
|
||||
NEXT STEP:
|
||||
[exact next step if defined in the file]
|
||||
[if not defined: "No next step defined — recommend reviewing 'What Has NOT Been Tried Yet' together before starting"]
|
||||
|
||||
════════════════════════════════════════════════
|
||||
Ready to continue. What would you like to do?
|
||||
```
|
||||
|
||||
### 步骤 4:等待用户
|
||||
|
||||
请**不要**自动开始工作。请**不要**触碰任何文件。等待用户指示下一步做什么。
|
||||
|
||||
如果会话文件中明确定义了下一步,并且用户说"继续"或"是"或类似内容 — 则执行该确切步骤。
|
||||
|
||||
如果未定义下一步 — 询问用户从哪里开始,并可选择性地从"尚未尝试的内容"部分提出建议。
|
||||
|
||||
***
|
||||
|
||||
## 边界情况
|
||||
|
||||
**同一日期有多个会话** (`2024-01-15-session.tmp`, `2024-01-15-abc123de-session.tmp`):
|
||||
加载该日期最近修改的匹配文件,无论其使用的是旧的无ID格式还是当前的短ID格式。
|
||||
|
||||
**会话文件引用了已不存在的文件:**
|
||||
在简报中注明 — "⚠️ 会话中引用了 `path/to/file.ts`,但在磁盘上未找到。"
|
||||
|
||||
**会话文件来自超过7天前:**
|
||||
注明时间间隔 — "⚠️ 此会话来自 N 天前(阈值:7天)。情况可能已发生变化。" — 然后正常继续。
|
||||
|
||||
**用户直接提供了文件路径(例如,从队友处转发而来):**
|
||||
读取它并遵循相同的简报流程 — 无论来源如何,格式都是相同的。
|
||||
|
||||
**会话文件为空或格式错误:**
|
||||
报告:"找到会话文件,但似乎为空或无法读取。您可能需要使用 /save-session 创建一个新的。"
|
||||
|
||||
***
|
||||
|
||||
## 示例输出
|
||||
|
||||
```
|
||||
SESSION LOADED: /Users/you/.claude/sessions/2024-01-15-abc123de-session.tmp
|
||||
════════════════════════════════════════════════
|
||||
|
||||
PROJECT: my-app — JWT Authentication
|
||||
|
||||
WHAT WE'RE BUILDING:
|
||||
User authentication with JWT tokens stored in httpOnly cookies.
|
||||
Register and login endpoints are partially done. Route protection
|
||||
via middleware hasn't been started yet.
|
||||
|
||||
CURRENT STATE:
|
||||
✅ Working: 3 items (register endpoint, JWT generation, password hashing)
|
||||
🔄 In Progress: app/api/auth/login/route.ts (token works, cookie not set yet)
|
||||
🗒️ Not Started: middleware.ts, app/login/page.tsx
|
||||
|
||||
WHAT NOT TO RETRY:
|
||||
❌ Next-Auth — conflicts with custom Prisma adapter, threw adapter error on every request
|
||||
❌ localStorage for JWT — causes SSR hydration mismatch, incompatible with Next.js
|
||||
|
||||
OPEN QUESTIONS / BLOCKERS:
|
||||
- Does cookies().set() work inside a Route Handler or only Server Actions?
|
||||
|
||||
NEXT STEP:
|
||||
In app/api/auth/login/route.ts — set the JWT as an httpOnly cookie using
|
||||
cookies().set('token', jwt, { httpOnly: true, secure: true, sameSite: 'strict' })
|
||||
then test with Postman for a Set-Cookie header in the response.
|
||||
|
||||
════════════════════════════════════════════════
|
||||
Ready to continue. What would you like to do?
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 注意事项
|
||||
|
||||
* 加载时切勿修改会话文件 — 它是一个只读的历史记录
|
||||
* 简报格式是固定的 — 即使某些部分为空,也不要跳过
|
||||
* "不应重试的内容"必须始终显示,即使它只是说"无" — 这太重要了,不容遗漏
|
||||
* 恢复后,用户可能希望在新的会话结束时再次运行 `/save-session`,以创建一个新的带日期文件
|
||||
252
docs/zh-CN/commands/save-session.md
Normal file
252
docs/zh-CN/commands/save-session.md
Normal file
@@ -0,0 +1,252 @@
|
||||
---
|
||||
description: 将当前会话状态保存到 ~/.claude/sessions/ 目录下带日期的文件中,以便在未来的会话中恢复完整上下文并继续工作。
|
||||
---
|
||||
|
||||
# 保存会话命令
|
||||
|
||||
捕获本次会话中发生的一切——构建了什么、什么成功了、什么失败了、还有哪些遗留事项——并将其写入一个带日期的文件,以便下次会话能从此处继续。
|
||||
|
||||
## 使用时机
|
||||
|
||||
* 在关闭 Claude Code 之前,工作会话结束时
|
||||
* 在达到上下文限制之前(先运行此命令,然后开始一个新会话)
|
||||
* 解决了一个想要记住的复杂问题之后
|
||||
* 任何需要将上下文移交给未来会话的时候
|
||||
|
||||
## 流程
|
||||
|
||||
### 步骤 1:收集上下文
|
||||
|
||||
在写入文件之前,收集:
|
||||
|
||||
* 读取本次会话期间修改的所有文件(使用 git diff 或从对话中回忆)
|
||||
* 回顾讨论、尝试和决定的内容
|
||||
* 记录遇到的任何错误及其解决方法(或未解决的情况)
|
||||
* 如果相关,检查当前的测试/构建状态
|
||||
|
||||
### 步骤 2:如果不存在则创建会话文件夹
|
||||
|
||||
在用户的 Claude 主目录中创建规范的会话文件夹:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.claude/sessions
|
||||
```
|
||||
|
||||
### 步骤 3:写入会话文件
|
||||
|
||||
创建 `~/.claude/sessions/YYYY-MM-DD-<short-id>-session.tmp`,使用今天的实际日期和一个满足 `session-manager.js` 中 `SESSION_FILENAME_REGEX` 强制规则的短 ID:
|
||||
|
||||
* 允许的字符:小写 `a-z`,数字 `0-9`,连字符 `-`
|
||||
* 最小长度:8 个字符
|
||||
* 不允许大写字母、下划线、空格
|
||||
|
||||
有效示例:`abc123de`、`a1b2c3d4`、`frontend-worktree-1`
|
||||
无效示例:`ABC123de`(大写)、`short`(少于 8 个字符)、`test_id1`(下划线)
|
||||
|
||||
完整有效文件名示例:`2024-01-15-abc123de-session.tmp`
|
||||
|
||||
旧文件名 `YYYY-MM-DD-session.tmp` 仍然有效,但新的会话文件应首选短 ID 形式,以避免同一天的冲突。
|
||||
|
||||
### 步骤 4:用以下所有部分填充文件
|
||||
|
||||
诚实地写入每个部分。不要跳过任何部分——如果某个部分确实没有内容,则写“Nothing yet”或“N/A”。一个不完整的文件比诚实的空部分更糟糕。
|
||||
|
||||
### 步骤 5:向用户展示文件
|
||||
|
||||
写入后,显示完整内容并询问:
|
||||
|
||||
```
|
||||
Session saved to [actual resolved path to the session file]
|
||||
|
||||
Does this look accurate? Anything to correct or add before we close?
|
||||
```
|
||||
|
||||
等待确认。如果用户要求,进行编辑。
|
||||
|
||||
***
|
||||
|
||||
## 会话文件格式
|
||||
|
||||
```markdown
|
||||
# 会话:YYYY-MM-DD
|
||||
|
||||
**开始时间:** [若已知大致时间]
|
||||
**最后更新:** [当前时间]
|
||||
**项目:** [项目名称或路径]
|
||||
**主题:** [关于本次会话的一行摘要]
|
||||
|
||||
---
|
||||
|
||||
## 正在构建的内容
|
||||
|
||||
[1-3段文字,描述功能、错误修复或任务。包含足够的背景信息,让对此会话毫无记忆的人也能理解目标。包含:它做什么、为什么需要它、它如何融入更大的系统。]
|
||||
|
||||
---
|
||||
|
||||
## 已确认有效的工作(附证据)
|
||||
|
||||
[仅列出已确认有效的事项。对于每个事项,说明你如何知道它有效——测试通过、在浏览器中运行、Postman 返回 200 等。没有证据的,请移至"尚未尝试"部分。]
|
||||
|
||||
- **[有效的事项]** — 确认依据:[具体证据]
|
||||
- **[有效的事项]** — 确认依据:[具体证据]
|
||||
|
||||
如果尚无任何事项确认有效:"尚无确认有效的事项——所有方法仍在进行中或未测试。"
|
||||
|
||||
---
|
||||
|
||||
## 无效的事项(及原因)
|
||||
|
||||
[这是最重要的部分。列出所有尝试过但失败的方法。对于每个失败,写出确切原因,以便下次会话不再重试。要具体:"因 Y 而抛出 X 错误"是有用的。"无效"是无用的。]
|
||||
|
||||
- **[尝试过的方法]** — 失败原因:[确切原因 / 错误信息]
|
||||
- **[尝试过的方法]** — 失败原因:[确切原因 / 错误信息]
|
||||
|
||||
如果无失败事项:"尚无失败的方法。"
|
||||
|
||||
---
|
||||
|
||||
## 尚未尝试的事项
|
||||
|
||||
[看起来有希望但尚未尝试的方法。对话中产生的想法。值得探索的替代方案。描述要足够具体,以便下次会话确切知道要尝试什么。]
|
||||
|
||||
- [方法 / 想法]
|
||||
- [方法 / 想法]
|
||||
|
||||
如果无待办事项:"未确定具体的待尝试方法。"
|
||||
|
||||
---
|
||||
|
||||
## 文件当前状态
|
||||
|
||||
[本次会话中修改过的每个文件。准确说明每个文件的状态。]
|
||||
|
||||
| 文件 | 状态 | 备注 |
|
||||
| ----------------- | -------------- | ---------------------------- |
|
||||
| `path/to/file.ts` | ✅ 完成 | [其作用] |
|
||||
| `path/to/file.ts` | 🔄 进行中 | [已完成什么,剩余什么] |
|
||||
| `path/to/file.ts` | ❌ 损坏 | [问题所在] |
|
||||
| `path/to/file.ts` | 🗒️ 未开始 | [计划但尚未接触] |
|
||||
|
||||
如果未修改任何文件:"本次会话未修改任何文件。"
|
||||
|
||||
---
|
||||
|
||||
## 已作出的决策
|
||||
|
||||
[架构选择、接受的权衡、选择的方法及其原因。这些可防止下次会话重新讨论已确定的决策。]
|
||||
|
||||
- **[决策]** — 原因:[选择此方案而非其他方案的原因]
|
||||
|
||||
如果无重大决策:"本次会话未作出重大决策。"
|
||||
|
||||
---
|
||||
|
||||
## 阻碍与待解决问题
|
||||
|
||||
[任何未解决、需要下次会话处理或调查的事项。出现但未解答的问题。等待中的外部依赖。]
|
||||
|
||||
- [阻碍 / 待解决问题]
|
||||
|
||||
如果无:"无当前阻碍。"
|
||||
|
||||
---
|
||||
|
||||
## 确切下一步
|
||||
|
||||
[若已知:恢复工作时最重要的单件事项。描述要足够精确,使得恢复工作时无需思考从何处开始。]
|
||||
|
||||
[若未知:"下一步未确定——在开始前,请查看'尚未尝试的事项'和'阻碍'部分以决定方向。"]
|
||||
|
||||
---
|
||||
|
||||
## 环境与设置说明
|
||||
|
||||
[仅在相关时填写——运行项目所需的命令、所需的环境变量、需要运行的服务等。若为标准设置,请跳过。]
|
||||
|
||||
[若无:请完全省略此部分。]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 示例输出
|
||||
|
||||
```markdown
|
||||
# 会话:2024-01-15
|
||||
|
||||
**开始时间:** ~下午2点
|
||||
**最后更新:** 下午5:30
|
||||
**项目:** my-app
|
||||
**主题:** 使用 httpOnly cookies 构建 JWT 认证
|
||||
|
||||
---
|
||||
|
||||
## 我们正在构建什么
|
||||
|
||||
为 Next.js 应用构建用户认证系统。用户使用电子邮件/密码注册,收到存储在 httpOnly cookie(而非 localStorage)中的 JWT,受保护的路由通过中间件检查有效的令牌。目标是在浏览器刷新时保持会话持久性,同时不将令牌暴露给 JavaScript。
|
||||
|
||||
---
|
||||
|
||||
## 哪些工作有效(附证据)
|
||||
|
||||
- **`/api/auth/register` 端点** — 确认依据:Postman POST 请求返回 200 并包含用户对象,Supabase 仪表板中可见行记录,bcrypt 哈希正确存储
|
||||
- **在 `lib/auth.ts` 中生成 JWT** — 确认依据:单元测试通过 (`npm test -- auth.test.ts`),在 jwt.io 解码的令牌显示正确的负载
|
||||
- **密码哈希** — 确认依据:`bcrypt.compare()` 在测试中返回 true
|
||||
|
||||
---
|
||||
|
||||
## 哪些工作无效(及原因)
|
||||
|
||||
- **Next-Auth 库** — 失败原因:与我们的自定义 Prisma 适配器冲突,每次请求都抛出“无法在此配置中将适配器与凭据提供程序一起使用”。不值得调试 — 对我们的设置来说过于固执己见。
|
||||
- **将 JWT 存储在 localStorage 中** — 失败原因:SSR 渲染发生在 localStorage 可用之前,导致每次页面加载都出现 React 水合不匹配错误。此方法从根本上与 Next.js SSR 不兼容。
|
||||
|
||||
---
|
||||
|
||||
## 尚未尝试的事项
|
||||
|
||||
- 在登录路由响应中将 JWT 存储为 httpOnly cookie(最可能的解决方案)
|
||||
- 使用 `cookies()` 从 `next/headers` 中读取服务器组件中的令牌
|
||||
- 编写 middleware.ts 通过检查 cookie 是否存在来保护路由
|
||||
|
||||
---
|
||||
|
||||
## 文件当前状态
|
||||
|
||||
| 文件 | 状态 | 备注 |
|
||||
| -------------------------------- | -------------- | ----------------------------------------------- |
|
||||
| `app/api/auth/register/route.ts` | ✅ 已完成 | 工作正常,已测试 |
|
||||
| `app/api/auth/login/route.ts` | 🔄 进行中 | 令牌已生成但尚未设置 cookie |
|
||||
| `lib/auth.ts` | ✅ 已完成 | JWT 辅助函数,全部已测试 |
|
||||
| `middleware.ts` | 🗒️ 未开始 | 路由保护,需要先实现 cookie 读取逻辑 |
|
||||
| `app/login/page.tsx` | 🗒️ 未开始 | UI 尚未开始 |
|
||||
|
||||
---
|
||||
|
||||
## 已做出的决策
|
||||
|
||||
- **选择 httpOnly cookie 而非 localStorage** — 原因:防止 XSS 令牌窃取,与 SSR 兼容
|
||||
- **选择自定义认证而非 Next-Auth** — 原因:Next-Auth 与我们的 Prisma 设置冲突,不值得折腾
|
||||
|
||||
---
|
||||
|
||||
## 阻碍与未决问题
|
||||
|
||||
- `cookies().set()` 在路由处理器中有效,还是仅在服务器操作中有效?需要验证。
|
||||
|
||||
---
|
||||
|
||||
## 确切下一步
|
||||
|
||||
在 `app/api/auth/login/route.ts` 中,生成 JWT 后,使用 `cookies().set('token', jwt, { httpOnly: true, secure: true, sameSite: 'strict' })` 将其设置为 httpOnly cookie。
|
||||
然后用 Postman 测试 — 响应应包含一个 `Set-Cookie` 头。
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 注意事项
|
||||
|
||||
* 每个会话都有其自己的文件——切勿追加到先前会话的文件中
|
||||
* “什么没有成功”部分是最关键的——没有它,未来的会话将盲目地重试失败的方法
|
||||
* 如果用户要求中途保存会话(而不仅仅是在结束时),则保存目前已知的内容,并清楚地标记进行中的项目
|
||||
* 该文件旨在通过 `/resume-session` 在下次会话开始时由 Claude 读取
|
||||
* 使用规范的全局会话存储:`~/.claude/sessions/`
|
||||
* 对于任何新的会话文件,首选短 ID 文件名形式(`YYYY-MM-DD-<short-id>-session.tmp`)
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
显示所有会话及其元数据,支持筛选和分页。
|
||||
|
||||
当您需要群组的操作员表层上下文时,使用 `/sessions info`:分支、工作树路径和会话最近性。
|
||||
|
||||
```bash
|
||||
/sessions # List all sessions (default)
|
||||
/sessions list # Same as above
|
||||
@@ -26,6 +28,7 @@
|
||||
node -e "
|
||||
const sm = require((process.env.CLAUDE_PLUGIN_ROOT||require('path').join(require('os').homedir(),'.claude'))+'/scripts/lib/session-manager');
|
||||
const aa = require((process.env.CLAUDE_PLUGIN_ROOT||require('path').join(require('os').homedir(),'.claude'))+'/scripts/lib/session-aliases');
|
||||
const path = require('path');
|
||||
|
||||
const result = sm.getAllSessions({ limit: 20 });
|
||||
const aliases = aa.listAliases();
|
||||
@@ -34,17 +37,18 @@ for (const a of aliases) aliasMap[a.sessionPath] = a.name;
|
||||
|
||||
console.log('Sessions (showing ' + result.sessions.length + ' of ' + result.total + '):');
|
||||
console.log('');
|
||||
console.log('ID Date Time Size Lines Alias');
|
||||
console.log('────────────────────────────────────────────────────');
|
||||
console.log('ID Date Time Branch Worktree Alias');
|
||||
console.log('────────────────────────────────────────────────────────────────────');
|
||||
|
||||
for (const s of result.sessions) {
|
||||
const alias = aliasMap[s.filename] || '';
|
||||
const size = sm.getSessionSize(s.sessionPath);
|
||||
const stats = sm.getSessionStats(s.sessionPath);
|
||||
const metadata = sm.parseSessionMetadata(sm.getSessionContent(s.sessionPath));
|
||||
const id = s.shortId === 'no-id' ? '(none)' : s.shortId.slice(0, 8);
|
||||
const time = s.modifiedTime.toTimeString().slice(0, 5);
|
||||
const branch = (metadata.branch || '-').slice(0, 12);
|
||||
const worktree = metadata.worktree ? path.basename(metadata.worktree).slice(0, 18) : '-';
|
||||
|
||||
console.log(id.padEnd(8) + ' ' + s.date + ' ' + time + ' ' + size.padEnd(7) + ' ' + String(stats.lineCount).padEnd(5) + ' ' + alias);
|
||||
console.log(id.padEnd(8) + ' ' + s.date + ' ' + time + ' ' + branch.padEnd(12) + ' ' + worktree.padEnd(18) + ' ' + alias);
|
||||
}
|
||||
"
|
||||
```
|
||||
@@ -110,6 +114,18 @@ if (session.metadata.started) {
|
||||
if (session.metadata.lastUpdated) {
|
||||
console.log('Last Updated: ' + session.metadata.lastUpdated);
|
||||
}
|
||||
|
||||
if (session.metadata.project) {
|
||||
console.log('Project: ' + session.metadata.project);
|
||||
}
|
||||
|
||||
if (session.metadata.branch) {
|
||||
console.log('Branch: ' + session.metadata.branch);
|
||||
}
|
||||
|
||||
if (session.metadata.worktree) {
|
||||
console.log('Worktree: ' + session.metadata.worktree);
|
||||
}
|
||||
" "$ARGUMENTS"
|
||||
```
|
||||
|
||||
@@ -220,6 +236,9 @@ console.log('ID: ' + (session.shortId === 'no-id' ? '(none)' : session.
|
||||
console.log('Filename: ' + session.filename);
|
||||
console.log('Date: ' + session.date);
|
||||
console.log('Modified: ' + session.modifiedTime.toISOString().slice(0, 19).replace('T', ' '));
|
||||
console.log('Project: ' + (session.metadata.project || '-'));
|
||||
console.log('Branch: ' + (session.metadata.branch || '-'));
|
||||
console.log('Worktree: ' + (session.metadata.worktree || '-'));
|
||||
console.log('');
|
||||
console.log('Content:');
|
||||
console.log(' Lines: ' + stats.lineCount);
|
||||
@@ -241,6 +260,11 @@ if (aliases.length > 0) {
|
||||
/sessions aliases # List all aliases
|
||||
```
|
||||
|
||||
## 操作员笔记
|
||||
|
||||
* 会话文件在头部持久化 `Project`、`Branch` 和 `Worktree`,以便 `/sessions info` 可以区分并行 tmux/工作树运行。
|
||||
* 对于指挥中心式监控,请结合使用 `/sessions info`、`git diff --stat` 以及由 `scripts/hooks/cost-tracker.js` 发出的成本指标。
|
||||
|
||||
**脚本:**
|
||||
|
||||
```bash
|
||||
|
||||
@@ -321,10 +321,12 @@ Never skip the RED phase. Never write code before tests.
|
||||
|
||||
## Related Agents
|
||||
|
||||
This command invokes the `tdd-guide` agent located at:
|
||||
`~/.claude/agents/tdd-guide.md`
|
||||
This command invokes the `tdd-guide` agent provided by ECC.
|
||||
|
||||
And can reference the `tdd-workflow` skill at:
|
||||
`~/.claude/skills/tdd-workflow/`
|
||||
The related `tdd-workflow` skill is also bundled with ECC.
|
||||
|
||||
For manual installs, the source files live at:
|
||||
- `agents/tdd-guide.md`
|
||||
- `skills/tdd-workflow/SKILL.md`
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user