Compare commits

...

2 Commits

Author SHA1 Message Date
lanrtop
965d095820 chore(release): v0.1.18
All checks were successful
Release / release (push) Successful in 4m18s
2026-07-03 13:24:32 +09:00
lanrtop
6efde66c42 feat(onboarding): T1 模板版本化三态分发 + B1 CONVENTIONS 1.10.0(R12/R13) + B2 agent 按钮章节
- dispatch_versioned:不存在写全新 / 有标记同版本跳过 / 版本不同原位升级块 / 无标记末尾追加块,块外用户内容永不触碰
- AGENTS.md.tmpl 重写为三分区:用户 TODO 区 + ONBOARDING_MANAGED v1.1.0 块(含 agent 按钮与验证路径章节)+ 四支柱防腐元规则
- git-workflow.md.tmpl 全文入管理块 v1.1.0
- CONVENTIONS 升 1.10.0:R12 边界单点实现、R13 验收路径须真实走通(含载体就近选择表)
- lefthook.yml 保持存在即跳过(用户深度定制不适用块机制)

Rules-Applied: R05-skip, R12, R13
2026-07-03 13:23:41 +09:00
10 changed files with 218 additions and 27 deletions

View File

@ -1,6 +1,6 @@
---
version: 1.9.0
updated: 2026-07-02
version: 1.10.0
updated: 2026-07-03
source: dev-manager-tauri
---
@ -928,6 +928,23 @@ scope 描述规则的正向适用范围,**boundaries 描述已知的反向边
- **evidence_count**: 1
- **derived_from**: 规则库只有正向 scope 无反例结构失败信息流失导致置信度虚高、边界永远探测不到2026-07-02 经验飞轮设计评审)
#### R12 — 边界单点实现:业务校验只写在能力本体层
- **scope**: `universal`
- **触发条件**:实现或修改带业务边界的功能(哪些允许、什么条件下允许、非法时如何拒绝)
- **自动动作**校验逻辑只写在能力本体层API / command / 服务函数UI 层只呈现状态(置灰/提示),不复制业务判断。发现前端 guard 承载业务边界时标记为需下沉
- **confidence**: 0.85
- **evidence_count**: 2
- **derived_from**: 空契约生成静默 return边界错写进 UI 层,与文案承诺冲突)、改 Token 假成功UI 报成功但本体未执行)——两例均为"人与 agent 验证路径空间分裂"症状2026-07-03
- **boundaries**: 纯展示逻辑(排序、折叠、格式化)属 UI 职责,不适用本规则
#### R13 — M/L 任务完成前,验收路径须被真实走通
- **scope**: `universal`
- **触发条件**M 或 L 复杂度任务卡准备标记 ✅ done
- **自动动作**acceptance 所述验证路径须由人或 agent **通过功能自身入口**真实走通一次agent 按钮载体就近选择Web 服务=HTTP API、CLI=命令、桌面应用=测试调用同一函数、UI 呈现层=Playwright 兜底。禁止绕过功能手改产物冒充验证agent 走通的关键路径顺手固化为一条测试(侦察→驻军),一次性验收不固化
- **confidence**: 0.80
- **evidence_count**: 2
- **derived_from**: noteapp manifest 被手改导致 schema 约束修复未获真实验证、autoforphone 接线被命令行代办导致 G7 按钮未走通——手动替代掩盖功能真实状态2026-07-03 用户裁决 + MCP 治理三件套 agent 实测首证)
### 规则演进路径
```

View File

@ -6,7 +6,7 @@ description: >
成为每个项目的贴身导师。炼境本身亦被纳入其中,
形成可自我进化的开发智能闭环。
iteration: 1
updated: 2026-07-02
updated: 2026-07-03
@ -369,8 +369,8 @@ modules:
name: 接入包
area: backend
status: in_progress
progress: 90
note: "新增体系分发主线2026-07-03T1 模板版本化(前置)→ B1-B4 agent 按钮体系四资产"
progress: 95
note: "体系分发主线2026-07-03T1 模板版本化 ✅ + B1 CONVENTIONS 1.10.0(R12/R13) ✅ + B2 AGENTS 模板 agent 按钮章节 ✅;剩 B3 提示词升级、B4 健康诊断遵守度"
position: [3500, 0]
- id: gitea-integration

View File

@ -98,16 +98,18 @@
- files: src-tauri/src/commands/onboarding.rs, src-tauri/src/commands/commit_metrics.rs
- acceptance: OnboardingReport 与飞轮展示标注该项目 commit 规范化比例conventional / 总数);比例低时提示"种 lefthook 后数据才准"避免脏数据被误读为可信CI 过滤 / 非规范单列已在 C1 落实)
### 📋 T1. 接入包模板版本化ONBOARDED_MANAGED 块机制)【体系分发前置】
- status: todo
### ✅ T1. 接入包模板版本化ONBOARDED_MANAGED 块机制)【体系分发前置】
- status: done
- done_note: 2026-07-03 dispatch_versioned 三态落地written/updated/appended + 同版本 skipped块外用户内容保护有测试兜底AGENTS/git-workflow 模板入 ONBOARDING_MANAGED v1.1.0 块lefthook 保持存在即跳过。对 enterprise-system/noteapp 的存量升级实测留给用户走 UI 流程R13
- complexity: M
- files: src-tauri/src/commands/onboarding.rs, src-tauri/resources/onboarding/git-workflow.md.tmpl, src-tauri/resources/onboarding/AGENTS.md.tmpl
- acceptance: git-workflow 与 AGENTS.md 模板的炼境管理内容包进 ONBOARDING_MANAGED 标记块(带 version分发逻辑三态文件不存在→写全新存在且有标记→原位更新块复用 blueprint.rs 的 upsert_managed_block 模式可提取公共函数存在无标记→末尾追加块块外用户内容永不触碰lefthook.yml 保持"存在即跳过"(用户深度定制不适用块机制);单元测试覆盖三态 + 用户区保护;对 enterprise-system 重跑接入包实测存量升级
> 背景模板演进无法触达存量项目是版本化闭环的最大缺口trailer 章节曾手工补)。
### 📋 agent 按钮体系分发B1/B2 可派发B3/B4 待拆)
- status: planned
### 🔵 agent 按钮体系分发B1/B2 已完成B3/B4 待做)
- status: in_progress
- progress: 2026-07-03 B1 done——CONVENTIONS 1.10.0 加 R12边界单点实现+ R13M/L 验收路径须真实走通含载体就近选择表B2 done——AGENTS.md.tmpl v1.1.0 管理块含「agent 按钮与验证路径」章节(双投影/边界单点/载体表/完成的定义/侦察→驻军)。剩 B3提示词升级M单独一轮、B4健康诊断遵守度后置
- 版本化闭环要求2026-07-03 用户澄清,体系分发的灵魂): 分发不是"发了就不管"——每类资产带版本分发 → 子项目按该版本实践产生经验(成功/失败)→ 经验自吸反哺炼境trailer/failure_cases/复盘/返工率)→ 按版本分组对比效果 → 修订出新版 → 再分发。CONVENTIONS 是模范生version+队列对比+梦核+同步1.8→1.9 已跑通一整圈B 系列每类资产按此标准建闭环。**前置依赖提升**「接入包模板演进分发MANAGED 块化」concept 卡——模板无版本机制是当前最大缺口,没有它体系 v2 到不了存量项目
- notes: 2026-07-03 概念探讨收束后的分发需求(体系详见 memory concept_dual_projection 与 mcp-server 模块 concept 卡)。用户全 agent 开发形态下,"给开发者立规范"="给 agent 注入规范",可完全机器化。四条现成管道分发四类资产:① B1(S) CONVENTIONS 1.10.0 加 R12 边界单点实现 + R13 验收须真实走通验证路径 + 载体选择原则;② B2(S) 接入包 AGENTS.md 模板加 agent 按钮章节(三要素/载体谱系/侦察驻军);③ B3(M) init/sync 提示词升级——建蓝图时声明项目按钮载体、acceptance 生成为可执行验证路径格式;④ B4(S,后置) 健康诊断加体系遵守度检查。移植体验=零新增动作,接入流程不变。

View File

@ -1,7 +1,7 @@
{
"name": "dev-manager-tauri",
"private": true,
"version": "0.1.17",
"version": "0.1.18",
"type": "module",
"scripts": {
"dev": "vite",

2
src-tauri/Cargo.lock generated
View File

@ -880,7 +880,7 @@ dependencies = [
[[package]]
name = "dev-manager-tauri"
version = "0.1.17"
version = "0.1.18"
dependencies = [
"axum",
"base64 0.22.1",

View File

@ -1,6 +1,6 @@
[package]
name = "dev-manager-tauri"
version = "0.1.17"
version = "0.1.18"
description = "A Tauri App"
authors = ["you"]
edition = "2021"

View File

@ -2,11 +2,21 @@
> 本文件遵循 [AGENTS.md 开放规范](https://agents.md/),供 Claude Code、Qwen Code、Cursor、Copilot 等 AI 工具读取。
> 由炼境接入包分发。请按项目实际补全下方 TODO 段落。
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外内容永不触碰。
## 项目概况
<!-- TODO: 一句话描述项目 + 技术栈。例pnpm monorepoReact 19 + TypeScript 前端 + Hono API。 -->
## 架构与模块
<!-- TODO: 列出主要目录/模块及职责,帮助 AI 快速定位「改哪里」。 -->
## 关键文档索引
<!-- TODO: 列出 README / ARCHITECTURE.md / 其他关键文档及用途。 -->
<!-- ONBOARDING_MANAGED_START version="1.1.0" -->
## 核心开发约束
### 包管理
@ -22,12 +32,27 @@
## Git 工作流
见 `docs/ai-context/git-workflow.md`(分支策略 + Conventional Commits + PR 规范)。
见 `docs/ai-context/git-workflow.md`(分支策略 + Conventional Commits + Rules-Applied trailer + PR 规范)。
**commit 必须符合 Conventional Commits**lefthook 强制),炼境据此采集飞轮数据。
## 架构与模块
## agent 按钮与验证路径
<!-- TODO: 列出主要目录/模块及职责,帮助 AI 快速定位「改哪里」。 -->
功能的本体是代码层的能力UI 按钮是它给人的投影,**agent 按钮**是给 agent 的投影
(可发现 + 可调用 + 有边界的能力声明)。开发任何功能时遵守:
1. **边界单点实现**业务校验只写在能力本体层API/commandUI 只呈现不复制逻辑——
否则人与 agent 的验证路径会分裂
2. **载体就近选择**(本项目的 agent 按钮是什么,按项目类型对号入座):
| 项目类型 | agent 按钮载体 |
|---------|---------------|
| Web 服务 | HTTP API 本身(前端按钮与 curl 调同一 endpoint天然双投影 |
| CLI/脚本 | 命令与 npm scripts |
| 桌面应用 | 测试直接调用 command 函数 |
| UI 呈现层 | Playwright 驱动真界面(最后手段,仅关键路径) |
3. **完成的定义**:功能实现后,由 agent 沿投影路径真实走通一次(起服务 → 调接口 →
断言行为),再交人做 UI 终验——不许绕过功能手改产物冒充验证
4. **侦察 → 驻军**agent 走通的关键路径顺手固化为一条测试vitest / cargo test
一次性验收不固化(少而稳 > 多而脆)
## 多 AI CLI 协作
@ -38,10 +63,7 @@
2. 待验证:<需要确认的地方>
3. 约束继承:<影响后续的关键限制>
```
## 关键文档索引
<!-- TODO: 列出 README / ARCHITECTURE.md / 其他关键文档及用途。 -->
<!-- ONBOARDING_MANAGED_END -->
---

