怎么用(附实测输出))
目录一、规矩写在提示词里为什么还是会漏规则文字靠模型自觉规则越写越长约束检查换了一种做法二、冷启动5 条种子规则三、AI 写代码时检查在哪一步发生三个环节一个例子四、在对话里主动检查一个文件五、索引建好后它会从代码里推断规则六、规则会升级也会退役三种状态从你的反馈里学七、它目前管不了的地方小结每个项目都有一些没写进文档、但大家都在守的规矩Lock()后面跟defer Unlock()错误返回值不能随手丢掉SQL 不拼字符串。AI 不知道这些。它写出来的代码能编译测试也能过就是不守规矩。review 时一条条指出来下次它照样再犯。我现在用的是 WES Code 里的约束检查CSEConstraint Satisfaction Engine。它把规矩变成能执行的检查AI 每次写文件都跑一遍违反了就把结果交回给 AI 改。这篇用一个 Go 小项目把它走一遍规矩从哪来什么时候检查结果长什么样以及它目前管不了的地方。一、规矩写在提示词里为什么还是会漏规则文字靠模型自觉把规矩写进提示词模型读到了不代表会照做。对话一长前面写的规则就被后面的内容冲淡了。规则越写越长项目越大规矩越多。整份规则每次都塞进上下文大部分和这次要改的文件没有关系却每一轮都在占 token。约束检查换了一种做法每条规则绑定一个检查器checker。判断对错靠检查器读代码不靠模型理解规则的文字规则文字只给人看。给模型的也只是和当前文件有关的那几条你在编辑器里打开着哪个文件发消息时就带上这个文件适用的生效规则最多 10 条不超过 500 token。二、冷启动5 条种子规则WES Code 打开一个 Go 项目时根目录有go.mod如果这个项目还没有任何规则会先注册 5 条种子规则作为冷启动的基线规则检查器状态置信度错误返回值要处理不能悄悄丢掉err_discard生效0.9Lock()要在同一个函数里配defer Unlock()mutex_defer生效0.9context.Context放第一个参数命名为ctxcontext_first候选0.7init()里不做网络、文件、数据库 I/Ono_init_io候选0.6导出的函数、类型要有以名字开头的注释exported_doc候选0.5只有「生效」的规则参与检查「候选」的不报。置信度到 0.8 转为生效跌破 0.5 退回候选。两个阈值之间留了一段空档免得一条规则卡在边界上一会儿报、一会儿不报。注册种子之前它会先按目录结构扫一遍第五节会讲。这一遍已经推断出规则的项目就不再注册种子规则。种子规则只是起点索引建好之后它还会从代码里推断这个项目自己的规矩。三、AI 写代码时检查在哪一步发生三个环节发消息时编辑器里当前打开的文件它适用的生效规则会带进上下文写入时AI 每次写文件、改文件都先用写入后的内容跑一遍检查器。检查不拦截写入违反项附在这次写入的结果后面下一轮AI 看到违反项通常会按提示改掉改完再写入时再检查一遍一个例子让 AI 给订单模块加一个带锁的缓存和一个清理函数它写出来的internal/order/cache.go是这样的packageorderimport(ossync)typeCachestruct{mu sync.Mutex itemsmap[string]int}func(c*Cache)Set(keystring,nint){c.mu.Lock()c.items[key]n c.mu.Unlock()}funcCleanup(pathstring){_os.Remove(path)}写入时检查器给出两条提示原样规则 ID检查器的判词seed-go-err-check62de6f7fcache.go: discarded call resultseed-go-mutex-defer62de6f7fcache.go: Set Lock without defer Unlock后面是按项目路径算出来的标识换一台机器会不一样。两处都是实打实的问题。Set里先Lock()、最后才Unlock()中间一旦 panic锁就不会释放。Cleanup把os.Remove的错误直接扔了删除失败也没人知道。还有一个细节Cache和Cleanup都是导出的也都没写注释但「导出符号要有注释」这一条还是候选所以没有报。AI 下一轮改成这样func(c*Cache)Set(keystring,nint){c.mu.Lock()deferc.mu.Unlock()c.items[key]n}funcCleanup(pathstring)error{returnos.Remove(path)}再检查结果是2 constraint(s) checked against internal/order/cache.go — all pass.四、在对话里主动检查一个文件不用等 AI 写文件也可以在 WES Code 的对话里直接让它检查检查一下 internal/order/cache.go 有没有违反项目约束有的话按提示改掉它会调用检查工具。对改之前的cache.go工具返回的是2 of 2 constraint(s) fail for internal/order/cache.go:[FAIL seed-go-err-check62de6f7f] cache.go: discarded call result[FAIL seed-go-mutex-defer62de6f7f] cache.go: Set Lock without defer Unlock工具只会给出三种结果情况返回内容有违反「几条里有几条没过」后面逐条列出规则 ID 和检查器的判词全部通过一行「检查了几条全部通过」没有适用的规则No constraints apply to this file.它只报违反项不会把规则全文贴回来。规则正文是给人看的模型拿到的只有检查器的判词。五、索引建好后它会从代码里推断规则种子规则只覆盖通用的 Go 写法这个项目自己的规矩要从代码里推断。目录结构扫描在打开项目时就会做。比如项目里有 auth、user、account 这类目录会推断出「密码要先哈希再存不能明文存储」项目里大多数公开函数已经把context.Context放在第一个参数会推断出「公开函数把 context 放第一个参数」。索引完成度到 90% 以上WES Code 会在后台再跑 7 类基于调用图和代码模式的推断类别推断什么检查器依赖包之间形成了循环引用import_cycle兼容性被很多地方调用的函数签名不要随便改signature_stable兼容性导出 API 的签名不要随便改signature_stable并发goroutine 捕获了外部变量却没有同步goroutine_capture安全SQL 字符串拼接、代码里写死的密钥sql_concat、plaintext_secret性能循环里逐条查库N1nplus1状态枚举的 switch 要覆盖全部取值state_machine每条推断出来的规则都会记下证据比如哪几个包构成了循环、哪几处调用缺了同步回头能看到它为什么存在。证据足够强的直接生效弱一些的先当候选。想马上跑一遍也可以在对话里让 AI 推断项目约束它会返回每一类新登记了几条。六、规则会升级也会退役⟦配图本地上传 marketing/images/diagrams/cse-flywheel.png图片说明「规则的五个阶段发现、注册、验证、学习、衰减」⟧三种状态状态怎么进入参与检查吗候选推断证据不够强种子里置信度低于 0.8 的刚从你的反馈里学到的不参与生效置信度升到 0.8参与退役超过有效期一直没用到证据消失你明确驳回不参与退役也分情况。超期或者证据消失而退役的以后证据再出现还能被重新推断出来。你亲手驳回的不会再回来。一次任务里被触发过的规则任务结束后引擎会根据这次的命中情况调整它们的置信度。从你的反馈里学目前只覆盖一类问题丢掉错误返回值。你拒绝了 AI 的一次编辑原因和错误处理有关理由里提到错误处理或者它写的代码本身就把调用结果丢掉了会给这个文件登记一条候选规则置信度 0.55你接受了编辑但自己把错误检查补了回去也会登记一条置信度 0.5同一个文件、同一类问题再次出现置信度往上加拒绝每次加 0.1修改每次加 0.05到 0.8 才生效一次拒绝不算规矩可能只是这一行、这一刻或者你改了主意。重复几次才说明真是规矩。七、它目前管不了的地方只检查 Go 文件。检查器基于 Go 的语法树.go以外的文件直接跳过种子规则也只在有go.mod的项目里注册。宁可漏报。代码解析失败、遇到不认识的检查器一律当作通过。只提示不拦截。违反项交给 AI 下一轮处理不会阻止写入。最后合不合并还是 review 的人说了算。能写成检查器的才算规矩。「handler 不能直连数据库」这种只写在文档里、没有对应检查器的规矩目前不会变成约束。检查器有自己的边界。比如err_discard抓的是_ 某个调用()这种把结果整个丢掉的写法直接调用、不接返回值的写法它不报。推断要等索引。大项目刚打开的一段时间里只有种子规则或者目录结构扫描推断出来的那几条。小结规矩写进提示词靠的是模型自觉约束检查把规矩绑到检查器上判对错靠读代码还没有任何规则的 Go 项目会先注册 5 条种子规则其中 2 条立刻生效AI 每次写文件都会检查违反项附在结果后面下一轮改掉也可以在对话里主动检查某个文件规则会被推断、升级、退役目前只覆盖 Go能写成检查器的才算文中的约束检查是 WES Code 里的功能官网是 weisyn.com。你们项目里有哪些「没写下来、但大家都守」的规矩欢迎评论区聊聊。觉得有用的朋友欢迎点赞、收藏、关注后面会继续分享 AI 编程的实战经验。