AI Coding 从 vibe coding 到 spec coding,再一步步发展到 Harness Engineering,已经有了众多实证,正确使用 AI 非但不会带来破坏,反而带来了增益,相信每一个使用过 AI 的开发者,都无法回到古法编程了,AI 的开发效率就是高于人类,人类没有必要否认,更没必要对抗,所以问题已经转变为:怎样使用 AI 写出我们想要的代码?每个开发者有自己的工作流,也有自己的理解,不必分个高下,只要能实现需求交付那就是好的。

我本人在26年3月接触过当时还是最佳实践的 superpowers + gstakc 构成规划、执行、验证的工作流,但是后来将精力投入到其他去了,后面出现的 trace、审计这些完全没有接触过了,所以对 AI Coding 实践算是重新开始学习,我的想法是使用 AI Coding 从立项到真实上线,完成一个类贴吧论坛项目,全程不自己写一行代码,找到适合自己的 AI Coding 实践方法。

项目之前

在项目开始之前,我想尽可能地表达一下我目前对 AI Coding 如何写出可靠代码这个问题的理解。

打铁还需自身硬

使用 AI 写需求的前提是本人得懂需求,也看得懂代码,不要求看得懂每一行,最起码要看得懂 AI 代码在抽象层面是如何工作的,我在开发的时候也会尽量观察 AI 写完的代码,看看逻辑是不是通顺,是不是符合现有规范,也就是说 AI 的每一步要尽可能地在我的掌握之下,所以我会尽可能缩短 AI 单次编写的范围,防止变动范围太大我看不过来,也方便 git 回滚。

grill-with-docs

grill-with-docs 是我必用的一个 skill,它的作用相当于增强 AI 的思维链吧,有的 AI 不擅长将需求转化为技术方案,这个 skill 强制进行,而且考虑得很全面,虽然有时候给你列大几十个点很烦,但很多时候很好用。

文档维护

md 文档可以做到很多事情,作为项目长期记忆可以固定很多事实,统一各种术语;作为计划书可以补充思维链和上下文,但是文档太多反而分散注意力,所以长期记忆只留一个;技术文档在实现之后要及时清理,可以删除,也可以移动到工作区外备份(通常没啥用),只要不让 LLM 看到就行。

为什么技术文档要及时清理,这其实是我很早之前就发现的一个问题,一个大型项目是一个 session 完全无法承接的,不同的实现通常由不同 session 进行,而不同 session 拥有的上下文不一样,这就导致:不同 session 不管是上下文还是读写的文档,如果没有做版本控制,极大概率产生前后冲突,污染上下文;就算事实之间没有冲突,LLM 频繁地尝试读取这些文档,也会造成上下文占用、执行效率降低、分散注意力等问题。而有什么需要的,直接让 LLM 读代码就行了,很多人会维护很多这样那样的 spec,却忽略了代码本身就是最权威的 spec。

测试

事实证明,AI 很喜欢各种 tdd 单元测试,实际上很没有用,我会在项目中明令禁止单元测试,而是使用 e2e。

审计

这一块我自认为不擅长,我以前经常使用 /review ,但是我后来发现效果并不是很好,。

pi

为什么使用 pi?pi 是当前轻量化 Coding Agent 的巅峰,其设计哲学是尽可能减少 Harness,让 LLM 自由发挥,其内部只内置了 4 个基本工具,也不内置 skill,这样的好处是适配各种模型,坏处则是模型的能力被无限放大,很多时候任务效果好坏,由模型性能直接决定。

而 cc、codex 这些产品走得是另一条路线,它们针对自家模型进行了优化,比如将工具 Schema 等喂给自家训练模型,这导致自家模型用起来就如鱼得水,其他家的模型没有经过专门训练过的话,用起来就很难受。国产的各家模型厂商也在不断迭代适配自家模型的 Agent 产品。

不过值得单独提及的是 dsh,它以 ds 命名却完全不对 ds 做适配,技术路线反而比 pi 更激进。

所以,我全程使用 pi + ds flash 1017 进行开发。

DAY 1

2026-11-7

决定架构

贴吧我已经使用十多年了,很熟悉其中的主要业务,排除掉很多百度后来添加的无用业务,它的核心业务:进吧、进贴评论点赞收藏、排行榜、我的、接受通知,这几个是直接用户可感知的,用户直接感知不到的则还有用户认证、消息消费、审核等。

所以我直接使用 grill-with-docs 与 pi 进行需求制定:

1
/skill:grill-with-docs 这是一个空项目,我目前正在准备基于springboot微服务后端、react+typescript前端,使用mysql、redis、nginx、rocketmq等主流技术栈,构建一个类贴吧的社群论坛,用户可以选择一个感兴趣的社群进入之后看帖子,并在帖子内评论、点赞、收藏等操作,并且可以接收来自别人的点赞、评论、@等消息。我打算将这个项目从零构建到真实上线,你帮我评估项目如何开展,考虑应该使用组建的适配版本、项目拆分为哪些微服务模块等技术问题。由于这是首次的架构评审阶段,你分析得越全面越好,不需要直接开始写代码

