Compare commits
No commits in common. "8c746cf8d5a6b0eea1783066b8f362983f3a3c8c" and "fd869ee161eed52ba98586e92f5fbbaf150876dd" have entirely different histories.
8c746cf8d5
...
fd869ee161
@ -56,5 +56,4 @@ docs/templates/ 炼境接入包模板草案(agents-meta-rules
|
|||||||
1. 读取 `.blueprint/manifest.yaml` 了解项目全景和当前状态
|
1. 读取 `.blueprint/manifest.yaml` 了解项目全景和当前状态
|
||||||
2. 读取 `.blueprint/CONVENTIONS.md` 了解完整工作流规则
|
2. 读取 `.blueprint/CONVENTIONS.md` 了解完整工作流规则
|
||||||
3. 遵循 AGENTS.md 中的蓝图工作流(需求→蓝图同步、复杂度决策、两阶段提交)
|
3. 遵循 AGENTS.md 中的蓝图工作流(需求→蓝图同步、复杂度决策、两阶段提交)
|
||||||
4. 调用 `mcp__lian-jing__list_envoy_returns` 检查子项目使者回传——若有待处理条目,在开始其他任务前先列出,询问是否立即处置
|
|
||||||
<!-- BLUEPRINT_MANAGED_END -->
|
<!-- BLUEPRINT_MANAGED_END -->
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
你是**炼境使者**——在子项目会话里代表炼境执行现场感知与回传。
|
|
||||||
|
|
||||||
直接执行以下步骤,无需用户提供任何输入。
|
|
||||||
|
|
||||||
## 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 条
|
|
||||||
· {标题} — {一句说明}
|
|
||||||
|
|
||||||
若本次会话无任何体系级洞察,直接输出:`✅ 本次会话无需回传,无体系级洞察。`
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<!-- TODO: 列出 README / ARCHITECTURE.md / 其他关键文档及用途。 -->
|
<!-- TODO: 列出 README / ARCHITECTURE.md / 其他关键文档及用途。 -->
|
||||||
|
|
||||||
<!-- ONBOARDING_MANAGED_START version="1.5.0" -->
|
<!-- ONBOARDING_MANAGED_START version="1.3.0" -->
|
||||||
## 核心开发约束
|
## 核心开发约束
|
||||||
|
|
||||||
### 包管理
|
### 包管理
|
||||||
@ -31,31 +31,6 @@
|
|||||||
- 异步统一 `async/await`,不用裸 Promise 链
|
- 异步统一 `async/await`,不用裸 Promise 链
|
||||||
- 错误处理明确 `try/catch`,不吞异常
|
- 错误处理明确 `try/catch`,不吞异常
|
||||||
- 优先编辑现有文件,避免创建不必要的新文件
|
- 优先编辑现有文件,避免创建不必要的新文件
|
||||||
- **Playwright 版本固定**:`package.json` 里的 `playwright` 锁死版本号,去掉 `^`;
|
|
||||||
另建 `test:install` 脚本显式安装浏览器(`playwright install --with-deps`),
|
|
||||||
升级时有意识操作,避免 pnpm install 静默触发 ~200MB 的浏览器重下
|
|
||||||
|
|
||||||
## 需求对齐协议
|
|
||||||
|
|
||||||
开始写代码前,先判断改动类型:
|
|
||||||
|
|
||||||
**Bug Fix**(当前行为与预期的意外偏差)
|
|
||||||
→ 建任务卡,直接执行,无需等确认词。
|
|
||||||
|
|
||||||
**Feature / 行为变更**(新增能力或主动改变已有行为)
|
|
||||||
→ 必须先输出确认卡,等用户说「确认」再动手:
|
|
||||||
|
|
||||||
- **S 级**(单文件、行为对外无变化,任务卡 complexity=S):输出三行轻量卡
|
|
||||||
```
|
|
||||||
改哪:<文件或模块>
|
|
||||||
改什么:<一句话>
|
|
||||||
验收:<agent_verify 路径>
|
|
||||||
```
|
|
||||||
- **M / L 级**:输出完整任务卡(含 `files` + `acceptance` + `complexity`),等确认
|
|
||||||
|
|
||||||
**边界模糊时**:保守判断,按 Feature 处理,走完整确认卡。
|
|
||||||
|
|
||||||
> ⚠️ Session 结束汇总补录 ≠ 确认卡替代——补录仅适用于漂移检测触发后用户主动选择补录的场景,不得作为「先做再补」的通道。
|
|
||||||
|
|
||||||
## Git 工作流
|
## Git 工作流
|
||||||
|
|
||||||
@ -85,11 +60,6 @@
|
|||||||
- 正例:`[Tauri command] apply_onboarding_pack(project_id) → written≥1,文件在磁盘存在`
|
- 正例:`[Tauri command] apply_onboarding_pack(project_id) → written≥1,文件在磁盘存在`
|
||||||
- 正例:`[HTTP API] POST /api/users → 201,body.id 非空`
|
- 正例:`[HTTP API] POST /api/users → 201,body.id 非空`
|
||||||
- 反例:`功能正常可用`(模糊,agent 无法自验)
|
- 反例:`功能正常可用`(模糊,agent 无法自验)
|
||||||
|
|
||||||
**分层原则**:凡含 UI 操作路径的 acceptance,必须拆成两段:
|
|
||||||
- `agent_verify:` — 机器可断言(HTTP 状态码、数据库记录、函数返回值);stop hook / CI 只验此段
|
|
||||||
- `human_verify:` — 需人眼判断(视觉效果、拖拽手势、30 秒浏览器终验)
|
|
||||||
纯 API / 命令行任务可省略 `human_verify:`;UI 拖拽 / 动画 / 视觉类必须拆,否则 stop hook 无法收敛。
|
|
||||||
6. **自验报告纪律**:交人终验前的反馈必须含「**没验什么**」一节(未覆盖的路径、依赖的
|
6. **自验报告纪律**:交人终验前的反馈必须含「**没验什么**」一节(未覆盖的路径、依赖的
|
||||||
假设、不确定的地方);自修过程中改了断言/验收标准必须显式声明理由(改功能让测试过是
|
假设、不确定的地方);自修过程中改了断言/验收标准必须显式声明理由(改功能让测试过是
|
||||||
常规,改测试让功能过需报备);agent 自验对 acceptance,人终验对意图——acceptance
|
常规,改测试让功能过需报备);agent 自验对 acceptance,人终验对意图——acceptance
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
||||||
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
|
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
|
||||||
|
|
||||||
<!-- ONBOARDING_MANAGED_START version="1.5.0" -->
|
<!-- ONBOARDING_MANAGED_START version="1.4.0" -->
|
||||||
|
|
||||||
## 分支策略(复杂度感知)
|
## 分支策略(复杂度感知)
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ git commit -m "fix(api/user): 修正分页 off-by-one"
|
|||||||
|
|
||||||
## Rules-Applied trailer(规则命中回传)
|
## Rules-Applied trailer(规则命中回传)
|
||||||
|
|
||||||
若本次任务中触发过项目约定规则(见项目 CONVENTIONS.md 或 `.blueprint/CONVENTIONS.md`),
|
若本次任务中触发过 CONVENTIONS 自动推荐规则(R01-R11,见 `.blueprint/CONVENTIONS.md` 规则列表),
|
||||||
在 commit message 末尾追加一行 trailer(与正文空行分隔):
|
在 commit message 末尾追加一行 trailer(与正文空行分隔):
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@ -9,13 +9,6 @@ pre-commit:
|
|||||||
typecheck:
|
typecheck:
|
||||||
glob: "*.{ts,tsx}"
|
glob: "*.{ts,tsx}"
|
||||||
run: pnpm typecheck
|
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:
|
commit-msg:
|
||||||
commands:
|
commands:
|
||||||
|
|||||||
@ -16,7 +16,6 @@ const MANAGED_END: &str = "<!-- ONBOARDING_MANAGED_END -->";
|
|||||||
const TMPL_AGENTS: &str = include_str!("../../resources/onboarding/AGENTS.md.tmpl");
|
const TMPL_AGENTS: &str = include_str!("../../resources/onboarding/AGENTS.md.tmpl");
|
||||||
const TMPL_LEFTHOOK: &str = include_str!("../../resources/onboarding/lefthook.yml.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_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)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
@ -146,7 +145,6 @@ pub fn dispatch_templates(project_path: &str) -> Vec<TemplateResult> {
|
|||||||
dispatch_versioned(root, "AGENTS.md", TMPL_AGENTS),
|
dispatch_versioned(root, "AGENTS.md", TMPL_AGENTS),
|
||||||
dispatch_one(root, "lefthook.yml", TMPL_LEFTHOOK),
|
dispatch_one(root, "lefthook.yml", TMPL_LEFTHOOK),
|
||||||
dispatch_versioned(root, "docs/ai-context/git-workflow.md", TMPL_GIT_WORKFLOW),
|
dispatch_versioned(root, "docs/ai-context/git-workflow.md", TMPL_GIT_WORKFLOW),
|
||||||
dispatch_one(root, ".claude/commands/envoy.md", TMPL_ENVOY),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,14 +57,6 @@ pub fn tools_list_result() -> Value {
|
|||||||
"required": ["project_id"]
|
"required": ["project_id"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "list_envoy_returns",
|
|
||||||
"description": "列出所有子项目通过「炼境使者」发回炼境的待处理洞察,按项目分组展示。炼境会话启动时调用,用于检查是否有需要处置的治理反馈(模板 bug、验证有效的实践、体系改进假设)。无需任何参数。",
|
|
||||||
"inputSchema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "append_project_note",
|
"name": "append_project_note",
|
||||||
"description": "将 Claude 的分析结论或复盘记录写入项目笔记,供未来会话和用户在炼境中查阅。完成 M/L 复杂度任务后必须调用,写入结构化复盘笔记。",
|
"description": "将 Claude 的分析结论或复盘记录写入项目笔记,供未来会话和用户在炼境中查阅。完成 M/L 复杂度任务后必须调用,写入结构化复盘笔记。",
|
||||||
@ -378,9 +370,6 @@ pub async fn tools_call(params: Option<&Value>) -> Value {
|
|||||||
let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or("");
|
let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
get_project_mentor_context(pid)
|
get_project_mentor_context(pid)
|
||||||
}
|
}
|
||||||
"list_envoy_returns" => {
|
|
||||||
list_envoy_returns()
|
|
||||||
}
|
|
||||||
"append_project_note" => {
|
"append_project_note" => {
|
||||||
let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or("");
|
let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
let content = args.get("content").and_then(|v| v.as_str()).unwrap_or("");
|
let content = args.get("content").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
@ -898,46 +887,6 @@ fn get_project_mentor_context(project_id: &str) -> Result<String, String> {
|
|||||||
Ok(ctx.mentor_markdown)
|
Ok(ctx.mentor_markdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_envoy_returns() -> Result<String, String> {
|
|
||||||
let conn = db::pool().get().map_err(|e| e.to_string())?;
|
|
||||||
let mut stmt = conn
|
|
||||||
.prepare(
|
|
||||||
"SELECT pn.id, pp.name, pn.content, pn.created_at
|
|
||||||
FROM project_notes pn
|
|
||||||
JOIN project_workspaces pw ON pn.project_id = pw.id
|
|
||||||
JOIN project_profiles pp ON pw.profile_id = pp.id
|
|
||||||
WHERE pn.content LIKE '【炼境使者回传】%'
|
|
||||||
ORDER BY pn.created_at DESC
|
|
||||||
LIMIT 50",
|
|
||||||
)
|
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
let rows: Vec<(i64, String, String, String)> = stmt
|
|
||||||
.query_map([], |row| {
|
|
||||||
Ok((
|
|
||||||
row.get::<_, i64>(0)?,
|
|
||||||
row.get::<_, String>(1)?,
|
|
||||||
row.get::<_, String>(2)?,
|
|
||||||
row.get::<_, String>(3)?,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.map_err(|e| e.to_string())?
|
|
||||||
.filter_map(|r| r.ok())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if rows.is_empty() {
|
|
||||||
return Ok("📭 暂无待处理的炼境使者回传".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut out = format!("📬 炼境使者回传(共 {} 条)\n\n", rows.len());
|
|
||||||
for (_id, project_name, content, created_at) in &rows {
|
|
||||||
let date = &created_at[..created_at.len().min(10)];
|
|
||||||
out.push_str(&format!("---\n**来源**: {} | **时间**: {}\n{}\n\n", project_name, date, content));
|
|
||||||
}
|
|
||||||
out.push_str("---\n💡 处置参考:fix_template → 改接入包模板文件;update_convention → 改 CONVENTIONS.md;log_for_review → 记录待观察,暂不动模板");
|
|
||||||
Ok(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_project_note(project_id: &str, content: &str) -> Result<String, String> {
|
fn append_project_note(project_id: &str, content: &str) -> Result<String, String> {
|
||||||
if content.trim().is_empty() {
|
if content.trim().is_empty() {
|
||||||
return Err("笔记内容不能为空".to_string());
|
return Err("笔记内容不能为空".to_string());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user