代码规范感知
wescode 中的 Convention(项目约定)与 Correction(用户纠正)——自动检测 vs 显式反馈。
Convention 概念
Convention 是自动检测的项目事实——代码库中已经存在但没有写成文档的编码规范:
项目约定示例:
- 缩进使用 tab(不是 space)
- import 按 stdlib → 第三方 → 本地排序
- 错误处理使用 errors.Wrap 而非 fmt.Errorf
- 测试文件命名 *_test.go
- 每个 handler 开头校验 Authorization header
关键特性
| 特性 | 说明 |
|---|---|
| 来源 | 自动从代码检测 |
| 持久化 | ❌ 不入 memory store(INV-MEM-12) |
| 存储 | runtime probe-cache(per-Cell LRU) |
| 生命周期 | 随进程(重启后重新检测) |
| 隔离 | per-workspace(per-Cell) |
Correction 概念
Correction 是用户显式教给 Agent 的偏好——通过拒绝或修改 AI 的编辑来学习:
纠正示例:
- "不要用 any 类型,用具体类型"
- "错误信息用中文"
- "函数命名用驼峰不用下划线"
关键特性
| 特性 | 说明 |
|---|---|
| 来源 | 用户反馈(拒绝/修改编辑) |
| 持久化 | ✅ 入 memory store(L4 Agent Memory) |
| 存储 | wesgine 记忆系统 |
| 生命周期 | 持久化(跨会话/跨重启) |
| 隔离 | per-Actor(默认跨项目) |
Convention vs Correction 对比
| 维度 | Convention(约定) | Correction(纠正) |
|---|---|---|
| 本质 | 项目事实 | 用户偏好 |
| 来源 | 自动检测 | 用户反馈 |
| 持久化 | ❌ runtime probe-cache | ✅ memory store |
| 存储介质 | per-Cell LRU cache | wesgine sessions.db |
| 生命周期 | 进程级(重启重检测) | 持久(直到删除) |
| 隔离范围 | per-workspace | per-Actor(跨 workspace) |
| 注入方式 | 系统提示词快照 | L4 Agent Memory |
| 修改方式 | 不可手动修改 | 记忆中心管理 |
| 跨项目 | ❌ | ✅ 默认跨项目 |
ScanConventions
检测流程
ScanConventions
→ 分析当前 workspace 代码
→ 检测缩进风格、命名规范、导入顺序等
→ 结果写入 per-Cell LRU ProbeCache
→ 注入系统提示词(作为快照)
ProbeCache 机制
// Convention 结果存储在 per-Cell 的 LRU 缓存中
// 不写入 memory store(INV-MEM-12)
type ProbeCache struct {
cache *lru.Cache // key = 工作目录
cellID string
}
为什么不存入记忆
Convention 是项目事实,不是认知记忆:
- 项目可能随时改变编码风格
- 不同分支可能有不同的约定
- 重检测的成本很低
- 存入记忆会污染认知空间
Learn 系统
Learn 系统处理用户反馈,生成 Correction 和 Convention:
API 端点
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /cells/{id}/learn/scan-conventions | 扫描项目约定 |
POST | /cells/{id}/learn/edit-rejected | 报告被拒绝的编辑 |
POST | /cells/{id}/learn/edit-modified | 报告被修改的编辑 |
GET | /cells/{id}/learn/corrections | 获取纠正列表 |
GET | /cells/{id}/learn/conventions | 获取约定列表 |
edit-rejected
当用户拒绝 AI 的编辑时:
// POST /cells/{id}/learn/edit-rejected
{
"file": "internal/service/user.go",
"original": "func GetUser(id string) (*User, error) {",
"proposed": "func getUser(id string) (*User, error) {",
"agent_id": "default-coder"
}
AI 学到:「用户不想让公开函数变成私有」→ 生成 Correction。
edit-modified
当用户修改 AI 的编辑时:
// POST /cells/{id}/learn/edit-modified
{
"file": "internal/service/user.go",
"original": "return fmt.Errorf(\"user not found: %s\", id)",
"ai_edit": "return errors.New(\"user not found\")",
"user_edit": "return errors.Wrapf(err, \"user not found: %s\", id)",
"agent_id": "default-coder"
}
AI 学到:「用户偏好 errors.Wrapf 并保留上下文」→ 生成 Correction。
Correction 的跨项目行为
在 wescode 中,1 workspace = 1 Cell,但 Correction 属于 L4 记忆(per-Actor):
workspace A (Cell ws-a1b2):
→ 用户拒绝了某个编辑
→ Correction 写入 Cell ws-a1b2 的记忆
workspace B (Cell ws-c3d4):
→ 这条 Correction 不在 Cell ws-c3d4 中
→ 不会跨 workspace 生效
为什么"默认跨项目"在 wescode 不完全成立
由于 1 workspace = 1 Cell 的隔离模型,Correction 实际上不跨 workspace——虽然 Correction 属于 L4 per-Actor 记忆,但 actor 绑定在 Cell 中:
wescode 的隔离:
Correction 生命周期 = Cell 生命周期 = workspace 生命周期
接入 SSO 后(多 workspace 共享 actor),Correction 才会真正跨项目生效。
Convention 注入时机
Convention 以快照形式注入系统提示词:
新对话开始
→ 读取 ProbeCache 中的 Convention
→ 作为快照注入系统提示词
→ 对话期间不变(byte-stable,保护 prompt 缓存)
Convention 变化
→ 下次 ScanConventions 时更新 ProbeCache
→ 下一个新对话生效
最佳实践
- 通过拒绝/修改教 AI:这是最自然的反馈方式
- 理解隔离:Convention 和 Correction 都随 workspace 切换
- 不需要手动配置 Convention:自动检测
- 在记忆中心管理 Correction:查看和删除不正确的纠正