chore(self-onboarding): 炼境自身接入产物治理——块外恢复被抹定制 + lefthook 检查段补齐
All checks were successful
Push & PR Check / check (push) Successful in 50s
All checks were successful
Push & PR Check / check (push) Successful in 50s
批量分发实调反噬实锤:分支策略表/Agent 按钮清单/降级约定/启动协议 第 4 条曾写在 MANAGED 托管块内,v1.6.0/1.11.0 块升级原位覆盖时被抹。 全部恢复至块外「炼境自身约定」区,教训入决策记录(本地定制严禁写 进托管块)。顺带:块外与块内重复的通用约束去重(单一事实来源)、 lefthook 补齐 blueprint-gate/conventional/feature-confirmed 检查段 (verify_onboarding 复验 7/7)、收编 envoy/blueprint-gate 接入产物。 Rules-Applied: R13
This commit is contained in:
parent
7cfbfb1b86
commit
f7ab6dbbb8
@ -31,6 +31,7 @@
|
||||
- 接入动作:现有 `apply_blueprint_buff` 升格为 `apply_onboarding_pack`,按档编排注入
|
||||
- 语义层进料口隐患:决策/验收/踩坑仍需主动写(与饿死复盘笔记同源),须配「从 PR 标题/commit body/review 评论半自动提取」,不再单纯指望人自觉
|
||||
- **分发文件三档升级语义(2026-07-15 择升环评估)**:① 版本化块文件(AGENTS/git-workflow)→ MANAGED 块原位升级;② 炼境全托管文件(envoy.md/blueprint-gate.cjs,用户不定制)→ 内容不一致即覆盖;③ 用户可定制文件(lefthook.yml)→ 绝不覆盖,但 verify_onboarding 须能检测落后。此前 ②③ 混用「存在即跳过」导致回流修正推不到存量项目
|
||||
- **本地定制严禁写进 MANAGED 块内(2026-07-15 实调反噬实锤)**:炼境自身曾把「分支策略表 / Agent 按钮清单 / 降级约定 / 启动协议第 4 条」写在托管块内,v1.6.0/1.11.0 块升级时全部被原位覆盖抹掉(托管块的设计行为)。已恢复至块外「炼境自身约定」区。规则:托管块只放分发内容,项目定制一律块外;改块内容只能改炼境模板源头再分发
|
||||
- **回流触发不自动化(2026-07-15 多角度辩证)**:否决子项目侧 hook 自动触发 /envoy——自动化触发拆掉人肉过滤层,诱导低价值回传污染通道,伤「择」换「环」转速。回流频率问题用炼境侧可观测性解(「沉默项目」诊断信号,见 B4 卡),人留在过滤环里。校验类需求优先放统计消费端(炼境 ingest)而非分发 hook(R12 边界单点 + 零分发成本 + 可回溯)
|
||||
|
||||
## 复用的现有能力(~60% 地基已具备)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
53
.claude/commands/envoy.md
Normal file
53
.claude/commands/envoy.md
Normal file
@ -0,0 +1,53 @@
|
||||
<!-- 由炼境托管:重跑接入包会用最新模板覆盖本文件,请勿在此做项目定制 -->
|
||||
|
||||
你是**炼境使者**——在子项目会话里代表炼境执行现场感知与回传。
|
||||
|
||||
直接执行以下步骤,无需用户提供任何输入。
|
||||
|
||||
## 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 条
|
||||
· {标题} — {一句说明}
|
||||
|
||||
若本次会话无任何体系级洞察,直接输出:`✅ 本次会话无需回传,无体系级洞察。`
|
||||
32
.claude/hooks/blueprint-gate.cjs
Normal file
32
.claude/hooks/blueprint-gate.cjs
Normal file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env node
|
||||
// 由炼境托管:重跑接入包会用最新模板覆盖本文件,请勿在此做项目定制。
|
||||
// 蓝图门控:pre-commit 检查未关闭的 🔵 任务卡,warn only(exit 0,不阻断提交)。
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const modulesDir = path.join(process.cwd(), '.blueprint', 'modules');
|
||||
|
||||
if (!fs.existsSync(modulesDir)) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const unclosed = [];
|
||||
for (const file of fs.readdirSync(modulesDir).filter(f => f.endsWith('.md'))) {
|
||||
const content = fs.readFileSync(path.join(modulesDir, file), 'utf8');
|
||||
for (const line of content.split('\n')) {
|
||||
if (line.startsWith('### 🔵')) {
|
||||
unclosed.push({ file, title: line.replace(/^###\s*🔵\s*/, '').trim() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unclosed.length > 0) {
|
||||
process.stderr.write('\n⚠️ 蓝图门控:发现未关闭任务卡\n');
|
||||
for (const { file, title } of unclosed) {
|
||||
process.stderr.write(` 🔵 ${title}(${file})\n`);
|
||||
}
|
||||
process.stderr.write('\n 已完成 → 改为 ✅;仍进行中 → 属预期,可忽略本提示。\n\n');
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
132
AGENTS.md
132
AGENTS.md
@ -15,11 +15,9 @@ Git 多空间开发管理器,同时也是**项目 Agent 化改造引擎**。
|
||||
- MCP Server:内嵌于 Tauri 进程(HTTP),供 Claude Code 调用炼境数据
|
||||
- 包管理:pnpm(禁止 npm/yarn/npx/bun)
|
||||
|
||||
## 核心开发约束
|
||||
## 炼境特有开发约束
|
||||
|
||||
**包管理**:pnpm 唯一,禁止 npm / yarn / npx / bun。
|
||||
|
||||
**TypeScript**:优先 TypeScript,避免 `any`;函数/变量 camelCase,组件 PascalCase;async/await,不用裸 Promise 链;try/catch 不吞异常。
|
||||
> 通用约束(pnpm / TS 规范 / 需求对齐协议)见下方 ONBOARDING_MANAGED 块——单一事实来源,勿在此复抄。
|
||||
|
||||
**Rust 业务函数**:禁止在函数内部调用 `pool().get()`,连接由调用方传入(依赖注入,便于 in-memory DB 测试)。Tauri command 层负责获取连接并调用(薄包装,无需测试)。
|
||||
|
||||
@ -45,16 +43,6 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
2. **SQLite 新增表或字段 → 必须在 `db.rs` 的 `migrate()` 里补 migration 语句**,否则旧版本升级后启动报错
|
||||
3. **修改接入包模板(`resources/onboarding/`)→ 检查 `docs/templates/agents-meta-rules.md` 是否需要同步**
|
||||
|
||||
## 多 AI CLI 协作
|
||||
|
||||
本项目可由多个 AI CLI 协同。交接时附上:
|
||||
|
||||
```
|
||||
已完成:<修改了哪些文件 + 核心决策>
|
||||
待验证:<需要对方确认的地方>
|
||||
约束继承:<影响后续工作的关键限制>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent 友好工程四支柱
|
||||
@ -112,7 +100,7 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
- [ ] `src/lib/commands.ts` 的封装覆盖了所有 `src-tauri/src/commands/` 下的 command 吗?
|
||||
- [ ] 接入包模板(`resources/onboarding/`)和 `docs/templates/` 内容一致吗?
|
||||
|
||||
<!-- BLUEPRINT_MANAGED_START version="1.10.0" -->
|
||||
<!-- BLUEPRINT_MANAGED_START version="1.11.0" -->
|
||||
## 项目蓝图
|
||||
|
||||
本项目使用 `.blueprint/` 目录维护项目全景架构图,驱动需求讨论和任务管理。
|
||||
@ -150,7 +138,7 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
完整规则(迭代管理、阻塞处理、复盘笔记等)详见 `.blueprint/CONVENTIONS.md`。
|
||||
<!-- BLUEPRINT_MANAGED_END -->
|
||||
|
||||
<!-- ONBOARDING_MANAGED_START version="1.2.0" -->
|
||||
<!-- ONBOARDING_MANAGED_START version="1.6.0" -->
|
||||
## 核心开发约束
|
||||
|
||||
### 包管理
|
||||
@ -163,38 +151,43 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
- 异步统一 `async/await`,不用裸 Promise 链
|
||||
- 错误处理明确 `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 处理,走完整确认卡。
|
||||
|
||||
**提交时**:`feat:` 提交须在 commit message 末尾加 `Feature-Confirmed: true` trailer(lefthook commit-msg 强制检查)。这是确认卡已输出的机器层存证。
|
||||
|
||||
> ⚠️ Session 结束汇总补录 ≠ 确认卡替代——补录仅适用于漂移检测触发后用户主动选择补录的场景,不得作为「先做再补」的通道。
|
||||
|
||||
## Git 工作流
|
||||
|
||||
见 `docs/ai-context/git-workflow.md`(Conventional Commits + Rules-Applied trailer + PR 规范)。
|
||||
见 `docs/ai-context/git-workflow.md`(分支策略 + Conventional Commits + Rules-Applied trailer + PR 规范)。
|
||||
**commit 必须符合 Conventional Commits**(lefthook 强制),炼境据此采集飞轮数据。
|
||||
|
||||
### 炼境自身的分支策略
|
||||
|
||||
> `git-workflow.md` 是分发给被管理子项目的接入包模板(dev→main 双分支)。
|
||||
> 炼境自身使用以下策略,不套用子项目模板。
|
||||
|
||||
| 任务复杂度 | 分支策略 |
|
||||
|-----------|---------|
|
||||
| S(简单增删改) | 直接 push `master`,不开分支 |
|
||||
| M(中等逻辑) | 开 `feat/<blueprint-module-id>` 分支,完成后 PR → `master` |
|
||||
| L(复杂系统) | 开 `feat/<blueprint-module-id>` 分支,必须走 PR + CI 验证 |
|
||||
|
||||
**分支命名**:直接对应蓝图模块 ID,如 `feat/manage-multi-view`、`feat/flywheel-intelligence`。
|
||||
|
||||
**为什么 M/L 要开分支**:
|
||||
- PR body 是 agent 自验报告的归宿,飞轮从中采集结构化数据(PR 事件比 push 事件包含更多意图信息)
|
||||
- feat/* 分支触发 PR CI,是 agent 自验链条的最后一环(本地 typecheck → PR CI → 人终验)
|
||||
- 炼境推荐子项目走 PR 工作流,自身也应遵守同一套规范
|
||||
|
||||
## agent 按钮与验证路径
|
||||
|
||||
> 完整体系设计见 `docs/ai-context/agent-button-system.md`。
|
||||
|
||||
**分工原则**:人定目标 → agent 执行 → agent 自验(走 agent 按钮)→ 人终验。
|
||||
人只保留两件事:**需求澄清(目标定义权)** 和 **目标验收(终验权)**。
|
||||
|
||||
开发任何功能时遵守:
|
||||
功能的本体是代码层的能力;UI 按钮是它给人的投影,**agent 按钮**是给 agent 的投影
|
||||
(可发现 + 可调用 + 有边界的能力声明)。开发任何功能时遵守:
|
||||
|
||||
1. **边界单点实现**:业务校验只写在能力本体层(API/command),UI 只呈现不复制逻辑——
|
||||
否则人与 agent 的验证路径会分裂
|
||||
@ -207,18 +200,62 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
| UI 呈现层 | Playwright 驱动真界面(最后手段,仅关键路径) |
|
||||
3. **完成的定义**:功能实现后,由 agent 沿投影路径真实走通一次(起服务 → 调接口 →
|
||||
断言行为),再交人做 UI 终验——不许绕过功能手改产物冒充验证
|
||||
4. **侦察 → 驻军**:agent 走通的关键路径,顺手固化为一条测试(炼境主路径为 cargo test;vitest 仅在引入独立纯逻辑模块后按需添加);
|
||||
4. **侦察 → 驻军**:agent 走通的关键路径,顺手固化为一条测试(桌面应用用 cargo test;Web 项目纯逻辑层用 vitest);
|
||||
一次性验收不固化(少而稳 > 多而脆)
|
||||
5. **acceptance 可执行化**:`/splitter` 生成任务卡时,`acceptance` 字段必须是可执行验证路径,
|
||||
格式:`[载体] 调用/运行什么(参数) → 断言什么`。
|
||||
- 正例:`[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
|
||||
可能继承需求理解偏差,两把尺子不可合一
|
||||
|
||||
## 多 AI CLI 协作
|
||||
|
||||
本项目可由多个 AI CLI 协同。交接时把结果总结成 3 条传给下一个:
|
||||
|
||||
```
|
||||
1. 已完成:<改了哪些文件 + 核心决策>
|
||||
2. 待验证:<需要确认的地方>
|
||||
3. 约束继承:<影响后续的关键限制>
|
||||
```
|
||||
<!-- ONBOARDING_MANAGED_END -->
|
||||
|
||||
## 炼境自身约定(块外区——托管块升级不会触碰本节)
|
||||
|
||||
> ⚠️ 教训(2026-07-15):本地定制严禁写进 MANAGED 块内——块会被版本升级原位覆盖。
|
||||
> 本节内容曾因写在块内被 v1.6.0 升级抹掉,现恢复至块外。
|
||||
|
||||
### 炼境自身的分支策略
|
||||
|
||||
> 块内 git-workflow 是分发给子项目的通用策略;炼境自身按下表执行。
|
||||
|
||||
| 任务复杂度 | 分支策略 |
|
||||
|-----------|---------|
|
||||
| S(简单增删改) | 直接 push `master`,不开分支 |
|
||||
| M(中等逻辑) | 开 `feat/<blueprint-module-id>` 分支,完成后 PR → `master` |
|
||||
| L(复杂系统) | 开 `feat/<blueprint-module-id>` 分支,必须走 PR + CI 验证 |
|
||||
|
||||
**分支命名**:直接对应蓝图模块 ID,如 `feat/manage-multi-view`;同名旧分支已存在时加卡号后缀(如 `feat/onboarding-pack-u1`)。
|
||||
|
||||
**为什么 M/L 要开分支**:
|
||||
- PR body 是 agent 自验报告的归宿,飞轮从中采集结构化数据(PR 事件比 push 事件包含更多意图信息)
|
||||
- feat/* 分支触发 PR CI,是 agent 自验链条的最后一环(本地 typecheck → PR CI → 人终验)
|
||||
- 炼境推荐子项目走 PR 工作流,自身也应遵守同一套规范
|
||||
|
||||
### 分工原则
|
||||
|
||||
人定目标 → agent 执行 → agent 自验(走 agent 按钮)→ 人终验。
|
||||
人只保留两件事:**需求澄清(目标定义权)** 和 **目标验收(终验权)**。
|
||||
完整体系设计见 `docs/ai-context/agent-button-system.md`。
|
||||
|
||||
### 炼境自己的 Agent 按钮清单
|
||||
|
||||
| 能力 | 调用方式 | 通过标准 |
|
||||
@ -236,14 +273,3 @@ docs/templates/ 炼境接入包模板草案(设计层)
|
||||
1. 失败原因(具体报错或不通过的断言)
|
||||
2. 已尝试的修正路径
|
||||
3. 需要人决策的具体问题
|
||||
|
||||
## 多 AI CLI 协作
|
||||
|
||||
本项目可由多个 AI CLI 协同。交接时把结果总结成 3 条传给下一个:
|
||||
|
||||
```
|
||||
1. 已完成:<改了哪些文件 + 核心决策>
|
||||
2. 待验证:<需要确认的地方>
|
||||
3. 约束继承:<影响后续的关键限制>
|
||||
```
|
||||
<!-- ONBOARDING_MANAGED_END -->
|
||||
|
||||
@ -47,7 +47,7 @@ docs/templates/ 炼境接入包模板草案(agents-meta-rules
|
||||
- 代码重构/简化:/simplify → /code-review
|
||||
- 发现深层问题:/Dev-deep-think
|
||||
|
||||
<!-- BLUEPRINT_MANAGED_START version="1.10.0" -->
|
||||
<!-- BLUEPRINT_MANAGED_START version="1.11.0" -->
|
||||
## 项目蓝图
|
||||
|
||||
蓝图工作流规则统一维护在 @AGENTS.md 的 BLUEPRINT_MANAGED 区(跨工具单一来源,勿在此复制)。
|
||||
@ -56,5 +56,7 @@ docs/templates/ 炼境接入包模板草案(agents-meta-rules
|
||||
1. 读取 `.blueprint/manifest.yaml` 了解项目全景和当前状态
|
||||
2. 读取 `.blueprint/CONVENTIONS.md` 了解完整工作流规则
|
||||
3. 遵循 AGENTS.md 中的蓝图工作流(需求→蓝图同步、复杂度决策、两阶段提交)
|
||||
4. 调用 `mcp__lian-jing__list_envoy_returns` 检查子项目使者回传——若有待处理条目,在开始其他任务前先列出,询问是否立即处置
|
||||
<!-- BLUEPRINT_MANAGED_END -->
|
||||
|
||||
**炼境自身附加启动步骤(块外,勿移入托管块——块升级会覆盖)**:
|
||||
4. 调用 `mcp__lian-jing__list_envoy_returns` 检查子项目使者回传——若有待处理条目,在开始其他任务前先列出,询问是否立即处置
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
||||
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
|
||||
|
||||
<!-- ONBOARDING_MANAGED_START version="1.3.0" -->
|
||||
<!-- ONBOARDING_MANAGED_START version="1.5.0" -->
|
||||
|
||||
## 分支策略(复杂度感知)
|
||||
|
||||
@ -48,7 +48,7 @@ git commit -m "fix(api/user): 修正分页 off-by-one"
|
||||
|
||||
## Rules-Applied trailer(规则命中回传)
|
||||
|
||||
若本次任务中触发过 CONVENTIONS 自动推荐规则(R01-R11,见 `.blueprint/CONVENTIONS.md` 规则列表),
|
||||
若本次任务中触发过项目约定规则(见项目 CONVENTIONS.md 或 `.blueprint/CONVENTIONS.md`),
|
||||
在 commit message 末尾追加一行 trailer(与正文空行分隔):
|
||||
|
||||
```
|
||||
|
||||
13
lefthook.yml
13
lefthook.yml
@ -1,11 +1,18 @@
|
||||
# 炼境自身 lefthook 配置(对齐接入包模板的检查段键名,verify_onboarding 按键自省检测)
|
||||
pre-commit:
|
||||
parallel: true
|
||||
commands:
|
||||
typecheck:
|
||||
glob: "src/**/*.{ts,tsx}"
|
||||
run: pnpm typecheck
|
||||
blueprint-gate:
|
||||
run: node .claude/hooks/blueprint-gate.cjs || true
|
||||
|
||||
commit-msg:
|
||||
scripts:
|
||||
"check-conventional.sh":
|
||||
runner: bash
|
||||
commands:
|
||||
conventional:
|
||||
run: "head -1 .git/COMMIT_EDITMSG | grep -qE '^(feat|fix|docs|chore|refactor|ci|perf|style|test|build|revert)(\\(.+\\))?!?: .+' || exit 1"
|
||||
feature-confirmed:
|
||||
run: |
|
||||
head -1 .git/COMMIT_EDITMSG | grep -qE '^feat' || exit 0
|
||||
grep -q 'Feature-Confirmed: true' .git/COMMIT_EDITMSG || { printf '\n⚠️ feat: 提交须含 Feature-Confirmed: true trailer\n 在 commit message 末尾加一行:Feature-Confirmed: true\n (确认卡已与用户对齐,方可提交)\n\n' >&2; exit 1; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user