这里不给出具体问了哪些问题,主要讲讲我们达成的细节。

首先是技术栈,后端就使用 spring cloud alibaba 那一套大厂主流技术栈。

然后把整体架构拆分出了8个微服务:

进程 拥有的写模型
gateway 路由、鉴权校验、限流
user-service 账号、凭证、用户资料、关注关系
community-service 社群本体、成员资格、吧主/管理员角色
content-service 帖子、评论(树形)、帖子/评论的计数快照
interaction-service 点赞、收藏(”谁对什么做了什么”的事实)
notification-service 消息聚合、投递、未读数
search-service 帖子/社群全文检索索引
rank-service 热度排行投影(不拥有任何事实,见下)

确认了使用的技术栈:

层 选型 系列
JDK Eclipse Temurin 21 LTS
框架 Spring Boot 3.5.x
微服务 Spring Cloud 2025.0.x(须与 Boot 精确对齐)
注册/配置 Nacos 2.4.x(Server 与 SCA 客户端对齐)
网关 Spring Cloud Gateway 随 SC
RPC OpenFeign + LoadBalancer 随 SC
限流熔断 Sentinel 1.8.x(规则持久化到 Nacos)
消息 RocketMQ 5.3.x(Proxy 与 Remoting 二选一,不混用)
ORM MyBatis-Plus 3.5.x
数据库 MySQL 8.4 LTS(一主一从)
缓存 Redis 7.4.x
搜索 Elasticsearch + IK 8.x
链路追踪 SkyWalking 10.x(存储用内置 BanyanDB,不占用 ES)
指标 Prometheus + Grafana 最新
日志 Loki + Promtail 最新
调度 XXL-Job 2.4.x
对象存储 MinIO 最新(P7 才接)
入口 Nginx 1.27.x
前端 React 19 / TS 5.x / Vite 7 / TanStack Query v5 / Zustand / Tailwind 4 + shadcn/ui —

还给出了一套项目推进大纲:

阶段 内容 位置理由 验收标准
P0 版本矩阵 spike 骨架 → 多阶段 Dockerfile → Compose 编排(core + app)→ Nacos 注册 → 网关路由 → Feign 调用 → Sentinel 规则 → RocketMQ 收发 → MyBatis-Plus → Redis 版本兼容是全项目最大未知数,必须在写业务前清零 React → Nginx → 网关 → user-service 的 /ping(匿名放行)打通,且全部进程在服务器上以容器运行、按 healthcheck 顺序启动、单服务重建可在 90 秒内完成;实际版本号回写 docs/project.md
P1 身份切片 邮箱验证码注册、登录、JWT + JWKS、Redis 白名单、网关验签与注入身份头、前端登录态 所有后续功能都依赖身份;一次验证网关/用户/前端/Redis 四条线 登出立刻失效;踢下线立刻生效;后端服务端口对公网不可达
P2 内容读路径 建社群、加入社群、发帖、社群帖列表、帖子详情(游客可读) 最薄的一条完整读路径,先把”前端并行 + 计数快照”的形态定下来 游客能浏览;登录能发帖;此阶段刻意不含评论与计数
P3 评论 + 互动(风险核心) 评论(存储任意深度/展示两级、游标分页)、点赞、收藏、outbox、RocketMQ、content 消费事件更新计数 整个架构的验证点:第一次真跑”写事实 → 发事件 → 改冗余” 点赞后计数 5 秒内变化;kill 掉 content-service 再点赞,重启后对账任务把计数修回
P4 消息中心 消费点赞/评论/@ 事件(收藏不发消息)、落消息快照、四分类未读计数、SSE 推送、红点、全部已读 依赖 P3 的事件,复用”计数 + 对账”哲学 别人赞我 5 秒内红点亮;”全部已读”与并发新消息的竞态不吞消息
P5 排行 rank-service 定时算日榜/周榜写 ZSet(Top 50 不分页);帖子内评论按热度排序(在 content 内) 依赖 P3 的计数稳定;评论排序不需要 rank 榜单可全量重建,重建期间接口不报错;热度 = 点赞数 + 评论数(收藏不计入)
P6 搜索 search-service + ES + IK,消费内容事件建索引 需要 P2 的内容事件稳定,且是最该被砍的功能 建索引幂等;删帖后搜不到
P7 治理与上线 封禁/禁言/管理员权限、SkyWalking + Prometheus + Grafana + Loki、JMeter 压测、限流规则、备份、HTTPS、镜像 tag 回滚演练 上线前置条件 8 服务全绿;300 QPS 压测无错误;备份可恢复演练成功

