Compare commits

...

4 Commits

Author SHA1 Message Date
cfdaily 3f07c528b6 [moz] docs: 重写 §26 Gitea 协作规范设计(流水账→设计文档风格)
CI / lint (pull_request) Successful in 7s
CI / test (pull_request) Successful in 28s
CI / notify-on-failure (pull_request) Successful in 1s
- §26 从落地流水账重写为正式设计文档
- 新增 26.1 设计目标(三个问题 + 目标)
- 新增 26.2 规范设计(标题规范/Label 体系/模板,含设计决策)
- 新增 26.3 执行机制(四层注入 + L2 priority 设计理由)
- 新增 26.4 Label 迁移策略(旧标签保留,不做批量迁移)
- 新增 26.5 与其他章节的交叉引用关系
- 保留 26.6 实现记录(压缩为记录而非主体)
- §4.5 末尾加交叉引用指向 §26
- P3 色值从 #c5def5 改为 #cfd3d7(解决与 type/impl 混淆)
2026-06-14 12:07:47 +08:00
pangtong-fujunshi 207c2aaaef Merge PR #69: [moz] feat: Gitea 协作规范落地 — 标题前缀+Label+模板+L2注入 2026-06-14 03:53:48 +00:00
cfdaily a89a70a983 feat: Gitea 协作规范落地 — 标题前缀+Label+模板+L2注入
CI / lint (pull_request) Successful in 7s
CI / test (pull_request) Successful in 30s
CI / notify-on-failure (pull_request) Successful in 0s
2026-06-14 11:51:57 +08:00
pangtong-fujunshi 1c939bfa27 Merge PR #68: impl: #16 知识注入 L2 引擎层 — WikiGuideSection 2026-06-14 02:35:34 +00:00
10 changed files with 295 additions and 15 deletions
+34
View File
@@ -0,0 +1,34 @@
name: Bug 报告
about: 报告一个 Bug
title: "[moz] bug: "
labels:
- type/bug
body:
- type: textarea
id: description
attributes:
label: Bug 描述
description: 清晰描述什么行为是错误的
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: 复现步骤
validations:
required: true
- type: textarea
id: expected
attributes:
label: 预期行为
validations:
required: true
- type: dropdown
id: priority
attributes:
label: 优先级
options:
- P0 紧急
- P1 高
- P2 中
- P3 低
+27
View File
@@ -0,0 +1,27 @@
name: 功能需求
about: 提出一个新功能需求
title: "[moz] feat: "
labels:
- type/feat
body:
- type: textarea
id: description
attributes:
label: 需求描述
description: 你希望实现什么功能?为什么需要?
validations:
required: true
- type: textarea
id: solution
attributes:
label: 建议方案
description: 如果有初步想法可以写 here
- type: dropdown
id: priority
attributes:
label: 优先级
options:
- P0 紧急
- P1 高
- P2 中
- P3 低
+20
View File
@@ -0,0 +1,20 @@
name: 测试任务
about: 创建一个测试任务(E2E、集成测试等)
title: "[moz] test: "
labels:
- type/test
body:
- type: textarea
id: description
attributes:
label: 测试目标
description: 要验证什么场景?
validations:
required: true
- type: textarea
id: steps
attributes:
label: 测试步骤
description: 关键步骤或验收标准
validations:
required: true
+26
View File
@@ -0,0 +1,26 @@
## 改动概述
<!-- 一句话说明这个 PR 做了什么 -->
## 关联 Issue
<!-- #issue_number,如果没有关联可删掉 -->
## 改动类型
- [ ] feat: 新功能
- [ ] impl: 实现
- [ ] fix: 修复
- [ ] docs: 文档
- [ ] test: 测试
- [ ] refactor: 重构
- [ ] ci: CI/CD
- [ ] chore: 杂项
## 检查清单
- [ ] 标题格式正确:`[代号] type(scope): 简述`
- [ ] 改动在开发目录(`~/.openclaw/sanguo_projects/`)完成
- [ ] 已同步到安装目录(`~/.sanguo_projects/`
- [ ] 已运行测试(如适用)
- [ ] 已更新相关设计文档(如适用)
+156 -9
View File
@@ -245,11 +245,14 @@ pm2 show sanguo-act-runner # 详情
|------|------|
| `feat` | 新功能 |
| `fix` | Bug 修复 |
| `impl` | 按设计文档实现 |
| `refactor` | 重构(不改行为) |
| `test` | 测试相关 |
| `docs` | 文档 |
| `chore` | 构建/工具/配置 |
sanguo 组织所有仓库统一使用此 commit 规范。
---
## §4. 问题管理
@@ -266,15 +269,19 @@ pm2 show sanguo-act-runner # 详情
### 4.2 Issue 标签体系
| 标签 | 颜色 | 说明 |
|------|------|------|
| `bug` | 红 | 功能异常 |
| `feature` | 蓝 | 新功能需求 |
| `improvement` | 绿 | 改进优化 |
| `security` | 橙 | 安全相关 |
| `risk:high/standard/low` | 分级色 | 风险级别(见 §6.1 判定规则) |
| `priority:high/medium/low` | 黄/灰 | 优先级 |
| `blocked` | | 阻塞中 |
| 标签 | 颜色 | 色值 | 说明 |
|------|------|------|------|
| `type/bug` | 红 | #ee0701 | Bug 修复 |
| `type/feat` | 蓝 | #84b6eb | 新功能 |
| `type/impl` | 浅蓝 | #c5def5 | 按设计实现 |
| `type/docs` | 黄 | #fbca04 | 文档 |
| `type/test` | 绿 | #0e8a16 | 测试 |
| `type/ci` | 紫 | #d4c5f9 | CI/CD |
| `type/refactor` | | #ff6f00 | 重构 |
| `priority/P0` | 深红 | #b60205 | 紧急 |
| `priority/P1` | 红 | #d93f0b | 高 |
| `priority/P2` | 黄 | #fbca04 | 中 |
| `priority/P3` | 浅蓝 | #c5def5 | 低 |
### 4.3 需求/问题 Review 前置
@@ -296,6 +303,29 @@ Open → In Progress → Review → Closed
└──── Reopened ←───────────────────┘
```
### 4.5 标题规范
所有 Issue 和 PR 标题**必须**包含项目代号前缀,让人类一眼识别项目+类型:
**Issue**: `[代号] type: 简述`
**PR**: `[代号] type(scope): 简述`
项目代号:
| 仓库 | 代号 |
|------|------|
| sanguo_moziplus_v2 | moz |
| sanguo_quant_live | quant |
| sanguo_vnpy | vnpy |
示例:
- `[moz] bug: Mail API 500 when comment_type invalid`
- `[moz] impl(daemon): 知识注入 L2 引擎层 — WikiGuideSection`
- `[quant] feat: 趋势跟踪策略骨架`
此规范通过 L2 引擎层 `GiteaConventionSection`priority=55)自动注入所有 Agent prompt。
完整规范文档:L3 Skill `gitea-conventions`。规范设计原理详见 [§26](#26-gitea-协作规范设计)。
---
## §5. CI/CD 管道设计
@@ -3297,3 +3327,120 @@ async def _handle_issue_comment(payload):
|------|------|------|
| 2026-06-09 | v1.0 | 初版:E2E 真实场景暴露问题 → 四层改造方案 + @mention 通知 + Mail type 改造 |
---
## §26. Gitea 协作规范设计
> **状态**: ✅ 已实现(PR #69
> **日期**: 2026-06-14
### 26.1 设计目标
团队三个仓库(moziplus_v2 / quant_live / vnpy)在 Gitea 上独立存在,协作时存在三个问题:
1. **标题不可辨识**`Fix mail API` 看不出是哪个项目、什么类型的改动
2. **Label 缺失**:无统一标签体系,无法按类型/优先级筛选
3. **填写无约束**:Issue/PR 内容格式随意,审查时缺少关键信息
本规范的目标:让人类一眼识别项目+类型,让 Agent 可程序化遵循,让模板降低填写门槛。
### 26.2 规范设计
#### 26.2.1 标题规范
**规则**:所有 Issue/PR 标题必须包含项目代号前缀。
| 类型 | 格式 | 示例 |
|------|------|------|
| Issue | `[代号] type: 简述` | `[moz] bug: Mail API 500 when comment_type invalid` |
| PR | `[代号] type(scope): 简述` | `[moz] impl(daemon): WikiGuideSection 注入` |
**项目代号**moz=moziplus_v2, quant=quant_live, vnpy=vnpy
**type 清单**bug / feat / impl / fix / docs / test / ci / refactor / chore
**设计决策**
- 为什么用代号前缀而不是靠仓库隔离?— 团队成员同时在多仓库协作,通知列表(Mail、Gitea dashboard)混合展示时代号前缀提供即时辨识。仓库隔离解决不了跨仓库视图的辨识问题
- PR 加 `scope` 是因为 PR 通常涉及具体模块(daemon / api / frontend),Issue 不需要
#### 26.2.2 Label 体系
采用 `type/*` + `priority/*` 双命名空间,替代旧标签(bug/feature/improvement/security):
| 标签 | 色值 | 说明 |
|------|------|------|
| `type/bug` | #ee0701 | Bug 修复 |
| `type/feat` | #84b6eb | 新功能 |
| `type/impl` | #c5def5 | 按设计实现 |
| `type/docs` | #fbca04 | 文档 |
| `type/test` | #0e8a16 | 测试 |
| `type/ci` | #d4c5f9 | CI/CD |
| `type/refactor` | #ff6f00 | 重构 |
| `priority/P0` | #b60205 | 紧急 |
| `priority/P1` | #d93f0b | 高 |
| `priority/P2` | #fbca04 | 中 |
| `priority/P3` | #cfd3d7 | 低 |
**设计决策**
-`type/` `priority/` 命名空间而非扁平命名,避免标签膨胀时冲突,且在 Gitea UI 中按前缀分组显示
- type 用暖色系(红/橙/黄),priority 用冷→热渐变(灰→蓝→黄→红),视觉上两类标签不混淆
- ⚠️ 已知问题:`type/impl`(#c5def5) 与 `priority/P3` 色值相近。P3 已调整为灰色 #cfd3d7 以区分
#### 26.2.3 Issue/PR 模板
**Issue 模板**3 种):bug.yml / feature.yml / test.yml
覆盖决策:只做最高频的 3 种类型(bug 报告、功能需求、测试任务),其余类型(docs/ci/refactor)频率低,走自由创建。每种模板包含描述、复现/方案、优先级字段。
**PR 模板**1 种):PULL_REQUEST_TEMPLATE.md
改动类型 checklist + 检查清单(标题格式、开发→安装目录同步、测试、设计文档更新)。
### 26.3 执行机制
规范通过四层路径保证执行,每层职责不同:
| 层 | 载体 | 职责 | Token 成本 |
|----|------|------|-----------|
| **L1** | TOOLS.mdAgent workspace | 代号表 + 格式速查,Agent 静态可见 | ~100 |
| **L2** | `GiteaConventionSection`priority=55 | 每次 spawn 动态注入,提醒标题格式 | ~80 |
| **L3** | `gitea-conventions` SkillextraDirs | 完整规范(标题/分支/commit/label),Agent 按需加载 | 按需 |
| **Gitea** | Issue/PR Template + Label(仓库级) | 人类创建时表单引导,标签选择 | — |
**L2 设计决策**
- `GiteaConventionSection` priority=55,排在 Constraints(50) 之后、Extension(60) 之前。标题规范属于约束类,但优先级低于安全/流程约束
- 注入所有 handlerTask/Toolchain/Mail),因为任何 handler 都可能创建 Issue/PR
- ⚠️ L1 文件在各 Agent workspace`~/.openclaw/workspace-*/TOOLS.md`),不在仓库管理。Agent workspace 变更不通过 PR
### 26.4 Label 迁移策略
旧标签(bug/feature/improvement/security/risk:high/priority:high)已由新体系替代:
- **旧标签保留不动**(不删除),避免历史 Issue 丢失标签信息
- **新 Issue/PR 使用新标签**type/* + priority/*
- 当前不做批量迁移。如有需要可后续通过 Gitea API 批量替换
### 26.5 与其他章节的关系
| 章节 | 关系 |
|------|------|
| §4.2 Issue 标签体系 | §26.2.2 Label 设计在问题管理场景的具体应用(已随 PR #69 更新) |
| §4.5 标题规范 | §26.2.1 标题规范的执行层摘要(已随 PR #69 新增) |
| §5 CI/CD 管道 | CI 事件通过标题前缀 `[CI]` 做事件路由(见 §16 事件中枢) |
| §6 代码审查流程 | PR Template 检查清单约束审查前置条件 |
### 26.6 实现记录
| 文件 | 改动 |
|------|------|
| `prompt_composer.py` | 新增 `GiteaConventionSection`priority=55 |
| `task_handler.py` | `get_sections()` 注册 `GiteaConventionSection()` |
| `toolchain_handler.py` | `get_sections()` 注册 `GiteaConventionSection()` |
| `mail_handler.py` | `get_sections()` 注册 `GiteaConventionSection()` |
| `db.py` | `COMMENT_TYPES``action_report`(修 API 500 bug |
| `.gitea/ISSUE_TEMPLATE/` | bug.yml / feature.yml / test.yml |
| `.gitea/PULL_REQUEST_TEMPLATE.md` | PR 检查清单模板 |
| Gitea Labels | 3 仓库各创建 11 个 Labeltype × 7 + priority × 4 |
PR #692026-06-14 合并。
+1
View File
@@ -209,6 +209,7 @@ VALID_TRANSITIONS = {
COMMENT_TYPES = frozenset({
"general", "handoff", "observation", "review", "rebuttal",
"rebuttal_response", "debate_argument", "debate_rebuttal", "debate_judgment",
"action_report",
})
SEVERITY_LEVELS = frozenset({"blocking", "warning", "info", "audit"})
+2 -2
View File
@@ -9,7 +9,7 @@ import logging
from pathlib import Path
from src.daemon.base_task_handler import BaseTaskHandler, VerifyResult
from src.daemon.prompt_composer import PromptComposer, PromptContext, WikiGuideSection
from src.daemon.prompt_composer import PromptComposer, PromptContext, GiteaConventionSection, WikiGuideSection
from src.blackboard.db import get_connection
logger = logging.getLogger("moziplus-v2.handler.mail")
@@ -36,7 +36,7 @@ class MailHandler(BaseTaskHandler):
return composer.compose(context)
def get_sections(self) -> list:
return [MailContextSection(), MailApiSection(), MailConstraintsSection(), WikiGuideSection()]
return [MailContextSection(), MailApiSection(), MailConstraintsSection(), GiteaConventionSection(), WikiGuideSection()]
def verify_completion(self, task_id: str, db_path: Path) -> VerifyResult:
"""Mail 完成验证:区分 inform/request。
+23
View File
@@ -129,6 +129,29 @@ class PromptComposer:
return result
# ---------------------------------------------------------------------------
class GiteaConventionSection:
"""Gitea 标题规范引导段 — 提醒 Agent 创建 Issue/PR 时遵循标题格式。"""
name: str = "gitea_convention"
priority: int = 55 # CONSTRAINTS(50) 和 EXTENSION(60) 之间
CONVENTION_TEXT = (
"## Gitea 标题规范\n"
"创建 Issue/PR 时,标题**必须**包含项目代号前缀:\n"
"- Issue: `[代号] type: 简述`,如 `[moz] bug: Mail API 500`\n"
"- PR: `[代号] type(scope): 简述`,如 `[moz] impl(daemon): WikiGuideSection 注入`\n"
"代号:moz=moziplus_v2, quant=quant_live, vnpy=vnpy\n"
"type: bug/feat/impl/fix/docs/test/ci/refactor/chore"
)
def render(self, context: "PromptContext") -> str:
return self.CONVENTION_TEXT
def should_include(self, context: "PromptContext") -> bool:
return True
# ---------------------------------------------------------------------------
# WikiGuideSection — 知识查询引导段
# ---------------------------------------------------------------------------
+3 -2
View File
@@ -10,7 +10,7 @@ from pathlib import Path
from typing import Dict, Optional
from src.daemon.base_task_handler import BaseTaskHandler, VerifyResult
from src.daemon.prompt_composer import PromptComposer, PromptContext, WikiGuideSection
from src.daemon.prompt_composer import PromptComposer, PromptContext, GiteaConventionSection, WikiGuideSection
from src.blackboard.db import get_connection
logger = logging.getLogger("moziplus-v2.handler")
@@ -306,13 +306,14 @@ class TaskHandler(BaseTaskHandler):
return True
def get_sections(self) -> list:
"""返回 5 个 PromptSection 实例。"""
"""返回 PromptSection 实例。"""
return [
TaskContextSection(),
PriorOutputsSection(),
RoleSkillSection(),
TaskApiSection(),
TaskConstraintsSection(),
GiteaConventionSection(),
WikiGuideSection(),
]
+3 -2
View File
@@ -13,7 +13,7 @@ from pathlib import Path
from typing import Dict, List
from src.daemon.base_task_handler import BaseTaskHandler, VerifyResult
from src.daemon.prompt_composer import PromptComposer, PromptContext, WikiGuideSection
from src.daemon.prompt_composer import PromptComposer, PromptContext, GiteaConventionSection, WikiGuideSection
from src.daemon.toolchain_templates import render_template, _TEMPLATE_MAP
from src.blackboard.db import get_connection
@@ -221,11 +221,12 @@ class ToolchainHandler(BaseTaskHandler):
return self._auto_mark_working(task_id, db_path)
def get_sections(self) -> list:
"""返回 3 个 Toolchain PromptSection 实例"""
"""返回 Toolchain PromptSection 实例"""
return [
ToolchainContextSection(),
ToolchainApiSection(),
ToolchainConstraintsSection(),
GiteaConventionSection(),
WikiGuideSection(),
]