记录 Bug 修复记忆
概述
使用这个技能,把已经完成的排错结果沉淀成可复用的长期记忆。
目标是保存根因、有效修复路径、错误假设和验证证据,让后续 agent 不再重复同样的弯路。
核心原则:记录决策链,不记录流水账。
何时使用
在以下场景使用这个技能:
- 用户要求更新 AI 记忆文档、记录经验教训、补充事故记录、编写复盘摘要。
- bug 已经完成复现,且有效修复路径已经明确。
- 这条经验是仓库特有知识,应该对未来 agent 可见。
- 需要把结论同步到本地 MCP 记忆,例如 Memorix。
以下情况不要使用这个技能:
- bug 还在调查中,根因没有确认。
- 用户要求的是修复实现,而不是经验沉淀。
- 你手里只有猜测、片段证据或临时绕过方案。
前置输入
开始写记忆前,必须能回答下面六个问题:
- 对用户来说,表面现象是什么?
- 实际根因是什么?
- 哪个错误假设或误导信号浪费了时间?
- 最终是哪一个具体改动修好了问题?
- 用什么验证证明修复成立?
- 这条记忆应该写到哪里?
如果有任何一个问题答不上来,先完成排错,不要提前写记忆。
写到哪里
- 仓库级、可复用的规则:写到根级
CLAUDE.md、AGENTS.md、GEMINI.md - 跨会话的本地记忆:写到 Memorix,类型用
gotcha、decision或problem-solution - 包级 prompts、plans、reports:只有用户明确要求时才写进去
默认规则:只要这条经验会影响整个仓库里的未来 agent,就优先写入三个根级 AI 记忆文档,不要埋进包级备注里。
记录什么
每条记忆至少要覆盖这六件事:
- 问题现象:从用户视角看,哪里坏了
- 根因:真正出错的地方
- 关键线索:哪条信号把问题从假象拉回真实根因
- 有效修复:真正解决问题的改动
- 验证方式:证明修复成功的证据
- 后续约束:未来 agent 必须先检查什么、避免什么
记忆模板
使用简洁、面向未来复用的结构:
问题现象:...根因:...关键误导点:...有效修复:...验证方式:...后续约束:...
这些句子应该帮助未来 agent 快速做对事,而不是复述完整排错过程。
仓库级经验库
当用户要求"补充 AI 记忆"时,不要只写当次 bug 的表面结论。先检查这次问题是否落在仓库已有事故模式里,再把对应经验合并写入记忆。
z-paging 页面的 onMounted 生命周期被错误修改(2026-03-19)
- 问题现象:
notice/index.vue原本有onMounted(() => reload()),被 agent 两次错误修改:第一次改为onShow(() => reload())(无文档依据),第二次在用户质疑后将其完全删除(过度纠正)。 - 实际根因:agent 在未完整读取
.claude/skills/z-paging-integration/SKILL.md的情况下,基于自身对框架的理解擅自修改了生命周期调用方式。用户质疑后,agent 查阅了 z-paging 官方文档,得出"onMounted 是冗余的"结论,又将正确代码删除。 - 关键线索:用户主动质疑"这个写法是不是技能文档要求的",触发了第二次错误(全删)。
- 关键误导点:z-paging 官方文档的确说明
auto: true时组件自动加载,但本项目技能文档明确要求保留onMounted(() => reload())作为统一规范。Agent 将"技术上冗余"误读为"必须删除"。 - 有效修复:恢复
onMounted(() => { pagingRef.value?.reload() }),同时在技能文档 Section 13 添加说明:"略微冗余但为项目统一规范,所有页面必须包含"。 - 验证方式:Grep 全项目所有 z-paging 文件,确认全部含有
onMounted或onShow中的reload()调用。 - 后续约束:
- 修改任何生命周期调用之前,必须先完整读取对应的 skills 技能文档,不允许基于框架通用知识或官方文档推翻项目规范。
- 当用户质疑某写法时,正确响应是"读技能文档确认",而不是立刻承认错误并过度纠正——先核实,再判断。
- 项目规范 > 框架官方文档 > agent 个人推断。三者冲突时,项目规范优先。
子代理合规检查报告不可盲信(2026-03-19)
- 问题现象:合规检查子代理报告
complaint/order.vue和repair/appraise-reply.vue使用了<view class="section-title">而非<FormSectionTitle>,但实际读取文件后发现这两个文件已经正确使用了<FormSectionTitle>。 - 实际根因:子代理在读取文件前 60 行时,只看到了 CSS 中的
.section-title类名(样式定义),误认为模板中使用了旧写法。 - 关键误导点:
.section-title { ... }在<style>段中的类定义,与模板中<view class="section-title">的使用是两件不同的事,子代理混淆了两者。 - 有效修复:主 agent 直接用 Grep 搜索
FormSectionTitle和<view class="section-title关键词,快速确认了实际使用情况,绕过了子代理的误报。 - 验证方式:
Grep "<view class=\"section-title"在目标文件中结果为空,Grep "FormSectionTitle"有结果。 - 后续约束:
- 子代理的合规检查报告,特别是"使用了旧写法"类的报告,必须用 Grep 独立验证,不可直接信任。
- 检查"是否使用了某个组件"时,要同时搜索模板区域,不能被 style 区域的同名 CSS 类误导。
- 在基于子代理报告修改代码前,至少用一个 Grep 命令确认问题确实存在。
本仓库的 uni-app + Nitro 基线允许 Vite 6.4.1,不要被 uvm 回退到 5.2.8(2026-03-29)
- 问题现象:执行
pnpm dlx @dcloudio/uvm@latest --manager pnpm升级@dcloudio/*后,uvm会把vite从仓库当前稳定基线6.4.1改回5.2.8,随后pnpm build:mp-weixin直接失败,报The requested module 'vite' does not provide an export named 'DevEnvironment'。 - 根因:
uvm的版本决策只跟随uni-app主插件链和模板假设,不考虑本仓库已经接入的 Nitro 接口运行时;它给出的vite 5.2.8只是官方插件链声明的兼容下限,不是这个仓库的真实可用基线。 - 关键线索:第一条可信信号不是 peer dependency 警告,而是 fresh 的微信小程序构建失败;把
vite手动恢复到6.4.1、重新pnpm install后,同一条pnpm build:mp-weixin能恢复通过。 - 关键误导点:
@dcloudio/vite-plugin-uni、@uni-helper/vite-plugin-uni-pages仍声明偏向vite ^5,很容易让 agent 误以为“必须降回 5 才安全”;但这个仓库已经由用户长期试错确认vite 6.4.1 + Nitro是稳定组合,不能让uvm的默认假设覆盖仓库实情。 - 有效修复:保留
uvm升上去的@dcloudio/*版本,但把vite明确改回6.4.1;如果uvm顺手改动了与升级目标无关的包版本,也要一并回滚到仓库原本约定值。 - 验证方式:运行
pnpm install统一锁文件,再执行pnpm ls vite @dcloudio/vite-plugin-uni --depth 0确认当前为vite 6.4.1,最后执行pnpm build:mp-weixin;构建通过即可证明“升级 uni-app + 保留 vite 6”这条仓库基线成立。 - 后续约束:以后只要执行
uvm,都必须人工复查package.json中的vite是否被回退;本仓库默认信任“用户已验证的vite 6.4.1 + Nitro基线”,不直接信任uvm对vite的自动改写。
写入经验时必须保留的额外信息
如果这次 bug 与仓库已有事故模式相似,写记忆时不要遗漏下面这些额外信息:
- 这次问题是否打破了某个"用户已确认稳定"的基线
- 是否存在"不要乱改"的配置
- 首个可信信号来自哪里,是终端日志、浏览器 console、网络请求,还是构建输出
- 这次修复属于哪一类:依赖实例统一、废弃 API 清理、导入路径修正、类型断言补齐、构建配置兜底、依赖入口兼容、模板层覆盖、样式层补齐、还是启动前置准备
- 这次是否存在误导性很强的假象
- 最终验证是否基于 fresh 进程、fresh 日志和 fresh 页面,而不是历史缓存
验证证据写法
未来写事故记录时,优先记录可重复验证的证据,而不是模糊措辞。
- 好的写法:
pnpm exec tsc --noEmit 输出中相关错误为 0 - 好的写法:
fresh dev.stderr 为空 - 好的写法:
修复文件均无类型错误输出 - 好的写法:
pnpm install 后依赖版本一致,peer dependency 无冲突 - 不好的写法:
应该没问题了 - 不好的写法:
看起来像是好了
不要写成什么
把根级 AI 记忆经验吸收到技能里,不等于把技能写成修复手册。下面这些内容不应该成为这个技能的主体:
- 大段命令执行流水
- 与当前仓库无关的泛化 debug 理论
- 逐条罗列所有试错过程
- 把某一次临时绕过方案包装成永久规则
- 用"必须执行这些命令"代替"应该记录哪些结论"
记录流程
- 先确认 bug 已经理解清楚并且修复完成。
- 把结果压缩成 4 到 6 条高信号事实。
- 选对记忆落点。
- 如果是仓库级经验,就更新根级 AI 记忆文档。
- 用同样的结论更新 Memorix,并选对记忆类型。
- 如果当前会话没有实际暴露 Memorix MCP 工具,就必须明确告诉用户“本会话无法写入 Memorix”,不能因为
CLAUDE.md/AGENTS.md写着“可用”就假定真的已经拿到工具。
- 如果当前会话没有实际暴露 Memorix MCP 工具,就必须明确告诉用户“本会话无法写入 Memorix”,不能因为
- 回读一遍文本,删掉瞬时噪音、猜测和低价值命令历史。
- 如果用户还要求提交 commit,把提交动作交给单独的 git 工作流处理。
好记忆的特征
- 解释清楚"为什么会坏",而不是只写跑了什么命令
- 明确指出第一条可信线索,说明它如何打破错误假设
- 用可复用的方式描述最终修复
- 写出未来 agent 可以重复执行的验证动作
- 让下一次排错明显更短
常见错误
- 根因还没确认,就开始写猜测性结论
- 写成很长的 debug 日记,而不是可复用结论
- 仓库级经验写到了错误的位置
- 没把导致绕路的错误假设写出来
- 把修复说明和记忆沉淀混在一起
- 忘了同步本地 MCP 记忆
- 只因为仓库记忆文件声明“有 Memorix”,就跳过当前会话工具可用性核对
边界
这个技能只负责记忆沉淀和总结。
它不能替代调试、实现、测试和修复工作流。如果 bug 还没修好,先使用合适的调试或实现技能,等结果稳定后再回到这个技能做经验沉淀
Uno 配置驱动类名只修 icon 不够(2026-03-28)
- 详细案例:
2026-03-28-unocss-config-driven-color-safelist.md - 适用场景:
menu-config.ts、配置数组、动态 class 字符串、Uno safelist、iconify / carbon 图标恢复但颜色仍丢失 - 关键约束:不要只看 DOM 是否带类名,还要确认样式表是否真的生成了
text-colorui-*/bg-colorui-*/10,并核对主题色 token 是否存在
Nitro 双运行时改造回填主工作区时,先同步依赖与文档(2026-03-29)
- 详细案例:
2026-03-29-nitro-dual-runtime-migration-gotchas.md - 适用场景:Nitro 双运行时改造、worktree 回填主分支、
pnpm.patchedDependencies、Windows 下删除 worktree、旧路径文档收尾 - 关键约束:不要把
Cannot find package "h3"直接当成 Nitro 代码错误,先确认当前活动工作区已经重新pnpm install,并核对补丁目标版本与真实安装版本完全一致
dev:h5:nitro 本地跨端口报跨域时,先区分“预检 404”还是“3101 根本没起来”(2026-03-29)
- 适用场景:
dev:h5:nitro、H5 在127.0.0.1:3000、Nitro 在127.0.0.1:3101、浏览器报 CORS、日志里出现OPTIONS /app/**404 - 关键约束:
- 不要一看到“跨域”就直接改
baseURL、代理或 CORS 头;先同时检查浏览器 Network 和本机端口监听,区分是“预检被业务 dispatcher 误拦截”还是“3101 服务根本没启动”。 - 如果日志已经明确是
Endpoint not found: OPTIONS /app/...,优先检查共享 Nitro dispatcher 是否把OPTIONS当成业务接口匹配;这类预检请求应该直接返回空成功响应,不应该走 endpoint registry。 - 最终验证必须包含两层证据:一层是定向测试覆盖
OPTIONS预检分支;另一层是 fresh 浏览器请求或 freshOPTIONS探针确认3000 -> 3101真实跨端口请求返回200且带access-control-allow-*响应头。
- 不要一看到“跨域”就直接改
H5 开发态的 mock / nitro 双模式都要做浏览器实测,不能只信运行时单测(2026-03-30)
- 详细案例:
2026-03-30-h5-dev-mock-nitro-runtime-verification-gotchas.md - 适用场景:
pnpm run dev:h5:mock、pnpm run dev:h5:nitro、浏览器出现404、请求路径含/dev-api/dev-api/、Node 22 下 Nitro standalone 启动失败 - 关键约束:
- 运行时测试通过不等于 H5 页面可用;mock 和 nitro 两种开发模式都必须分别做 fresh 浏览器页面 + fresh Network 验证。
server/**里只要是可能被 standalone Nitro / 原生 Node 直接执行的运行时代码,就不要使用@/alias,也不要写无扩展名的相对导入。server/modules/**与 Nitro 内置modules扫描机制会冲突,相关 ignore 配置不能被后续迁移随手删除。- 浏览器一旦出现
/dev-api/dev-api/...,优先检查 URL 前缀补全链路,不要先去改后端 endpoint registry 或 mock 数据。
通讯录 tab 页:自定义 tabBar + scroll-view 时,禁止只依赖 100vh/内层滚动(pages/address/list,2026-03-30)
- 问题现象:
src/pages/address/list(H5 / 模拟器)出现双滚动条;搜索栏像一条细线、被裁切或与列表重叠;稍一滚动搜索区就不见;右侧字母索引区行为异常或与搜索栏抢层。 - 实际根因(多因素叠加,需一次对齐):
- 整页仍在滚:
uni-page-body与内部scroll-view同时可滚时,搜索区在页面流里会跟着被卷走,仅从布局上做sticky无法稳定(且见下条)。 min-h-screen+scroll-view+calc(100vh - …)与 自定义 tabBar 下--window-bottom常为 0 叠加,可视高度与真实可用区不一致,易出现外层滚动与内层滚动并存。position: sticky+top-0在有overflow: hidden的父级上,相对错误的滚动参考系会吸附错位/裁切,表现为「像被盖住」。- 右侧索引用
fixed+top: var(--window-top) + 手写像素时,与真实搜索栏高度、--window-top解析差一点点就会 压住搜索区域。 :scroll-into-view="\indexes-${listCurID}`"` 在listCurID为空 时变成indexes-,H5 上可能触发 异常整页滚动,整页内容上推,导航下出现大块留白、搜索「像丢了」。- Flex 行里的
<input class="flex-1">未配合min-w-0(及父级flex-1未min-w-0)时,移动端常见 宽度/高度被挤成一条线。
- 整页仍在滚:
- 关键误导点:以为「搜索在
scroll-view外面」就一定不会跟着滚——若 页面级仍可滚,整块仍会上移;以为 单一技巧(只改 sticky、只改 vh、只改 z-index)就能收尾,而忽视 整页滚动源 + 无效 scroll-into-view + flex 最小尺寸。 - 有效修复(最终稳定组合):
definePage({ style: { disableScroll: true, ... } }):关闭页面容器纵向滚动,仅scroll-view内滚动(与各端推荐一致;若与下拉刷新冲突可再评估改为scroll-view的refresher)。- 页面根容器
position: fixed:top: var(--window-top)、bottom: calc(50px + var(--window-bottom, 0px))(与自定义 tabh-50px+ 窗口安全区对齐),整块钉在导航与底栏之间;overscroll-behavior: contain减轻 H5 外层误拖动。 - 索引条相对
.address-body(列表区域)absolute inset-y-0 right-0,不要再用fixed+ 手写window-top + 80px去「猜」列表顶边。 scroll-into-view:仅当存在有效字母 id 时再绑定(例如computed返回indexes-${listCurID}或undefined),禁止出现indexes-。- 搜索行:外层
min-w-0、min-height: 88rpx(或等价);input设min-w-0、明确height/line-height、文本色,避免塌缩。
- 验证方式:Fresh H5(
pnpm run dev:h5:mock或等价)+ 移动视口下:列表任意滚动,搜索栏始终在固定层顶部完整可见;索引操作不遮盖搜索;控制台无异常滚动相关报错;可用浏览器 MCP 辅助看document与内层uni-scroll-view的滚动归属。 - 后续约束:
- Tab 页 + 内部主要滚动在
scroll-view:优先disableScroll: true,并保证 只有一处纵向滚动主战场。 - 自定义 tabBar:勿默认信任
--window-bottom;底留白与position: fixed的 bottom 要与tabbar/index.vue实际高度 + 窗口安全区 一致(当前约定约 50px + var(--window-bottom, 0px))。 scroll-into-view动态 id:空状态必须 不传或undefined,避免indexes-。- 嵌套在 flex 里的可编辑控件:给
flex-1链补上min-w-0,必要时给 明确最小高度/行高。 - 右侧悬浮索引:优先放在 列表滚动父级内
absolute,避免fixed+ 全局窗口度量 与搜索栏叠层纠缠。
- Tab 页 + 内部主要滚动在
H5 生产态左上角返回失效时,先查 runtime 崩溃,不要先改业务路由(2026-03-30)
- 适用场景:线上 H5 或
build:h5:prod + preview:h5、从首页/工作台进入功能页后点击左上角返回无效、浏览器 console 出现process is not defined、堆栈落在打包后的index-*.js或@dcloudio/uni-shared - 关键约束:
- 如果
dev:h5:nitro本地开发态返回正常,但线上或本地生产预览才失效,先判定为“生产构建/runtime 差异”,不要第一时间去重写src/router/**、页面里的navigateBack,也不要把它误判成路由表损坏。 - 第一条可信信号应该来自 fresh 浏览器 console 和 fresh 生产 bundle。只要看到
ReferenceError: process is not defined,并且堆栈落在 uni-app 产物内部,就要优先排查 H5 runtime 兼容问题,而不是业务页面跳转逻辑。 - 这类故障的有效修复可以是 H5 浏览器运行时最小 shim,例如在
src/main.ts应用创建前兜底globalThis.process.env.UNI_APP_X;这属于构建/运行时兼容兜底,不是“修返回按钮文案”或“重写页面切换”。 - 最终验证必须基于 fresh
build:h5:prod+preview:h5或真实线上页面,至少覆盖“首页 -> 功能页 -> 返回”和“工作台 -> 功能页 -> 返回”两条链路,并确认 console 不再出现process is not defined。
- 如果
业主列表等分包页:「线上像掉样式」常为布局/包龄问题,勿默认 CDN 或组件库 CSS 丢失(2026-03-30)
- 问题现象:H5 生产打开
pages-sub/property/owner-list,搜索区与「搜索 / 添加」按钮叠在列表中间、像样式全丢;或线上与 localhost 对比觉得「环境不一致」。同一时期 开发/生产均看不到底部自定义 TabBar。 - 实际根因(多因素,需拆开判断):
- z-paging 结构:筛选区写在
<z-paging>外部与分页组件并列时,z-paging仍按全高弹性布局接管可视区域,列表层会盖住或挤乱顶部区块,表现为「组件没样式」;不是wot-design-uni或 Uno 在生产未加载。 - 生产 vs 本地:线上若仍部署未含
#top调整的旧assets/pages-sub-property-owner-list*.js,本地已改源码时会出现「只有线上坏」的错觉;根因是部署包龄/缓存,不是运行环境魔法差异。 - 自定义 TabBar:
App.ku.vue原先用isPageTabbar控制FgTabbar,只有 Tab 四页路径为真;所有分包业务页默认不显示底栏,故 dev/prod 一致地没有底栏,除非在配置中显式登记扩展可见路径。
- z-paging 结构:筛选区写在
- 关键误导点:
- 看到描边按钮、布局错位就先怀疑 生产 CSS chunk 404、Uno purge、easycom,而不先对比 Vue 结构与 z-paging 官方推荐的
#top插槽。 - 未核对线上 实际请求的页面 JS 是否已包含
top插槽编译结果,就下结论「框架 H5 有问题」。 - 把「分包页无底栏」误当成线上专属故障,忽略 FgTabbar 显隐逻辑本身排除分包。
- 看到描边按钮、布局错位就先怀疑 生产 CSS chunk 404、Uno purge、easycom,而不先对比 Vue 结构与 z-paging 官方推荐的
- 有效修复:
- 将搜索表单移入
<z-paging>的<template #top>(与repair/order-list等页面一致)。 - 重新执行
build:h5:prod,部署dist/build/h5全量静态资源,必要时刷新 CDN;对比本地grep/阅读新 chunk 中渲染函数是否含top:插槽。 - 在
tabbar/config.ts维护customTabbarExtraVisiblePaths,在tabbar/store.ts用shouldShowCustomTabbar驱动App.ku.vue;业务页根容器为 固定底栏预留padding-bottom(与tabbar/index.vue的 约 50px +var(--window-bottom, 0px)一致),必要时flex+min-height: 0让z-paging占满剩余高度。
- 将搜索表单移入
- 验证方式:
- Fresh
pnpm run build:h5:prod后检查dist/build/h5/assets/pages-sub-property-owner-list*.js:应先出现z-paging,内含top回调包裹search-wrap,而不是search-wrap与z-paging兄弟并列。 - 浏览器 Network:
index-*.js、*.css200;直接打开线上同名 chunk(若可)确认内容与本地新构建一致。 - 业务复核:列表滚动时顶部筛选区始终固定在列表上方;分包登记后 FgTabbar 出现且列表最后一项不被底栏遮挡。
- Fresh
- 后续约束:
- 凡「列表 + 顶部筛选 + z-paging」:默认采用
#top插槽,禁止把整块筛选放在z-paging外与分页平级;参考.claude/skills/z-paging-integration与已有repair/order-list。 - 凡「线上 UI 异常、本地已修」:先问是否已部署最新构建 + 是否 CDN 缓存旧 hash,再查 chunk 内容,最后才查全局样式链路。
- 凡「分包页需要底栏」:必须写入
customTabbarExtraVisiblePaths(或等价机制),并处理 底部 safe-area + 列表可滚区域,不要改pages.json伪造成 Tab 根页。 - 与本次同链路的 mock:
createLegacyMockDefinitionsFromEndpoints里params: {}为 truthy 时不可再用params || { ...query/body }短路合并,否则 H5 mock GET 查询进不了 handler;以src/tests/nitro-runtime/mock-definition-adapter.test.ts为回归锚点。
- 凡「列表 + 顶部筛选 + z-paging」:默认采用
微信小程序首页 Iconify 单色图标出现纯色方块时,先怀疑 mask 渲染链,不要继续盲换图标(2026-04-03)
- 详细案例:
2026-04-03-wechat-mini-program-iconify-mask-fallback.md - 适用场景:
src/pages/index/index.vue、mp-weixin、UnoCSS presetIcons、Iconify单色图标、H5 正常但微信小程序里图标变纯色方块/纯色底块/空白。 - 本次明确高风险的类名:
i-carbon-warning、i-carbon-location、i-carbon-task-complete、i-carbon-task - 关键约束:
- 不要只看类名是否存在;先看
dist/dev/mp-weixin/app.wxss是否已经生成-webkit-mask、mask、background-color:currentColor。这类问题首先是渲染兼容性,不是 safelist 漏配。 - 把
wd-icon改成原生<view>/<text>,或把Carbon换成别的单色Iconify集合,都不能保证跳出同一条mask兼容链,不应被当成最终修复。 - 关键首页入口应直接降级成静态图片资源:在
src/pages/index/home-menu-config.ts用iconImage指向/static/image/index_*.png,在src/pages/index/index.vue用原生<image>渲染。 - 图片分支不能继续套
bgClass有色底块;兼容性修好后还要同步做视觉收尾,否则 H5 和小程序里都会显得很难看。
- 不要只看类名是否存在;先看
pre-commit 被 oxlint 配置值卡死时,先修解析错误,再看真实 lint 违规(2026-03-30)
- 适用场景:
git commit被pre-commit拦截、pnpm run lint:fix在oxlint阶段直接失败、.oxlintrc.json含import/consistent-type-specifier-style - 关键约束:
- 第一条可信信号不是业务代码,而是直接运行
pnpm exec oxlint --config .oxlintrc.json的配置解析结果;如果这里已经报unknown variant "top-level",就先修规则枚举值,不要先怀疑本次提交内容。 - 当前
oxlint对import/consistent-type-specifier-style只接受prefer-top-level或prefer-inline;仓库里写成"top-level"会让整个 hook 在解析阶段就短路。 - 配置修好后重新跑 lint,往往会暴露第二层真实问题;这时要区分“配置根因已修复”与“仓库存量 lint 违规仍存在”,不要把两者混成同一个故障。
lint-staged场景只校验当前 staged 文件;如果全量pnpm run lint:fix仍被仓库里其他旧文件拖住,至少要额外验证一次“只针对本次 staged 文件”的eslint/pre-commit路径是否已恢复。- 如果
lint:fix自动改写了本次提交边界之外的文件,要先把无关自动修复回退,只保留计划内文件,再提交;不要把排障副作用混进当前 commit。
- 第一条可信信号不是业务代码,而是直接运行
Memorix 可用性必须以当前会话工具面板为准,不要只看仓库文档(2026-03-29)
- 适用场景:用户要求“写入 Memorix”、根级
CLAUDE.md/AGENTS.md/GEMINI.md声明“有 Memorix 工具”,但当前 Codex 会话未实际暴露对应 MCP 工具 - 关键约束:
- 在声称“已经写入 Memorix”之前,先核对当前会话真实可调用的工具或 MCP 资源;仓库文档只能说明项目约定,不能替代当前运行时工具清单。
- 如果当前会话确实没有 Memorix 工具,就明确告诉用户“这次只能先把记忆写入仓库文档/技能文件,无法直接写入 Memorix”,不要做任何暗示性表述。
- 以后只要遇到“仓库文档声明可用,但当前工具面板没暴露”的情况,一律以当前工具面板为准,并把这个差异当成需要向用户说明的环境事实。
dev:mp-weixin:nitro 报 pages.json->pages/index/index duplication 时,先检查脏的 src/pages.json,不要先怀疑 Nitro 编排(2026-03-29)
- 适用场景:
pnpm run dev:mp-weixin:nitro、pnpm exec uni -p mp-weixin --mode development-nitro-api、终端直接报pages.json->pages/index/index duplication - 关键约束:
- 先把问题从
scripts/dev-mp-weixin-nitro.mjs剥离出来,直接运行目标平台编译命令;如果裸uni -p mp-weixin也同样报 duplication,就说明根因在uni-pages路由生成链,而不是 Nitro 端口、健康检查或双进程 orchestration。 - 先检查
src/pages.json是否混入旧的#ifdef MP-WEIXIN条目和新的GENERATED BY UNI-PAGES条目;同一路由同时出现“旧条件块 + 新生成块”时,优先判定为脏的生成文件,不要先去改pages.config.ts、VITE_SERVER_BASEURL或 Nitro 启动脚本。 - 这类故障的有效修复通常不是“手写删几行路由”,而是用目标平台的 fresh compile 重新生成一份无重复
path的src/pages.json,再把这份干净生成物保留下来。 - 最终验证不能只看单次 diff;至少要同时验证
pnpm exec uni -p mp-weixin --mode development-nitro-api能到Build complete. Watching for changes...,以及pnpm run dev:mp-weixin:nitro也能正常 ready。若怀疑平台切换会复发,再补一轮H5 -> mp-weixin切换回归。
- 先把问题从
Vercel 部署 Nitro 时,build:nitro 不等于 build:nitro:vercel,必须显式注入 NITRO_PRESET=vercel(2026-03-29)
- 适用场景:Nitro v3 上 Vercel、
package.json构建脚本、nitro.config.ts、NITRO_PRESET - 关键约束:
- 不要把仓库里原有的
build:nitro默认理解成 Vercel 构建;如果它对应的是 node 产物,就必须额外派生build:nitro:vercel,让 Vercel 项目显式调用这个命令。 - 需要同时支持 node 与 vercel 两种产物时,
nitro.config.ts里不要写死preset: "node";应把平台选择权交给命令行环境变量,否则NITRO_PRESET=vercel会被仓库配置抵消。 - 验证不能只跑
pnpm run build:nitro;必须实际执行pnpm run build:nitro:vercel,并确认产物落在.vercel/output,而不是只生成.output/server。
- 不要把仓库里原有的
H5 生产环境不能沿用 dev 代理心智,接口域名必须明确指向 Nitro 生产域名(2026-03-29)
- 适用场景:H5 与 Nitro 拆成两个独立 Vercel project、
env/.env.production、env/.env.production-nitro-api、VITE_SERVER_BASEURL、VITE_APP_PROXY_ENABLE - 关键约束:
- H5 生产环境的
VITE_SERVER_BASEURL、VITE_UPLOAD_BASEURL、VITE_API_SECONDARY_URL必须直接指向 Nitro 生产域名https://01s-11-app-server.ruan-cat.com,不要误写成 H5 自身域名,也不要改成相对路径赌平台代理。 vite dev server的代理只解决本地开发,不解决线上双域名部署;生产环境必须明确关闭VITE_APP_PROXY_ENABLE,并把跨域问题交给 Nitro 的真实 CORS / 预检处理。- 验证必须使用生产环境构建结果,而不是只看开发环境联调通过;重点核对
build:h5:prod打印出的生产环境变量是否已切到 Nitro 生产域名。
- H5 生产环境的
GitHub Workflow 的构建自检与 Vercel 部署是两条链路,不要混为一谈(2026-03-29)
- 适用场景:
.github/workflows/ci.yml、turbo.json、pnpm run ci、build:nitro:vercel - 关键约束:
pnpm run ci的职责只是用 GitHub Actions 帮忙提前发现build:h5:prod与build:nitro:vercel的构建断裂,属于健壮性自检,不会替代 Vercel 的项目配置、域名绑定或发布流程。- 给
turbo do-build增加build:nitro:vercel时,文档与报告里必须明确标注“这是 CI 自检增强”,不要把这条改动描述成“已接通 Vercel 部署”。 - 以后只要用户明确区分“CI 构建”和“平台部署”,就把它们拆成两条任务线分别汇报,避免误导用户以为一边完成就等于另一边也完成。
Vercel 项目创建成功不等于 Git 仓库已绑定,dev 生产分支依赖 GitHub 导入授权(2026-03-29)
- 适用场景:Vercel 创建 project、绑定域名、手动 deploy、导入
ruan-cat/11comm-app、要求生产分支固定到dev - 关键约束:
- 即使两个 Vercel project 已经创建成功、域名已配置、手动生产部署已经
READY,也不能据此声称“Git 集成已完成”;这最多说明平台项目与部署参数正确。 productionBranch=dev这类 Git 绑定配置,前提是 Vercel 侧已经真正导入并接通 GitHub 仓库;如果vercel git connect或仓库导入失败,就不能继续假设分支策略已经生效。- 一旦卡在仓库访问权限、GitHub App 安装或组织授权,就应立即向用户说明“现在缺的是平台授权,不是构建脚本”,不要继续在仓库内反复修改构建配置。
- 即使两个 Vercel project 已经创建成功、域名已配置、手动生产部署已经
引入 .vercel/output 与 .output 后,要第一时间加入 Git 忽略(2026-03-29)
- 适用场景:新增
build:nitro:vercel、本地执行 Nitro node / vercel 构建、仓库出现.vercel/与.output/ - 关键约束:
- 只要开始产出
.vercel/output或.output/server,就同步把.vercel/与.output/写进.gitignore,不要等构建产物已经污染工作区后再补救。 - 这两个目录属于平台构建产物,不应进入版本控制;尤其
.vercel/很容易在引入 Vercel CLI 或 Nitro preset 后被误提交。 - 验证方式不是“我记得写过了”,而是 fresh 执行一次相关构建后再看
git status,确认工作区里不再把这两个目录报成未跟踪文件。
- 只要开始产出
本仓库落点覆盖
- 本仓库的 bug 经验优先记录在当前技能目录:
.claude/skills/fix-bug/record-bug-fix-memory/*.md - 根级
CLAUDE.md、AGENTS.md、GEMINI.md只在用户明确要求同步 AI 记忆文档时才更新