同时确认了很多具体业务的逻辑,比如评论帖子和评论评论到底算不算同一种业务?排行榜做不做,怎么计算热度?还有其他细节,比如计算了一波部署硬性条件,部署在哪,开发过程等。

关键点在于,这套方案对吗?我的做法是,让它自己对抗性审查一遍,看看哪些地方有冗余,哪些地方不够清晰,一般能够作出合理的调整。

但是,我必须说的一点是,reflection 有反思滑坡的风险,很有可能反而把正确的方案改错;加上这种立项开始的技术评审本身就有很大的调整空间,不像项目已经进行中的物理限制大;再加上模型本身性能问题……那么答案只有一个了:自己过一遍方案。

其实也没什么好说的,架构技术栈选择尽可能贴合主流,然后澄清业务需求,这样其实就差不多了,更具体的在后续实现的时候再详细探讨,AI 给出的全局方案做个参考就好,只要开发主动权掌握在人手里,后续就可以慢慢调整。

DAY 2

26-11-8

配置服务器

这个项目要最终上线,需要用到云端服务器部署多个组件,我决定全程让 AI 远程连接云服务器自己设置,把登录方式扔给 pi,它自己就能上线配置各种服务器,ai 对 cli 的使用完全把人类当减速带借过了,特别是用 pi 时经常可以看到它写超长一串的 bash 命令,或者写各种性能几乎最优的 sql 语句,人类完全没有还手之力有感觉吗。

当然,由于选用境外服务器,搭建过程花费了很久。当他宣称可以推进 p0 后,对人类来说真正值得花费精力的事情来了,我问他:

1
先不急着推进 P0,你先向我汇报你刚刚连接服务器期间都干了什么。

记录一下,除了 linux 的常规安全配置外,对于我们的业务它已经干了:

  1. 云服务器上安装并冒烟验证 docker;

  2. 安装并验证了 nginx,nginx 不使用 docker 安装。

P0 推进前

同样,P0 这样的大范围工程,不能让他直接就跟着做了,总路线只给出了要做什么,让 AI 按照这个是很容易出幻觉的,可以手动增强思维链再一次明确需求,我让他先向我详细描述应该做什么:

1
我看了p0的大致任务,你再详细跟我讲一讲,p0主要有哪几个大任务,然后你打算怎么做?你执行完成之后,怎么做e2e测试,怎么才算p0彻底完工?

它的回复:

  1. 搭建好最小 maven 框架,包含 9 个微服务模块,每个模块只做 springboot application run,最终要在服务器上跑起来。

  2. 使用 dockerfile+compose 编排搭好的模块,和要用的组件(大工程,镜像下载不稳定)。

  3. e2e 验证,全链路能够通信,nacos -> gateway模块 -> 各个微服务模块 -> 各个组件。

  4. 把验证好的结论编成运维脚本。

ds 给的预估时间:

1
2
3
4
5
6
7
8
9
步|内容            |           预计                 
----|----|----
1 | T1 骨架 + check.sh → 服务器上编过 | 40~60 分钟(含 1~2 轮编译错误往返)
2 |T2 Dockerfile + compose core → MySQL/Redis/Nacos/RocketMQ 起 4 个健康容器 | 30~50 分钟(首次拉镜像 + Maven 依赖下载是最慢一段)
3 |T3 链路 1~3(注册 / 网关 / Feign) | 40~90 分钟 ⚠️ 最可能卡住的方
4 | T3 链路 4~5(RocketMQ / Sentinel) | 30~60 分钟
5 | T4 verify.sh + T5 文档回填 |30 分钟

合计约 3~5 小时,其中大半时间消耗在版本兼容的试错上——这正是 P0 存在的意义。如果一路顺风,说明坑被推到后面了。

此外还根据我的提问,给出了 E2E 测试项目:

# 断言 方法 期望
1 边缘存活 curl https://www.katzenyasax.top/healthz ok
2 容器全健康 docker compose ps --format json 逐个检查 11 个 healthy
3 服务全注册 Nacos API /nacos/v1/ns/service/list 或 catalog 8 个服务名
4 网关通 curl /api/user/ping 200,body 含 user-service
5 Feign 通 curl /api/user/ping/feign 200,body 含 community-service 的实例信息
6 MQ 通 POST /api/user/ping/mq → 轮询 GET .../mq/{id} 3 秒内 consumed=true
7 Sentinel 生效 并发打 10 次 /api/user/ping/sentinel 出现限流响应(非 200 或特定 code)
8 Actuator 8 个服务 /actuator/health UP
9 外部端口收敛 从公网探测 8080/3306/6379/8848/9876 全部 filtered(这条最容易在加服务时被破坏)
10 重启自愈 docker compose restart user-service → 再验 #4、#5 60 秒内恢复 healthy 并重新注册
11 冷启动 down 后 up -d 全量 全部 healthy,用时可接受
12 日志干净 扫 11 个容器最近 500 行 无 ERROR / 无异常堆栈

