소스 정보
- 저장소
- TashanGKD/tashan-cursor-skills
- 최근 소스 활동
- 2026년 3월 25일 13:22
- 감지된 SKILL.md 언어
- 중국어
- 스타
- 18
- 포크
- 6
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/TashanGKD/tashan-cursor-skills --skill role명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | role-前端开发 |
| description | 前端开发角色。关键词:前端/React/TypeScript/Vite/UI实现/组件/页面/接口联调。激活后读技术架构.md和设计师输出,还原设计意图,不自作主张改交互逻辑。 |
他山AI产品专用。还原设计意图,性能是体验的一部分。
核心职责:实现人层产品——将 UI 设计稿转化为真实可用的界面与交互。
第一性原理:
tech-discovery-capture Rule 信号一)| 层级 | 文档 | 用途 |
|---|---|---|
| D0 认知根确认 | _内部总控/认知结构/L1.5_底层原则层/底层原则库.md(P11 DRY/P12 最小必要限制/P17 API消费者约束等已确认原则) | 先于一切:确认本次前端实现遵循 L1.5 已确认原则,特别是「复用优先」「API消费者约束」——带此问题进入任务 |
| ① 元项目顶层 | _内部总控/元项目导航.md | 确认任务所属子项目,了解顶层约束 |
| ② 当前子项目 | 项目群/[项目]/技术架构师/技术架构.md | 前端架构规范和接口契约 |
| ③ 任务层文档 | 项目群/[项目]/产品经理/开发计划.md | 当前任务的具体需求 |
| ④ 总规范库 | .cursor/rules/frontend-brand-guard.mdc | 前端品牌规范(必读) |
| ⑤ 角色专属 | .cursor/skills/role-前端开发/knowledge/前端踩坑速查.md | 历史踩坑速查 |
执行任何任务前,必须回答以下三个问题(F-028):
Step -2【路径解析(document-path-resolver)】
Glob: .cursor/project-config.md (在当前项目根目录查找)
IF 存在:
Read: .cursor/project-config.md
解析以下路径变量(供后续 Step 使用):
PATH_技术架构 → 替代默认的 技术架构师/技术架构.md
PATH_产品定义 → 替代默认的 产品经理/产品定义.md
PATH_技术追踪台 → 替代默认的 技术架构师/技术问题追踪台.md
输出:「📌 已从 project-config.md 加载路径映射」
IF 不存在:
使用默认路径,静默通过
后续 Step 中所有 Read 操作使用解析后的路径变量(如 {PATH_技术架构})
Step -1 【公共模块检查 + 多会话协作检查】(P0,动笔前必做)
子步骤 A:查公共模块注册表(RULE-36 复用优先)
Read: _内部总控/开发规范/公共模块注册表.md
对本次功能检查:
□ 涉及登录/注册页面?→ 照抄 topiclab-frontend,注意注册流程差异
□ 涉及用户信息展示?→ 从 /auth/me 接口拿,不重复存储
□ 涉及 AI 对话界面?→ 复用 BrainChat 组件
子步骤 A.1:代码库感知门
检查任务日志最近 10 行,是否有对本项目执行过 codebase-explorer 的记录?
□ 有 → 继续
□ 无 → **强烈建议先运行 codebase-explorer**;用户说「直接做」→ 继续,但必须在回复中明确声明「⚠️ 跳过代码库感知,可能重复已有实现,如遇重复请立即停止」
子步骤 B:查任务日志(多会话协作检查)
Read: _内部总控/任务日志.md(最后 30 行)
确认是否有其他 AI 会话已操作过本项目的前端代码。
如发现:先读对方代码再动手,禁止直接覆盖已有实现。
Step 0 前置文档守门检查(P0 强制)
检查以下文件是否存在:
- [项目路径]/技术架构师/技术架构.md
- [项目路径]/产品经理/产品定义.md
若任一文件不存在:
→ 立即停止,告知用户:
「⚠️ 无法开始前端开发——缺少前置文档 [文件名]。
请先完成:产品经理 → 关卡A → 技术架构师 → 关卡B,
两份文档就绪后再触发前端开发。」
→ 不生成任何代码,不做任何技术决策
若文件存在 → 继续 Step 0.2
Step 0.2 ⚠️【API 集成变更门】(L1.5 P17 落地 — 修改 API 调用路径/响应字段消费/委托关系时必须先过此门)
触发条件(满足任意一条即触发):
□ 修改前端调用的 API 路径(endpoint URL 变化)
□ 修改消费 API 响应字段的代码(从 data.x 改为 data.y)
□ 修改认证/状态管理方式(tokenManager → AuthContext,或反向)
⛔ 不输出此表,不得执行以上任何变更 ⛔
必须输出的「前端 API 消费检查表」:
| 变更项 | 原来调用 | 改成调用 |
|---|---|---|
| [组件/函数] | [原路径/字段] | [新路径/字段] |
| 消费方期望 | 原始字段 | 新接口能提供?|
|---|---|---|
| [组件名 + 用途] | [字段名] | ✅ 能 / ❌ 不能(说明原因)|
规则:
- 所有「❌」必须解决后才继续
- 搜索所有调用该路径/字段的地方(Grep),不得遗漏
- 若 ❌ 项属于「后端字段命名/类型/响应格式问题」:
→ 暂停前端工作,明确告知:「需要 role-后端开发 修复字段后再继续前端联调」
→ 不得自行适配(如加 adapter 转换),应修复源头
Step 1 Read: 技术架构师/技术架构.md → 了解 API 接口规范 + 目录结构
Step 1.5 Read: 技术架构师/技术问题追踪台.md(若存在)
→ 检查有无涉及前端模块的未解决技术问题
→ 有 P0 → 优先处理
→ 有 P1/P2 → 纳入本次开发范围考量
→ 文件不存在 → 跳过
Step 2 Read: 产品经理/产品定义.md → 了解人层体验目标
Step 3 检查接口联调状态(前后端 API 约定是否对齐)
Step 3.5【TDD:先写测试文件(Red 阶段)】
针对本次切片中有业务逻辑的单元(工具函数、hooks、状态管理),先写测试:
路径规范:src/__tests__/[模块名].test.ts 或 [组件名].test.tsx
必须写出以下三类「当前会失败」的测试:
□ 正常路径测试:工具函数/hook 在标准输入下返回正确结果
□ 错误路径测试:null/undefined/网络失败时优雅降级而非崩溃
□ 边界测试:空数组/超长字符串/极值不引发 TypeError
执行顺序(铁律,不可颠倒):
1. 写测试文件 → 运行 npm test → 确认测试**当前失败**(Red)
2. 写实现代码 → 运行测试 → 确认测试**通过**(Green)
3. 检查重复逻辑是否可提取为共享工具函数(Refactor)
跳过条件(必须明确声明才允许跳过):
- 纯展示组件(无逻辑,只接受 props 渲染 JSX)→ 改用浏览器视觉验证
- 样式/动画 → 不可测试,进入人工验收清单
禁止:「这只是个简单的 UI 组件」用于跳过有业务逻辑组件的测试
Step 4 实现功能 → 自测(见「自测检查清单」)
Step 4.5 【F-022 全节点挑战者反思】自测完成后、提交前执行
以「第一次接手这段代码的陌生开发者」视角执行3条挑战:
1. 边界输入:这些组件或函数在收到 null / undefined / 空字符串 / 超长字符串时,
UI 会崩溃还是优雅降级?有哪个 prop 没有做防御性检查?
2. 副作用:有没有哪个 useEffect / 状态更新会在某个条件下无限触发,
或在组件卸载后继续执行?
3. 复用遗漏:有没有某段逻辑或 UI 元素已经在其他页面/组件里存在,
本次重新写了而不是复用?
若发现可修复的问题 → 修复后再提交
若确实无重大问题 → 输出「前端自检:[具体轻微问题或潜在风险]」
Step 4.8【服务运行检查门】提交测试前必过(2026-03-21 新增)
⚠️ 在输出任何「人工验收清单」之前,先判断:服务是否已在运行?
检查方法(按顺序,任一为真即视为「运行中」):
□ 终端文件中有正在运行的 dev server 进程(如 vite / uvicorn / npm run dev)
□ 用户在本次对话中明确说「已启动」「在跑了」等
□ 有端口监听(lsof 或用户告知)
判断结果:
IF 服务「运行中」:
→ 正常执行 Step 5(输出「人工验收清单」),行为不变
IF 服务「未运行」:
→ 不输出「人工验收清单」
→ 改为输出「待部署后验收清单」(格式见下)
→ 主动询问用户:「后端/前端服务尚未启动,需要我帮你启动吗?」
「待部署后验收清单」格式:
```
📋 待部署后验收清单(服务启动后执行)
以下项目需要打开浏览器人工确认:
1. [验收项描述]
2. [验收项描述]
…
启动方式:[告知如何启动,或询问用户是否需要帮助]
```
⚠️ 禁止:服务未运行时输出「请在浏览器中验证」类语句——这会给用户制造
「任务完成」的错觉,但实际上什么都测不了。
⚠️ 补充禁令(2026-03-21 第三次同类问题后加入):
- 重启服务后,禁止只做 /health 检查就宣布就绪——必须重跑 DevOps RULE-LOC 完整清单
- 「之前测过」不等于「现在还对」——重启后一切都要重新验证
- 本次任务新增了哪些功能路径,就必须在 RULE-LOC V11+ 补上对应的端到端测试
Step 4.9【开发计划任务状态同步门】(2026-03-22 新增,任务完成后必须执行)
目的:确保代码实现与 开发计划.md 的任务状态保持同步,杜绝「代码完成但文档显示未完成」的错位。
执行步骤:
1. 回顾本次实现的功能,在 开发计划.md 中找到对应的任务条目
2. 将该条目的 `[ ]` 改为 `[x]`,并在完成标准中勾选对应项
3. 若本次功能未在 开发计划.md 中有对应条目 → 在开发计划中追加新条目并标 ✅
4. 同时更新任务总览的计数
查找规则(按优先级):
- 直接搜索功能名称(如「brain_init」「TwinSetupFlow」)
- 搜索对应的产品定义章节编号(如「PD-014」「G.3」)
- 若找不到→新建条目(不允许以「找不到」为由跳过)
⚠️ 禁止:代码跑通了就跳过 Step 4.9,必须先完成文档同步再提交测试
Step 5 提交给测试工程师(附自测清单 + 无法自测项清单)
frontend/
├── src/
│ ├── api/ ← API 调用模块
│ │ ├── auth.ts ← 认证 API(只放认证,不混业务)
│ │ └── [业务].ts ← 各业务 API 独立文件
│ ├── pages/ ← 页面级组件
│ ├── components/ ← 通用组件
│ ├── hooks/ ← 自定义 hooks
│ ├── types/ ← TypeScript 类型
│ └── utils/ ← 工具函数
├── public/
├── vite.config.ts
├── package.json
└── Dockerfile
见:.cursor/skills/role-前端开发/knowledge/前端踩坑速查.md
核心踩坑摘要:
| # | 症状 | 根因 | 修复 |
|---|---|---|---|
| 1 | API 请求静默失败,Unexpected end of JSON input | vite 代理端口与 BACKEND_PORT 不一致 | 对齐 vite.config.ts 中的 proxy 端口 |
| 2 | 验证码框不显示 | input 藏在 codeSent 条件后 | 始终显示,按钮 disabled 控制 |
| 3 | import 断链 orgApi not found | 业务 API 混入 auth.ts 后被删 | 业务 API 放独立文件,不混入 auth.ts |
| 4 | 登录后看不到 AI 引导 | 根路由固定跳 /chat,没判断用户状态 | 用 HomeRedirect 组件检查状态再跳转 |
| 5 | localhost:3000 报 ERR_CONNECTION_REFUSED (-102) | Node 18+ Windows 默认绑定 IPv6 ::1,Chrome 先试 IPv4 被拒 | vite.config.ts 加 host: '127.0.0.1',或直接访问 127.0.0.1:3000 |
| 6 | 流式输出时用户向上翻页,界面立即跳回底部 | useEffect 无条件调用 scrollIntoView(),忽略用户翻页行为 | 用 ref 追踪是否在底部,只在底部时才自动滚动;向上翻时显示「回到底部」浮动按钮(详见 FE-11) |
| 7 | Write 覆写文件后 StrReplace 将文件回退到旧结构混入新结构 | StrReplace old_string 在旧文件和新文件均可匹配,执行了错误替换 | Write 覆写后先 Read 验证新内容,确认后再做后续 StrReplace(详见 FE-15) |
| 8 | 发送按钮点击无反应,无任何提示(静默失败) | token resolver 把 localStorage 放最高优先级 → 旧 token → 401 → wsId 永远 null → handleSend 第一行 return | ① localStorage token 降为最低优先级;② getWorkspaces 失败时清缓存重试;③ wsId=null 时显示明确错误提示(详见 FE-12) |
| 9 | 切换分身后组件数据不更新(旧数据残留) | useCallback deps 含多余 state → useEffect 重跑 → 模块变量被重置覆盖新值 | useCallback 只保留必要 deps;切换回调直接 async fetch,不走依赖模块变量的共享 loader;行为标记用 useRef 而非 useState(详见 FE-16) |
| 10 | 登录后需认证 API 全线 401;Authorization 恒为空;控制台无报错 | AuthContext 写入 token 与 api.ts(或 getAuthHeader)读取 token 使用不同 localStorage key,读写永不相交 | 统一定义 TOKEN_KEY 常量,全局 import;迁移前全文搜索 localStorage 的 get/set/removeItem 核对 key;集成测试断言登录后 GET /auth/me 返回 200(勿仅断言 token 字符串存在)(详见 FE-17) |
从 TopicLab 或其他产品复制任何页面/组件/API 模块时,必须先执行以下验证,才允许开始复制。
判断标准:本次任务是否涉及从其他产品直接复制/参考代码?
IF YES(涉及跨产品复制):
Step 1 列出组件/页面调用的所有 API 端点
示例:RegisterPage → /api/auth/send-code、/api/auth/register
Step 2 对每个端点,在本项目后端执行验证:
curl -X POST /api/auth/send-code → 404?(该接口不存在)
curl -X POST /api/auth/register -d '{}' → 422 required 字段列表?
Step 3 比对字段差异,明确记录:
| 端点 | 来源产品字段 | 本项目字段 | 差异 |
|---|---|---|---|
| /auth/register | phone, code, password | phone, invite_code, password, display_name | code→invite_code |
Step 4 根据差异重写接口调用代码(视觉风格可保留,接口层必须适配)
IF NO(全新组件,无跨产品复制):
→ 直接进入正常开发流程
禁止:直接照搬另一产品的接口调用,不经过验证
禁止:「两个产品都用同一套后端」为由跳过验证(各项目接口可能不同)
模板来源:
项目群/Tashan-TopicLab/frontend/src/api/auth.ts项目群/Tashan-TopicLab/frontend/src/pages/Register.tsx / Login.tsx⚠️ 登录页 vs 注册页规范(必须区分):
| 页面 | 规范 |
|---|---|
| LoginPage.tsx | 字面照抄 TopicLab(仅删除 Router 依赖),API 路径 /auth/login 两边相同 |
| RegisterPage.tsx | 先验证后端 /auth/register 接口所需字段,再决定是否照抄。注册流程可能因产品不同而异(TopicLab=短信验证码 / OpenBrain=邀请码),不允许不验证就直接照抄 |
验证后端注册流程的步骤:
1. curl -X POST /api/auth/register -d '{}' → 查看 422 错误中的 required 字段
2. curl -X POST /api/auth/send-code → 是否返回 404?(404=没有短信流程)
3. 根据实际字段编写 RegisterPage,保持视觉风格与 TopicLab 一致但接口适配后端
六个关键约束(违反必出 Bug):
auth_token,自动附加到所有受保护请求头// vite.config.ts
export default defineConfig({
server: {
port: 310X, // ← 与 FRONTEND_PORT 对齐
proxy: {
'/api': {
target: 'http://localhost:810X', // ← 与 BACKEND_PORT 完全一致
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''), // 去掉 /api 前缀再发给后端
}
}
}
})
⚠️ 关键:vite proxy 剥离 /api 前缀后的路径匹配规则
前端调用: /api/platform/brains
vite 转发: /platform/brains (已去掉 /api)
后端收到: /platform/brains
因此后端 FastAPI router prefix 规则:
✅ 正确:router = APIRouter(prefix="/platform") → 路由 /platform/brains
❌ 错误:router = APIRouter(prefix="/api/platform") → 路由 /api/platform/brains(多了 /api,永远匹配不到)
判断方法:curl http://localhost:{BACKEND_PORT}/platform/brains(不含 /api)能否返回 200?
能 → prefix 正确;不能 → prefix 包含了 /api 前缀,需要去掉
// SSE 前端接收
const eventSource = new EventSource('/api/chat/stream', {
// 带认证头需要用 fetch + ReadableStream
});
// 推荐方式:fetch + ReadableStream
const response = await fetch('/api/chat/stream', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ message }),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
const lines = text.split('\n');
for (const line of lines) {
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
const data = JSON.parse(line.());
}
}
}
□ 每个功能节点按设计稿还原(视觉、交互都对)
□ 空状态处理:用户没有数据时,页面显示引导而非空白
□ 加载状态:API 请求中有明确的 loading 提示
□ 错误状态:API 失败时有用户可读的错误提示
□ 跨浏览器:Chrome / Safari 主流版本验证
□ 响应式:移动端和桌面端都能正常显示
□ API 接口:所有接口路径和参数与后端约定完全一致
□ 端口对齐:vite proxy 端口 = BACKEND_PORT
□ **新增调用的函数 import 已更新**:Ctrl+F 搜索每个新用到的函数名,确认 import 行存在(FE-10)
□ **代码删除后无游离 JSX 碎片**:StrReplace 删除代码块时覆盖到最后的关闭符,删除后刷新浏览器确认无 Vite parse error(FE-11)
□ **多视图布局中有状态组件用 CSS hidden 而非条件渲染**:对话/表单等有 state 的组件确认使用 `display:none` 控制显隐(FE-12)
□ 【必填】无法自测项清单:列出所有需要打开浏览器人工确认的体验项
(例:Banner 显示是否正确、动画效果、弹窗交互等视觉/体验类问题)
这份清单随代码一起提交给测试工程师,不可省略
我接收:
我输出:
技术架构师/技术问题追踪台.md 对应条目状态更新为「已修复(含修复说明)」修复任何 Bug 后(包括用户反馈的问题、关卡C 发现的问题、追踪台中的问题),必须执行以下步骤:
Step 1 构造原 Bug 的复现场景(触发条件 + 预期行为 + 实际行为)
Step 2 调用 /verifier 子智能体(前台,等待完成)
传入:
- 被修复的功能描述
- 原 Bug 复现场景(用于验证是否真正修复)
- 修改的文件路径列表
done_criteria: [原 Bug 场景下行为符合预期]
Step 3 verifier 返回后:
→ pass:更新追踪台对应条目状态为「已修复(已验证)」
告知用户:「Bug 已修复并通过验证」
→ fail:说明原因,继续修复,重复 Step 1-3
(最多 3 轮,3 轮后仍失败升级给用户决策)
前端特有注意:前端 Bug 修复后,体验类验证(视觉/交互)仍需人工确认——verifier 只验证逻辑层面,体验层面必须输出「人工验收清单」。
遇到设计-工程冲突时:主动通知 PM 和设计师,等待决策,不自行决断
根因:五条工程原则对照分析(TASK-20260320-01)证明:role-前端开发缺少「先写测试再实现」的任何步骤,完全未覆盖 TDD 原则,是结构性空白。
修改内容:
验证结果:
验证状态:🔵 待验证
根因:双模式功能开发中,前端完成后未列出体验类验收项(Banner 显示、popover 交互等),导致测试工程师无从知晓哪些需要人工打开浏览器验证。
修改内容:
验证结果:
已知风险:开发者可能识别不完整(处于开发视角),清单不能保证完备,只保证存在
根因:追踪台写入后没有人负责关闭,状态永远「未解决」,失去参考价值。
修改内容:
根因:openclaw-proxy 项目聊天界面开发时,useEffect 无条件调用 scrollIntoView(),导致用户向上翻页时被强制跳回底部,无法查看历史消息。踩坑速查中无此记录。
经验核心:用 ref(非 state)追踪滚动位置,仅在底部时自动滚动;用户离开底部时显示浮动「回到底部」按钮;用户发送新消息时重置锁定状态。
修改内容:
验证结果:
本节由 uto-experience-hook Rule 驱动,此处为提示性说明。
执行本 Skill 过程中,若触发以下任一信号,立即追加一行到暂存区(不中断主任务):
暂存格式(追加到 .cursor/skills/skill-index/PENDING-EXPERIENCES.md):
| [今日日期] | [本Skill目录名] | [信号类型] | [一句话描述经验内容] | 🔲 待处理 |
所有执行步骤完成后,检查暂存区是否有新增条目。若有,在收尾时告知用户: 「本次执行感知到 N 条经验(已暂存),任务确认跑通后可说「做一次项目复盘」处理。」
⚠️ 强制收尾——写入任务日志(不可省略,不可等用户提示):
执行顺序铁律:先工具调用 → 确认成功 → 告知用户。禁止声称「已写入」而未实际调用工具。
1. [工具调用-读取] grep 今日 TASK-YYYYMMDD 全部条目,取最大序号 NN → 新序号 = NN+1
2. [工具调用-写入] StrReplace 追加到 `_内部总控/任务日志.md`:
本次 Skill 执行的核心操作 + 创建/修改的文件 + 用户原始需求 + 遗留事项
3. 工具调用成功 → 输出「📝 任务日志已写入 [TASK-YYYYMMDD-NN]」
工具调用报错 → 输出「⚠️ 任务日志写入失败,请手动检查任务日志.md」
这是继「跨产品前端统一」之后第二个最常见的执行漏洞,必须在动笔前先判断。
判断标准:本次任务是「范式升级」还是「功能叠加」?
范式升级(必须推倒重建)的典型特征:
□ 整体主题/视觉风格发生根本变化(深色 → 浅色;工具风格 → 平台风格)
□ 核心布局结构完全不同(单栏 → 三栏;Owner/Visitor双模式 → 统一登录体验)
□ 某个旧功能模式在新产品里「概念上不存在」(如旧版 IS_PROXY 在新平台里没有意义)
□ 用户类型定义发生变化(单一Owner → 所有人平等登录)
功能叠加(可以在现有基础上增加)的特征:
□ 在现有页面里新增一个按钮/组件/标签页
□ 新增一条导航路由,不改变已有页面
□ 后端接口增加字段,前端展示新字段
范式升级的强制前置步骤(不可跳过):
Step A【废弃清单】:列出所有与新设计矛盾的旧代码模式,逐一标注「删除/替换/保留」
示例:IS_PROXY 逻辑 → 删除(新产品不存在访客模式)
旧 AppLayout 深色背景 → 替换(用 TopicLab 浅色方案)
BrainChat.tsx 组件 → 保留(功能组件,只需放入新容器)
Step B【基础选择】:明确以哪个产品/框架为重建基础
他山产品标准:以 TopicLab 为前端基础(CSS Variables / 组件风格 / Auth 流程)
禁止:在旧产品的 App.tsx 上打补丁
Step C【范围声明】:告知用户「本次将重写 App.tsx + 替换布局,保留以下功能组件:[列表]」
等待用户确认范围后再开始写代码
违反此规则的症状:
IS_PROXY ? <OldView> : <NewView>)⚠️ 最常见误区:「只复制
modules/目录 ≠ 前端完全一致」
「前端完全一致」必须覆盖以下 4 个层次,缺一不可:
| 层次 | 路径 | 说明 | 遗漏后果 |
|---|---|---|---|
| 层1 模块层 | src/modules/{功能}/ | 核心功能组件(步骤流程、状态逻辑等) | 功能失效 |
| 层2 页面容器层 | src/pages/{功能}Page.tsx | 页面标题、标签名、整体布局容器 | ⚠️ 最常被遗漏:标题/标签显示旧产品名称 |
| 层3 设计系统层 | 全局 CSS 变量 | --bg-secondary、--text-primary 等 Design Token | 颜色、间距与源产品不一致 |
| 层4 路由层 | App.tsx 中的路由注册 | 路径是否与源产品一致,/profile-helper 等 | 路径不同导致跳转/分享链接失效 |
执行跨产品统一时的检查顺序:
□ 层1:src/modules/{功能}/ 目录完整复制并适配
□ 层2:src/pages/{功能}Page.tsx 页面容器已更新(标题/标签/布局容器)← 重点检查
□ 层3:全局 CSS 变量 / Design Token 已同步(搜索 var(-- 确认变量名一致)
□ 层4:App.tsx 路由注册路径已对齐
根因:同 role-后端开发——AI 修完前端 Bug 后没有自动重测闭合回路。
修改内容:
验证状态:🔵 待验证
根因:SK-004 沙盘验证发现:role-前端开发 激活后直接读 技术架构.md,若文件不存在只是跳过,不会阻断。这使得用户可绕过关卡A/B,直接让 AI 写前端代码,造成核心流程被穿越。
修改内容:
验证结果:
已知风险:项目路径需要 AI 自行识别,多项目场景可能需要用户指定路径
根因:full-node-audit.mdc 要求所有代码生产节点在提交前内置挑战者反思,role-前端开发在自测后直接提交,缺少独立挑战者视角的边界输入/副作用/复用遗漏检查。
修改内容:
验证状态:🔵 待验证
根因:本次对话中发生两处问题: ① TASK-24 覆盖了 TASK-23 已写好的 platform_api.py(多会话协作时没有先查任务日志) ② proxy_v2_api.py 的 router prefix 写成 "/api/proxy" 而非 "/proxy",导致 vite proxy 剥离 /api 后路径不匹配
修改内容:
验证状态:✅ 已验证(本次 openbrain 开发中暴露了这两个问题)
根因:RegisterPage.tsx 照抄 TopicLab 的短信验证码注册流程,但 OpenBrain 后端用邀请码注册,没有 /auth/send-code 接口。用户尝试注册时看到 404 Not Found。
修改内容:
验证状态:✅ 已验证(本次修复了 RegisterPage 为邀请码流程,注册404问题解决)
根因:OpenBrain v2.0 前端实现时(TASK-24),当产品从「单用户工具+IS_PROXY访客模式」升级为「多用户平台+统一登录」时,AI 选择了在旧 App.tsx 上打补丁,保留了 IS_PROXY 旧代码,而不是以 TopicLab 为基础重建。用户打开页面看到的仍然是旧深色主题的登录页。根因是 Skill 中「跨产品前端统一」章节只覆盖「复制组件」场景,没有「整体范式替换」规则。
修改内容:
验证结果:
验证状态:🔵 待验证(本次 OpenBrain 前端重建时验证)
根因:RegisterPage.tsx 从 TopicLab 照抄,但两产品注册流程不同(TopicLab=短信验证码,OpenBrain=邀请码),前端直接调用 /api/auth/send-code 返回 404,注册功能完全失效。现有 Skill 只在「账号系统规范」中单独说明了注册页,但没有通用规则覆盖「复制任何跨产品组件时的接口验证」。
修改内容:
验证结果:
验证状态:🔵 待验证
根因:TASK-20260321-46(TwinSetupFlow 前端实现)完成后,按 Step 5 规范输出了「人工验收清单」,但 tashan-openbrain 服务从未在本机启动(.env 里是 Windows 路径,前端 dev server 也未启动),用户根本无法测试任何内容。这个问题在本次对话中多次复现,根因是 Skill 的 Step 5 无前置检查,无条件输出测试清单,默认「服务已在运行」的假设从未被显式化。
修改内容:
验证结果:
已知风险:「服务运行状态」判断依赖终端文件状态,若用户在外部终端启动服务但不在 IDE 内,可能误判为「未运行」→ 已在规范中加入「用户明确说已启动」作为第二判据
验证状态:🔵 待验证(下次前端开发任务完成时观察)
根因:跨产品前端统一任务中,只复制 modules/ 目录,未更新页面容器层(ProfileHelperPage.tsx),导致标题、标签名、布局与源产品完全不同,视觉不一致。现有 Skill 无「前端统一范围」章节,属步骤偏差。
经验核心:「前端完全一致」= 层1模块 + 层2页面容器 + 层3设计系统 + 层4路由,缺少层2是最常见的遗漏点。
修改内容:
## 跨产品前端统一的完整范围 章节,含4层定义表格和执行检查清单验证结果:
验证状态:🔵 待验证
根因:tashan-openbrain 开发中,backend 改变 nginx 路由时,前端 AuthContext 的 workspace_id 字段消费被静默破坏。根本原因是「改上游,不检查下游期望」(违反 L1.5 P17 下游优先检查)。
修改内容:
验证结果:
验证状态:🔵 待验证
根因:scenario-sandbox-builder Phase 2 验证(PD-015沙盘)发现:Step 0.2「前端API消费检查表」发现❌项后,只要求「所有❌必须解决」,但未定义「后端字段问题由谁修复」。缺少向 role-后端开发 路由的显式指令,导致修复方不清晰。
修改内容:
history/SKILL_v1.5_20260322_before_pd015.md验证方法:前端联调发现字段不匹配时,Skill 应输出「需要 role-后端开发 修复」而非静默等待 验证状态:🔵 待验证
根因:
修改内容:
验证结果:
场景:token resolver 把 localStorage 放最高优先级 → localStorage 里是旧 token → getWorkspaces() 返回 401 → wsId 永远 null → handleSend 第一行 return,无任何提示
根因:localStorage token 优先级过高 + wsId=null 时无用户提示
解决:
预防:所有前端「发送/提交」操作必须在 wsId=null 时显示明确错误状态,禁止静默失败
根因:project-retrospective-20260323 批量沉淀积压经验。
修改内容:
备份路径:history/SKILL_before_20260323.md
验证状态:🔵 待验证
修改内容:
备份路径:
history/SKILL_v1.6_20260323_before_changelog_fix.md注:本条变更记录补录于 2026-03-23,实际代码改动发生于上述两个日期。
验证状态:🔵 待验证
场景:分身切换后,DocTree / 数据列表仍显示旧分身的内容,切换回调被覆盖。
根因:
loadDocs = useCallback(() => { fetch(getDocRegistry()) }, [user, navView])
useEffect(() => { loadDocs(); setActiveTwinWorkspace('') }, [user, loadDocs])
navView 进入 useCallback deps → navView 变化时 loadDocs 引用更新 → useEffect 重跑 → setActiveTwinWorkspace('') 覆盖了 onSwitch 刚写入的新 workspace → 组件读到空 workspace,仍拉旧数据。
三条正确模式(已验证):
useCallback 只保留必要 deps,将模块变量与 re-render 解耦
// ❌ 错误:navView 进入 deps,导致 useEffect 在切换时重跑并重置模块变量
const loadDocs = useCallback(() => { fetch(getDocRegistry()) }, [user, navView])
// ✅ 正确:只保留真正影响 fetch 逻辑的 deps
const loadDocs = useCallback(() => { fetch(getDocRegistry()) }, [user])
切换回调直接 async fetch,不走依赖模块变量的共享 loader
// ❌ 错误:setActiveTwinWorkspace 与 loadDocs 之间存在竞态
const onSwitch = (ws: string) => {
setActiveTwinWorkspace(ws)
loadDocs() // loadDocs 读的是旧 _activeTwinWorkspace
}
// ✅ 正确:直接 fetch 并显式传 workspace header,不依赖时序
const onSwitch = async (ws: string) => {
setActiveTwinWorkspace(ws)
const res = await fetch(url, { headers: { 'X-Twin-Workspace': ws } })
setDocRegistry(await res.json())
}
行为标记(如「是否首次登录」)用 useRef 而非 useState
// ❌ 错误:state 变化触发 re-render,可能连锁触发其他 effect
const [isFirstLogin, setIsFirstLogin] = ()
isFirstLoginRef = ()
预防:
useCallback 时,逐个问 deps 中的每个变量:「它的变化是否需要 useEffect 重跑?」useRef 存储而非放入 deps根因:tashan-openbrain_myagent 项目(TASK-20260322-100),分身切换后 DocTree 不更新 Bug。loadDocs 的 useCallback 将 navView 纳入依赖,导致 useEffect 在切换分身时重跑并调用 setActiveTwinWorkspace(''),覆盖了 onSwitch 刚写入的新 workspace,DocTree 仍读旧分身文档。
经验核心:useCallback deps 不等于「函数体内用到的所有变量」——只放「需要 effect 重跑」的变量;切换回调应直接 fetch + 明确传参,不依赖模块变量时序;行为标记用 useRef。
修改内容:
验证结果:
useCallback 依赖 user 的正常 refresh 逻辑不受影响备份路径:history/SKILL_v1.7_20260323.md
验证状态:✅ 已验证(tashan-openbrain_myagent TASK-20260322-100)
根因:project-retrospective retro-20260322d-b02;tashanbrain v2 迁移实战(2026-03-22),QA 第一轮发现。
经验核心:AuthContext 用 key A 写入 token,api.ts 用 key B 读取 → getAuthHeader() 恒为空 → 所有需认证请求 401,且无 JS 报错,极难肉眼定位。
修改内容:
验证结果:
TOKEN_KEY 贯通读写时行为不变备份路径:history/SKILL_v1.8_20260323.md
验证状态:🔵 待验证