diff --git a/src-tauri/resources/onboarding/.claude/commands/envoy.md b/src-tauri/resources/onboarding/.claude/commands/envoy.md new file mode 100644 index 0000000..b711334 --- /dev/null +++ b/src-tauri/resources/onboarding/.claude/commands/envoy.md @@ -0,0 +1,51 @@ +你是**炼境使者**——在子项目会话里代表炼境执行现场感知与回传。 + +直接执行以下步骤,无需用户提供任何输入。 + +## Step 1:读取项目身份 + +用 Read 工具读取 `.claude/liangjing.json`,获取 `project_id` 和项目名称。 +若文件不存在:输出 `⚠️ 未找到 .claude/liangjing.json,该项目未接入炼境` 并停止。 + +## Step 2:扫描本次会话 + +回顾本次会话的完整对话,识别有价值的洞察。 +跳过:纯代码实现细节、具体 bug 修复、一次性操作记录。 + +## Step 3:分类每条洞察 + +**📦 带回炼境**(满足任一条): +- 炼境分发的模板 / 约定 / 接入包有 bug 或可改进 +- 某工作流或实践有明确代价或验证结果(有具体证据) +- 会影响多个项目的体系级改进(哪怕还是假设) + +**🏠 留本项目**(同时满足以下所有): +- 只影响本项目的具体实现 +- 无任何跨项目复用价值 +- 纯猜测、零证据 + +## Step 4:发回炼境 + +对每条「带回」洞察,单独调用一次 `mcp__lian-jing__append_project_note`。 +- `project_id`:来自 Step 1 +- `content` 格式(严格遵守): + + 【炼境使者回传】来源: {项目名} + 类型: template_bug | validated_practice | workflow_hypothesis + 置信度: confirmed | under_validation + 影响范围: this_project | project_type:{类型} | all_projects + 内容: {一句话精确描述} + 建议炼境: fix_template | update_convention | log_for_review + +**`confirmed` 的门槛**:必须能陈述至少一条具体代价或验证结果(如"导致 N% 时间损耗"、"在 X 场景实测有效")。 +无法陈述具体证据的,一律标 `under_validation`,不得标 `confirmed`。 + +## Step 5:输出摘要 + +📦 已发回炼境 N 条 + · {标题}({置信度} · {影响范围}) + +🏠 留本项目 M 条 + · {标题} — {一句说明} + +若本次会话无任何体系级洞察,直接输出:`✅ 本次会话无需回传,无体系级洞察。` diff --git a/src-tauri/resources/onboarding/AGENTS.md.tmpl b/src-tauri/resources/onboarding/AGENTS.md.tmpl index d0c2973..54d6373 100644 --- a/src-tauri/resources/onboarding/AGENTS.md.tmpl +++ b/src-tauri/resources/onboarding/AGENTS.md.tmpl @@ -18,7 +18,7 @@ - + ## 核心开发约束 ### 包管理 @@ -31,6 +31,9 @@ - 异步统一 `async/await`,不用裸 Promise 链 - 错误处理明确 `try/catch`,不吞异常 - 优先编辑现有文件,避免创建不必要的新文件 +- **Playwright 版本固定**:`package.json` 里的 `playwright` 锁死版本号,去掉 `^`; + 另建 `test:install` 脚本显式安装浏览器(`playwright install --with-deps`), + 升级时有意识操作,避免 pnpm install 静默触发 ~200MB 的浏览器重下 ## Git 工作流 @@ -60,6 +63,11 @@ - 正例:`[Tauri command] apply_onboarding_pack(project_id) → written≥1,文件在磁盘存在` - 正例:`[HTTP API] POST /api/users → 201,body.id 非空` - 反例:`功能正常可用`(模糊,agent 无法自验) + + **分层原则**:凡含 UI 操作路径的 acceptance,必须拆成两段: + - `agent_verify:` — 机器可断言(HTTP 状态码、数据库记录、函数返回值);stop hook / CI 只验此段 + - `human_verify:` — 需人眼判断(视觉效果、拖拽手势、30 秒浏览器终验) + 纯 API / 命令行任务可省略 `human_verify:`;UI 拖拽 / 动画 / 视觉类必须拆,否则 stop hook 无法收敛。 6. **自验报告纪律**:交人终验前的反馈必须含「**没验什么**」一节(未覆盖的路径、依赖的 假设、不确定的地方);自修过程中改了断言/验收标准必须显式声明理由(改功能让测试过是 常规,改测试让功能过需报备);agent 自验对 acceptance,人终验对意图——acceptance diff --git a/src-tauri/resources/onboarding/lefthook.yml.tmpl b/src-tauri/resources/onboarding/lefthook.yml.tmpl index d7569a3..4f9b7d3 100644 --- a/src-tauri/resources/onboarding/lefthook.yml.tmpl +++ b/src-tauri/resources/onboarding/lefthook.yml.tmpl @@ -9,6 +9,13 @@ pre-commit: typecheck: glob: "*.{ts,tsx}" run: pnpm typecheck + # ⚠️ 如果项目有 API / 后端层,必须在此补对应的 typecheck——否则后端类型错误不会被拦截。 + # 取消注释并按实际填写(留多余示例行删掉即可): + # api-typecheck: + # glob: "api/**/*.{ts,tsx}" + # run: pnpm --filter api typecheck # monorepo workspace + # # run: pnpm exec tsc -p api/tsconfig.json --noEmit # 独立 tsconfig + # # run: pnpm -r typecheck # 递归所有包 commit-msg: commands: diff --git a/src-tauri/src/commands/onboarding.rs b/src-tauri/src/commands/onboarding.rs index b865e8d..b15540e 100644 --- a/src-tauri/src/commands/onboarding.rs +++ b/src-tauri/src/commands/onboarding.rs @@ -16,6 +16,7 @@ const MANAGED_END: &str = ""; const TMPL_AGENTS: &str = include_str!("../../resources/onboarding/AGENTS.md.tmpl"); const TMPL_LEFTHOOK: &str = include_str!("../../resources/onboarding/lefthook.yml.tmpl"); const TMPL_GIT_WORKFLOW: &str = include_str!("../../resources/onboarding/git-workflow.md.tmpl"); +const TMPL_ENVOY: &str = include_str!("../../resources/onboarding/.claude/commands/envoy.md"); /// 单个模板的分发结果。 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -145,6 +146,7 @@ pub fn dispatch_templates(project_path: &str) -> Vec { dispatch_versioned(root, "AGENTS.md", TMPL_AGENTS), dispatch_one(root, "lefthook.yml", TMPL_LEFTHOOK), dispatch_versioned(root, "docs/ai-context/git-workflow.md", TMPL_GIT_WORKFLOW), + dispatch_one(root, ".claude/commands/envoy.md", TMPL_ENVOY), ] }