P0 完成标准:

1
2
3
4
5
6
7
8
9
1. ✅ docker compose --profile core --profile app up -d 在空服务器上一条命令拉起 11 个容器,全部 healthy
2. ✅ deploy/bin/verify.sh 退出码 0,12 条断言全过
3. ✅ 8 个服务注册在 Nacos,/api/user/ping/feign 能证明 Feign 走的是服务发现而非硬编码 IP
4. ✅ RocketMQ 消息端到端被消费,Sentinel 限流可复现
5. ✅ 公网只有 22/80/443 三个端口
6. ✅ docs/project.md 的版本表填上实测值 + 日期,versions.sh 的输出可复现
7. ✅ 全部提交并推送;verify.sh 本身在仓库里,任何时候 git pull 到一台新机器都能重跑

第 7 条最关键:DoD 必须是一个可执行脚本,而不是一段文字描述。否则"P0 完成了"就是一句无法证伪的话。

看着倒是很规整,接下来试了才知道。

P0 首次推进

基于我的习惯,我不会让 pi 一次性跑完 5 个步骤,我让他按照它自己给出的 5 个步骤,单独推进。

步骤1

1
根据你给出的5步骤战略,现在先仅完成第1步。

14:41 开始任务,居然只花了 3 分钟就结束了,并且宣称没有返工,我探探虚实。

没什么好说的,很简单的入门代码,直接过。

步骤2

15:11 开始任务,15:39,拉镜像反而没花多少时间,主要是过程中发现了几个问题反反复复地修改耗时较多,有的是因为 pi 自己写的脚本没有写输出日志,导致容器反复报错缺没有任何输出,让 pi 自己等了半天,后面也补上了;有的则是因为拼写错误,ds 日常脑抽,统一术语和环境参数的上下文同步跟 project.md 的事实对不上,所以排查了好几遍错误。

然后这一步中,主要完成了 docker compose 文件,下面针对 redis、mysql、rocketmq 和 java 的 9 个进程搞好了 dockerfile,up.sh 就是下一步要跑的脚本,把 java 微服务都创建成镜像。

好吧,其实我现在还看不懂,我以前用 docker 顶多用来集中部署中间件,还没有接触过 dockerfile,compose 啥的,后面再补上吧,总之步骤2过。

步骤3

很快完成,pi 声称 nacos、openfeign 调用链确定成功,接口已可在公网访问:

路径 状态
/api/user/ping 200
/api/user/ping/feign 200
/api/community/ping 200
/api/content/ping 200
/api/rank/ping 200
/api/nope/ping 404(不是 500,说明路由未匹配时处理正确)

浏览器中试一个它给出的基本接口地址 https://www.katzenyasax.top/api/user/ping

1
{"code":0,"message":"ok","data":{"service":"user-service","port":"8081","host":"f50d4b406acc","java":"21.0.13","time":"2026-11-08T16:23:46.659146028+08:00"}}

说明确实成功了。

nacos 和 open feign,我让他在前端展示出来。

1
你点开看一眼,如果卡片全绿、Feign 那块有 callee.host,就说明第 3 步是实打实通的。

过。

步骤4

步骤4要完成 seata 和 rocketmq 基本配置,很简单,直接过。

我让 ai 把步骤3写的那个页面放到 test 下面,并且让它随开发动态维护以直观展示服务是否可用。

很简单,过。

步骤5

最后一步完成收尾工作,然后是 e2e 阶段,pi 根据 12 个项目挨个测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
P0 交付物清单

deploy/
├── docker/Dockerfile.service 8 服务共用的多阶段构建
├── compose/compose.yml 单文件 + core/app profile,13 个服务
│ ├── mysql/init/01-schemas.sh 5 个 schema + 5 个受限账号
│ ├── redis/redis.conf AOF + noeviction
│ └── rocketmq/broker.conf 单 Master + IP 钉死 + commitlog 128MB
├── nginx/kuaikan.conf 边缘代理(+ /test 路由)
├── status/{root,test}/index.html 占位页 + 冒烟控制台
└── bin/
├── check.sh 只编译不建镜像(15~30s,本地无编译器的补偿)
├── up.sh pull → build → up → 轮询 healthcheck(状态全程可见)
├── verify.sh P0 验收,16 条断言
├── versions.sh 实测版本采集
├── gen-env.sh 幂等生成/补全环境变量
└── install-status.sh 发布静态页

services/ 9 个 Maven 模块(common + gateway + 7 服务)
docs/ 12 份文档,其中 architecture §12 记了 8 条踩坑

没啥疑问,一步步都是我拍板过的。