View File

@ -1,6 +1,9 @@
# Git 工作流 — AI Agent 操作指南
> 把此文件粘贴给任何 AI Agent让它了解本项目的 git 工作方式。由炼境接入包分发。
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
<!-- ONBOARDING_MANAGED_START version="1.1.0" -->
## 分支策略
@ -76,3 +79,4 @@ git status --short
git log --oneline -10
git reset --soft HEAD~1 # 撤销最后一次 commit保留改动
```
<!-- ONBOARDING_MANAGED_END -->

View File

@ -1,12 +1,17 @@
//! 接入包模板分发(基线档)。
//!
//! 向项目种入 AGENTS.md / lefthook.yml / git-workflow.md 标准模板:
//! 文件不存在才写、绝不覆盖用户已有;返回每个模板的处理结果。
//! 版本化分发T12026-07-03AGENTS.md / git-workflow.md 的炼境管理内容
//! 包在 ONBOARDING_MANAGED 标记块中——文件不存在写全新;已有标记原位升级块;
//! 无标记则末尾追加块。块外用户内容永不触碰。
//! lefthook.yml 因用户常深度定制monorepo filter 等),保持"存在即跳过"。
//! 模板蓝本取自 enterprise-system已通用化。
use serde::{Deserialize, Serialize};
use std::path::Path;
const MANAGED_START: &str = "<!-- ONBOARDING_MANAGED_START";
const MANAGED_END: &str = "<!-- ONBOARDING_MANAGED_END -->";
// 标准模板(编译期内嵌)
const TMPL_AGENTS: &str = include_str!("../../resources/onboarding/AGENTS.md.tmpl");
const TMPL_LEFTHOOK: &str = include_str!("../../resources/onboarding/lefthook.yml.tmpl");
@ -55,14 +60,91 @@ fn dispatch_one(root: &Path, relative: &str, content: &str) -> TemplateResult {
}
}
/// 从模板中提取 ONBOARDING_MANAGED 块(含首尾标记行)。
fn extract_managed_block(template: &str) -> Option<&str> {
let start = template.find(MANAGED_START)?;
let end = template.find(MANAGED_END)? + MANAGED_END.len();
template.get(start..end)
}
/// 从标记行提取版本号(`version="x.y.z"`)。
fn block_version(text: &str) -> Option<&str> {
let start = text.find(MANAGED_START)?;
let rest = &text[start..];
let v = rest.find("version=\"")? + "version=\"".len();
let tail = &rest[v..];
tail.split('"').next()
}
/// 版本化分发(三态):不存在→写全新;有标记→原位升级块;无标记→末尾追加块。
fn dispatch_versioned(root: &Path, relative: &str, template: &str) -> TemplateResult {
let target = root.join(relative);
let tpl_block = match extract_managed_block(template) {
Some(b) => b,
None => return dispatch_one(root, relative, template), // 模板无标记,退化为旧行为
};
let tpl_ver = block_version(tpl_block).unwrap_or("?");
if !target.exists() {
return dispatch_one(root, relative, template);
}
let content = match std::fs::read_to_string(&target) {
Ok(c) => c,
Err(e) => {
return TemplateResult {
name: relative.to_string(),
action: "failed".into(),
detail: format!("读取失败: {e}"),
}
}
};
let (new_content, action, detail) = if let (Some(s), Some(e)) =
(content.find(MANAGED_START), content.find(MANAGED_END))
{
let old_ver = block_version(&content).unwrap_or("?").to_string();
if old_ver == tpl_ver {
return TemplateResult {
name: relative.to_string(),
action: "skipped".into(),
detail: format!("管理块已是 v{tpl_ver}"),
};
}
let mut nc = String::new();
nc.push_str(&content[..s]);
nc.push_str(tpl_block);
nc.push_str(&content[e + MANAGED_END.len()..]);
(nc, "updated", format!("管理块 v{old_ver} → v{tpl_ver},块外内容未动"))
} else {
(
format!("{}\n\n{}\n", content.trim_end(), tpl_block),
"appended",
format!("追加管理块 v{tpl_ver}(存量文件无标记,原内容保留在上方)"),
)
};
match std::fs::write(&target, new_content) {
Ok(_) => TemplateResult {
name: relative.to_string(),
action: action.into(),
detail,
},
Err(e) => TemplateResult {
name: relative.to_string(),
action: "failed".into(),
detail: format!("写入失败: {e}"),
},
}
}
/// 向项目分发全部基线模板,返回每个的处理结果。
/// project_path 为项目根WSL 项目为 \\wsl.localhost\... UNC 路径,可直接写)。
pub fn dispatch_templates(project_path: &str) -> Vec<TemplateResult> {
let root = Path::new(project_path.trim_end_matches(['/', '\\']));
vec![
dispatch_one(root, "AGENTS.md", TMPL_AGENTS),
dispatch_versioned(root, "AGENTS.md", TMPL_AGENTS),
dispatch_one(root, "lefthook.yml", TMPL_LEFTHOOK),
dispatch_one(root, "docs/ai-context/git-workflow.md", TMPL_GIT_WORKFLOW),
dispatch_versioned(root, "docs/ai-context/git-workflow.md", TMPL_GIT_WORKFLOW),
]
}
@ -103,13 +185,77 @@ mod tests {
assert!(base.join("lefthook.yml").exists());
assert!(base.join("docs/ai-context/git-workflow.md").exists());
// 改一个文件,验证再次分发不覆盖
// 改一个文件(无管理块标记),验证用户内容不被覆盖:
// T1 后的契约——AGENTS/git-workflow 追加管理块原内容保留lefthook 仍跳过
std::fs::write(base.join("AGENTS.md"), "用户自己的内容").unwrap();
let r2 = dispatch_templates(pp);
assert!(r2.iter().all(|t| t.action == "skipped"), "已存在应全部跳过");
let agents_r = r2.iter().find(|t| t.name == "AGENTS.md").unwrap();
assert_eq!(agents_r.action, "appended", "无标记存量文件应追加管理块");
let kept = std::fs::read_to_string(base.join("AGENTS.md")).unwrap();
assert_eq!(kept, "用户自己的内容", "绝不覆盖用户已有内容");
assert!(kept.starts_with("用户自己的内容"), "用户内容必须保留在原位");
let lefthook_r = r2.iter().find(|t| t.name == "lefthook.yml").unwrap();
assert_eq!(lefthook_r.action, "skipped", "lefthook 保持存在即跳过");
let _ = std::fs::remove_dir_all(&base);
}
// ── T1版本化三态分发 ────────────────────────────────────────────────
#[test]
fn versioned_dispatch_three_states() {
let base = std::env::temp_dir()
.join(format!("lianjing_onb_ver_test_{}", std::process::id()));
let _ = std::fs::remove_dir_all(&base);
std::fs::create_dir_all(&base).unwrap();
let pp = base.to_str().unwrap();
// 态一:不存在 → 写全新(含管理块标记)
let r1 = dispatch_templates(pp);
assert!(r1.iter().all(|t| t.action == "written"));
let agents = std::fs::read_to_string(base.join("AGENTS.md")).unwrap();
assert!(agents.contains(MANAGED_START) && agents.contains(MANAGED_END));
// 态二(同版本):有标记且版本一致 → skipped文件不动
let r2 = dispatch_templates(pp);
let agents_r = r2.iter().find(|t| t.name == "AGENTS.md").unwrap();
assert_eq!(agents_r.action, "skipped");
// 态二(旧版本):把版本改旧 + 块外加用户内容 → updated块升级、用户内容保留
let old = agents
.replace("version=\"1.1.0\"", "version=\"1.0.0\"")
.replace("## 项目概况", "## 项目概况
")
+ "
##
";
std::fs::write(base.join("AGENTS.md"), &old).unwrap();
let r3 = dispatch_templates(pp);
let agents_r = r3.iter().find(|t| t.name == "AGENTS.md").unwrap();
assert_eq!(agents_r.action, "updated");
let upgraded = std::fs::read_to_string(base.join("AGENTS.md")).unwrap();
assert!(upgraded.contains("version=\"1.1.0\""), "块应升级到模板版本");
assert!(upgraded.contains("我的项目说明"), "块外用户内容(前)须保留");
assert!(upgraded.contains("用户自加的章节"), "块外用户内容(后)须保留");
assert_eq!(upgraded.matches(MANAGED_START).count(), 1, "只有一个管理块");
// 态三:存量文件无标记 → appended原内容保留在上方
std::fs::write(base.join("AGENTS.md"), "# 手写的 AGENTS
").unwrap();
let r4 = dispatch_templates(pp);
let agents_r = r4.iter().find(|t| t.name == "AGENTS.md").unwrap();
assert_eq!(agents_r.action, "appended");
let appended = std::fs::read_to_string(base.join("AGENTS.md")).unwrap();
assert!(appended.starts_with("# 手写的 AGENTS"));
assert!(appended.contains(MANAGED_START));
// lefthook 始终保持"存在即跳过"
let lefthook_r = r4.iter().find(|t| t.name == "lefthook.yml").unwrap();
assert_eq!(lefthook_r.action, "skipped");
let _ = std::fs::remove_dir_all(&base);
}
}

View File

@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "dev-manager-tauri",
"version": "0.1.17",
"version": "0.1.18",
"identifier": "com.yangzhixiang.dev-manager-tauri",
"build": {
"beforeDevCommand": "pnpm dev",