Compare commits

...
20 Commits
Author SHA1 Message Date
QiuSW 947a06846e docs: add DevHarness upgrade baseline guidance (#16) 2026-08-16 19:51:20 +08:00
QiuSW fe99ca52e3 docs: add project baseline examples (#15) 2026-08-16 19:39:08 +08:00
QiuSW a959fc385d docs: evaluate open-source project baselines (#15) 2026-08-16 19:30:22 +08:00
QiuSW d1f55f9df3 feat: export task archives on demand (#14) 2026-08-16 19:21:36 +08:00
QiuSW f23c2cf81f docs: record task #13 acceptance 2026-08-11 10:24:51 +08:00
QiuSW fb9229a74e docs: archive task #13 2026-08-10 19:08:33 +08:00
QiuSW 4e1db4558c docs: support multi-project delivery units (#13) 2026-08-10 19:05:07 +08:00
QiuSW 105328ee2e docs: record task #12 acceptance 2026-08-10 18:01:12 +08:00
QiuSW eba851561a docs: archive task #12 2026-08-10 15:04:43 +08:00
QiuSW 0271a3ebd7 docs: 新增已有项目接入指南 (#12) 2026-08-10 15:01:15 +08:00
QiuSW eb92fb3033 docs: 归档任务 #11 2026-08-10 14:29:06 +08:00
QiuSW 3474870499 docs: 建立最小交付文档体系 (#11) 2026-08-10 14:25:34 +08:00
QiuSW 4e9f2e1380 docs: 记录任务 #8 #9 #10 验收完成 2026-08-10 12:01:19 +08:00
QiuSW e9c9fb415b docs: 归档任务 #10 2026-08-10 11:56:39 +08:00
QiuSW 353bd97212 feat: 增加需求记录规则 (#10) 2026-08-10 11:53:38 +08:00
QiuSW 48404070d0 docs: 归档任务 #9 2026-08-10 01:13:24 +08:00
QiuSW 10e82d61e6 feat: 定义 Agent 快捷指令 (#9) 2026-08-10 01:09:13 +08:00
QiuSW f652cbd46c docs: 归档任务 #8 2026-08-10 00:36:37 +08:00
QiuSW a59e3b5374 feat: 增加最小工单依赖规则 (#8) 2026-08-10 00:30:31 +08:00
QiuSW d1136c2bc5 docs: 记录任务 #5 #6 #7 验收完成 2026-08-08 11:27:19 +08:00
28 changed files with 1834 additions and 130 deletions
+40
View File
@@ -5,6 +5,29 @@
- 所属 MVP / 版本:# - 所属 MVP / 版本:#
- 阶段: - 阶段:
## 依赖与并行
- 前置工单:无 / #编号
- 是否允许与前置工单并行:是 / 否
- 原因:
## 子项目影响
<!-- 单应用项目填写唯一交付单元;多应用单仓库必须明确单端、跨端和共享契约影响。 -->
- 仅影响的子项目 / 交付单元:
- 是否跨子项目:是 / 否
- 是否修改共享接口或契约:是 / 否;唯一事实来源:
- 各子项目需要执行的验证:
## 原始需求
- 来源:用户对话 / Gitea / 其他
- 提出时间:
- 关键原话或脱敏摘要:
<!-- 只保留表达用户目的、场景和限制所需的内容;不要复制完整聊天、内部推理或敏感信息。 -->
## 要解决什么 ## 要解决什么
<!-- 描述现状和目标。缺陷需要写清复现步骤、实际结果和期望结果。 --> <!-- 描述现状和目标。缺陷需要写清复现步骤、实际结果和期望结果。 -->
@@ -22,6 +45,14 @@
- <!-- 填写 --> - <!-- 填写 -->
## 需求变化记录
<!-- 只记录影响范围、接口、数据、风险或验收的变化;没有变化时填写“无”。 -->
| 日期 | 变化内容 | 原因 | 用户确认 |
|---|---|---|---|
| | | | 是 / 否 |
## 文档影响 ## 文档影响
<!-- 至少选择一项;不影响长期文档时必须写明原因。 --> <!-- 至少选择一项;不影响长期文档时必须写明原因。 -->
@@ -33,6 +64,15 @@
- [ ] 更新常见修改或故障排查 - [ ] 更新常见修改或故障排查
- [ ] 更新其他 Wiki 页面: - [ ] 更新其他 Wiki 页面:
## 交付文档影响
<!-- 至少选择一项;面向用户、客户或其他岗位的行为、配置、部署、接口或支持方式变化时,必须列出受众和页面。 -->
- [ ] 无交付文档影响,原因:
- [ ] 更新已有交付文档,受众与页面:
- [ ] 新增交付文档,受众与页面:
- [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式:
## 验收标准 ## 验收标准
- [ ] <!-- 填写 --> - [ ] <!-- 填写 -->
+38 -9
View File
@@ -1,6 +1,6 @@
# Agent 开发规则 # Agent 开发规则
本仓库采用 DevHarness 工作流:Gitea 工单是任务过程的事实来源,Gitea Wiki 是长期开发文档和任务归档的事实来源,Git 是代码与版本绑定资料的变更记录,`docs/` 只保存 Wiki 的只读镜像。人负责确认方案与验收,Agent 负责检查、实现、测试和留下证据。 本仓库采用 DevHarness 工作流:Gitea 工单是任务过程的事实来源,Gitea Wiki 是长期开发文档和任务归档的事实来源,Git 是代码与版本绑定资料的变更记录。`docs/` 默认保存核心 Wiki 的只读镜像,`docs/task/` 只保存人工按需导出的任务归档快照。人负责确认方案与验收,Agent 负责检查、实现、测试和留下证据。
开始工作前先阅读 [项目档案](docs/00-project-profile.md) 和任务涉及目录中的 `AGENTS.md`。目录越深的规则越具体,但不得削弱上级安全规则。 开始工作前先阅读 [项目档案](docs/00-project-profile.md) 和任务涉及目录中的 `AGENTS.md`。目录越深的规则越具体,但不得削弱上级安全规则。
@@ -33,13 +33,41 @@
2. 给出目标、非目标、方案、影响范围、风险、回退方式、验证方法和文档影响。 2. 给出目标、非目标、方案、影响范围、风险、回退方式、验证方法和文档影响。
3. 方案没有得到用户明确确认前,只做只读诊断和方案整理,不实施正式代码。 3. 方案没有得到用户明确确认前,只做只读诊断和方案整理,不实施正式代码。
4. 方案确认后,先建立单元任务工单,再修改代码。 4. 方案确认后,先建立单元任务工单,再修改代码。
5. 开始实施前检查分支和工作区,明确哪些现有改动不属于本任务。 5. 建立新工单不要求其他工单已经完成;开始实施前检查工单声明的前置工单。真实依赖未满足时保持“待实施”,允许并行时必须写明原因。
6. 严格按工单范围实现;新发现的问题先记录,不顺手混入当前任务。 6. 开始实施前检查分支和工作区,明确哪些现有改动不属于本任务。
7. 执行与风险相称的测试,把关键结果和未验证部分更新到工单。 7. 严格按工单范围实现;新发现的问题先记录,不顺手混入当前任务。
8. 长期文档必须先修改 Wiki、读取确认,再运行 `python dev_scripts/sync_wiki_docs.py` 导出本地镜像;不得直接编辑 `docs/` 后反向覆盖 Wiki。 8. 执行与风险相称的测试,把关键结果和未验证部分更新到工单。实施过程中出现计划外、当前无法解除的问题时才标记“阻塞”。
9. 长期核心文档必须先修改 Wiki、读取确认,再运行 `python dev_scripts/sync_wiki_docs.py` 导出本地镜像;任务归档默认只更新 Wiki,不自动导出本地。不得直接编辑镜像后反向覆盖 Wiki。
Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明确授权,不得默认绕过建单。 Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明确授权,不得默认绕过建单。
### 自然语言快捷指令
快捷指令只是本工作流的自然语言别名,不得绕过方案确认、前置依赖、安全规则、工单范围、Wiki 主源、必要验证或人工验收:
- `只分析`:只读检查并给出方案;不建单、不修改,停在等待确认。
- `建工单`:根据已确认方案创建单元任务工单;建单后停止,不修改代码。
- `执行工单 #N`:检查工单和依赖,实施、测试、提交、归档、推送并回写证据;停在“待验收”。
- `建工单并做`:依次建单和执行,`建工单,做`、`建工单,做` 含义相同;停在“待验收”。
- `继续工单 #N`:核对工单、Git 和 Wiki 证据,从首个未完成步骤继续,不重复仍然有效的检查。
- `检查工单 #N`:只读核对范围、验收、测试和证据并输出报告;不自动修复。
- `同步文档`:读取 Wiki、导出核心 `docs/` 并检查一致性,不处理任务归档;不修改 Wiki、不自动提交。
- `导出任务归档`:人工触发 `python dev_scripts/export_task_archives.py`,只导出新增或 revision 已变化的任务归档;不删除本地文件、不自动提交。
- `导出全部任务归档`:人工触发 `python dev_scripts/export_task_archives.py --all`,读取并导出全部线上任务归档;不删除本地文件、不自动提交。
- `#N 验收通过`:仅在用户明确验收后,更新 Wiki 归档、同步必要的核心文档、推送、同步父工单并关闭任务;不自动导出任务归档。
方案未确认或前置依赖未满足时,实施类指令必须停在对应门禁;除 `#N 验收通过` 外,快捷指令不得关闭待验收工单。任务归档导出必须由用户明确提出,其他指令不得隐式执行。Gitea 工单不导出全文,`docs/task/` 只是可能不完整的 Wiki 任务归档快照。详细语义见 [开发工作流](docs/01-workflow.md)。
### 需求记录与流转
- 创建单元任务工单时,记录原始需求的来源、提出时间,以及能表达用户目的、场景和限制的少量关键原话或脱敏摘要;不得臆造用户原话。
- 工单中的目标、非目标、已确认方案、验收标准和文档影响构成确认后的正式任务需求。
- 影响范围、接口、数据、风险或验收的需求变化必须记录日期、内容、原因和用户确认;会改变已确认结果时先更新工单并等待再次确认。
- 不复制完整聊天,不保存 Agent 内部推理,不写入密码、令牌、个人数据或生产数据;包含敏感信息的原话必须删除敏感部分或改写为脱敏摘要。
- 长期有效的产品需求、业务规则和系统边界进入对应 Wiki 主题页并导出核心 `docs/`;完成结果进入 Wiki 任务归档,仅在用户明确要求时导出 `docs/task/`。Gitea 工单全文不导出到仓库。
详细记录边界见 [开发工作流](docs/01-workflow.md) 与 [业务规则和术语](docs/03-business-rules-and-glossary.md)。
### 效率与范围控制 ### 效率与范围控制
本节只用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、Wiki 同步、Git 提交和验收归档要求。 本节只用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、Wiki 同步、Git 提交和验收归档要求。
@@ -100,8 +128,8 @@ Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明
1. 逐项完成验收、测试和实现提交,并把最终方案、差异、结果、提交及遗留问题写回工单。 1. 逐项完成验收、测试和实现提交,并把最终方案、差异、结果、提交及遗留问题写回工单。
2. 工单保持“待验收”,用户没有明确验收通过前不得关闭。 2. 工单保持“待验收”,用户没有明确验收通过前不得关闭。
3. 运行 `python dev_scripts/new_task_archive.py <编号> "<短标题>"`,先创建 Wiki 归档,再登记并导出本地镜像。 3. 运行 `python dev_scripts/new_task_archive.py <编号> "<短标题>"`,只创建 Wiki 任务归档,不登记或导出本地镜像。
4. 读取确认 Wiki,运行 `python dev_scripts/sync_wiki_docs.py --check`;归档镜像单独提交,并把页面、revision、路径和提交哈希写回工单。 4. 读取确认 Wiki,运行 `python dev_scripts/sync_wiki_docs.py --check` 检查核心镜像,并把任务归档页面、revision 和提交哈希写回工单。只有用户明确提出时才增量或全量导出任务归档。
5. 用户验收通过后关闭单元工单,并同步更新 MVP 和 Epic。 5. 用户验收通过后关闭单元工单,并同步更新 MVP 和 Epic。
MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才能关闭 MVP。Epic 的全部范围完成后才能关闭 Epic。 MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才能关闭 MVP。Epic 的全部范围完成后才能关闭 Epic。
@@ -140,8 +168,9 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才
<!-- 在项目初始化时填写不可违反的技术、安全和业务约束。复杂子项目请在其目录中增加 AGENTS.md。 --> <!-- 在项目初始化时填写不可违反的技术、安全和业务约束。复杂子项目请在其目录中增加 AGENTS.md。 -->
- 长期开发文档以 Gitea Wiki 为事实来源,`docs/` 是显式映射生成的只读镜像。 - 长期开发文档以 Gitea Wiki 为事实来源,`docs/` 默认保存显式映射生成的核心只读镜像;`docs/task/` 是人工按需快照,可能不完整或不是最新状态。
- Wiki 与镜像的固定顺序是:修改 Wiki → 读取确认 → 导出 `docs` → 校验差异 → 提交镜像。 - 核心 Wiki 与镜像的固定顺序是:修改 Wiki → 读取确认 → 导出核心 `docs` → 校验差异 → 提交镜像。
- 任务归档默认只保存在 Wiki;`导出任务归档` 或 `导出全部任务归档` 必须由用户明确提出,且不得自动传播删除或重命名。
- 同步配置只允许写入 `docs/` 下的 Markdown;发现镜像有未提交修改时必须停止。 - 同步配置只允许写入 `docs/` 下的 Markdown;发现镜像有未提交修改时必须停止。
- Gitea 凭据只通过进程环境或 MCP 安全配置提供,不得写入仓库。 - Gitea 凭据只通过进程环境或 MCP 安全配置提供,不得写入仓库。
- `dev_scripts/` 只存放 DevHarness 自身工具;业务项目的通用脚本必须使用独立目录,不得混放。 - `dev_scripts/` 只存放 DevHarness 自身工具;业务项目的通用脚本必须使用独立目录,不得混放。
+7 -6
View File
@@ -14,7 +14,7 @@ DevHarness 是一个以 Gitea 工单管理任务过程、以 Gitea Wiki 管理
-> Agent 实现并测试 -> Agent 实现并测试
-> 提交代码并更新工单 -> 提交代码并更新工单
-> 人工验收 -> 人工验收
-> 先归档 Wiki,再导出 docs/task 镜像 -> 归档 Wiki;任务快照仅在人工提出时导出
-> 关闭工单并更新父工单 -> 关闭工单并更新父工单
``` ```
@@ -44,17 +44,18 @@ docs/00-project-profile.md Wiki 项目档案的只读镜像
docs/01-workflow.md Wiki 开发工作流的只读镜像 docs/01-workflow.md Wiki 开发工作流的只读镜像
docs/02-07*.md 代码地图、业务、验证、修改、排错和初始化镜像 docs/02-07*.md 代码地图、业务、验证、修改、排错和初始化镜像
docs/templates/task-archive.md Wiki 任务归档模板的只读镜像 docs/templates/task-archive.md Wiki 任务归档模板的只读镜像
docs/task/ Wiki 任务归档页的只读镜像 docs/task/ 人工按需导出的 Wiki 任务归档快照
wiki-docs.json Wiki 页面到本地镜像的显式映射 wiki-docs.json 核心 Wiki 页面到本地镜像的显式映射
dev_scripts/check_harness.py 模板和归档的最小自检 dev_scripts/check_harness.py 模板和归档的最小自检
dev_scripts/sync_wiki_docs.py 单向导出或检查 Wiki 镜像 dev_scripts/sync_wiki_docs.py 单向导出或检查 Wiki 镜像
dev_scripts/new_task_archive.py 先创建 Wiki 任务归档,再导出镜像 dev_scripts/new_task_archive.py 只创建 Wiki 任务归档
dev_scripts/export_task_archives.py 人工增量或全量导出任务归档
``` ```
## 设计原则 ## 设计原则
- 人决定目标、范围和验收结果,Agent 负责检查、实现和验证。 - 人决定目标、范围和验收结果,Agent 负责检查、实现和验证。
- 工单记录实施过程,Wiki 保存长期有效的最终事实,`docs/` 只保存可审查的镜像。 - 工单记录实施过程,Wiki 保存长期有效的最终事实,`docs/` 默认保存核心镜像;任务归档快照按需导出。
- 一个单元工单只解决一个可独立测试和回退的问题。 - 一个单元工单只解决一个可独立测试和回退的问题。
- 实现提交与归档提交分开,便于审查与追溯。 - 实现提交与必要的核心文档镜像提交分开,便于审查与追溯。
- 凭据、个人数据和生产数据不得进入代码、工单或归档。 - 凭据、个人数据和生产数据不得进入代码、工单或归档。
+101 -2
View File
@@ -24,6 +24,13 @@ CORE_PAGE_PATHS = {
"New-Project-Documentation-Setup": ( "New-Project-Documentation-Setup": (
"docs/07-new-project-documentation-setup.md" "docs/07-new-project-documentation-setup.md"
), ),
"Existing-Project-Adoption-Guide": (
"docs/08-existing-project-adoption.md"
),
"Delivery-Documentation-Guide": "docs/delivery/README.md",
"Audience-Document-Template": (
"docs/delivery/audience-document-template.md"
),
"Task-Archive-Template": "docs/templates/task-archive.md", "Task-Archive-Template": "docs/templates/task-archive.md",
} }
CORE_DOCUMENT_REQUIREMENTS = { CORE_DOCUMENT_REQUIREMENTS = {
@@ -35,6 +42,8 @@ CORE_DOCUMENT_REQUIREMENTS = {
), ),
"docs/00-project-profile.md": ( "docs/00-project-profile.md": (
"## 基本信息", "## 基本信息",
"## DevHarness 来源与基线",
"## 子项目与交付单元",
"## 技术栈与运行环境", "## 技术栈与运行环境",
"## 阅读入口", "## 阅读入口",
"## 常用命令", "## 常用命令",
@@ -43,7 +52,9 @@ CORE_DOCUMENT_REQUIREMENTS = {
"docs/01-workflow.md": ( "docs/01-workflow.md": (
"## 面向初级维护者的修改边界", "## 面向初级维护者的修改边界",
"## 每个任务的文档影响", "## 每个任务的文档影响",
"## 需求记录与流转",
"## 稳定文档与任务归档", "## 稳定文档与任务归档",
"## 自然语言快捷指令",
"## 效率与范围控制", "## 效率与范围控制",
"### 严格控制范围", "### 严格控制范围",
"### 渐进执行和修复", "### 渐进执行和修复",
@@ -80,8 +91,50 @@ CORE_DOCUMENT_REQUIREMENTS = {
), ),
"docs/07-new-project-documentation-setup.md": ( "docs/07-new-project-documentation-setup.md": (
"## 初始化顺序", "## 初始化顺序",
"### 2. 选择建设基线",
"#### 判断案例",
"### 3. 识别子项目与交付单元",
"### 7. 确定交付对象和文档",
"## 完成标准", "## 完成标准",
), ),
"docs/08-existing-project-adoption.md": (
"## 与新项目初始化的区别",
"## 接入前只读盘点",
"## 已有内容保护原则",
"## 多应用单仓库判断",
"### 适合继续单仓库",
"### 可以考虑拆仓",
"### 保持单仓库时的最小规则",
"## 增量接入顺序",
"## 后续升级",
"### 升级步骤",
"### 可复制升级指令",
"## 冲突处理和停止条件",
"## 可复制 Agent 指令",
"### 只分析",
"### 方案确认后实施",
"## 最小验收清单",
"## 回退原则",
),
"docs/delivery/README.md": (
"## 什么时候需要交付文档",
"## 受众与文档选择",
"## 内部文档与交付文档边界",
"## 编写和维护流程",
"## 最小验收清单",
),
"docs/delivery/audience-document-template.md": (
"## 文档信息",
"## 目的与适用范围",
"## 前置条件",
"## 操作步骤",
"## 常见错误与恢复",
"## 安全与权限",
"## 已知限制",
"## 支持与升级处理",
"## 版本记录",
"## 交付前检查",
),
} }
REQUIRED_FILES = ( REQUIRED_FILES = (
"AGENTS.md", "AGENTS.md",
@@ -94,6 +147,7 @@ REQUIRED_FILES = (
"wiki-docs.json", "wiki-docs.json",
"dev_scripts/wiki_docs.py", "dev_scripts/wiki_docs.py",
"dev_scripts/sync_wiki_docs.py", "dev_scripts/sync_wiki_docs.py",
"dev_scripts/export_task_archives.py",
".gitea/issue_template/epic.md", ".gitea/issue_template/epic.md",
".gitea/issue_template/mvp.md", ".gitea/issue_template/mvp.md",
".gitea/issue_template/task.md", ".gitea/issue_template/task.md",
@@ -129,6 +183,15 @@ def check_archives(errors: list[str]) -> None:
if not re.match(r"^\d+-.+\.md$", path.name): if not re.match(r"^\d+-.+\.md$", path.name):
errors.append(f"归档文件名不符合 <编号>-<标题>.md:{path.name}") errors.append(f"归档文件名不符合 <编号>-<标题>.md:{path.name}")
content = path.read_text(encoding="utf-8") content = path.read_text(encoding="utf-8")
try:
metadata, _ = parse_mirror(content)
except WikiDocsError as exc:
errors.append(f"{path.name} 的任务镜像无效:{exc}")
continue
if re.fullmatch(r"Task-\d+-.+", metadata.get("wiki_page", "")) is None:
errors.append(f"{path.name} 的 wiki_page 不是任务归档页面")
if re.fullmatch(r"[0-9a-f]{40,64}", metadata.get("wiki_revision", "")) is None:
errors.append(f"{path.name} 的 wiki_revision 无效")
for heading in ARCHIVE_HEADINGS: for heading in ARCHIVE_HEADINGS:
if heading not in content: if heading not in content:
errors.append(f"{path.name} 缺少章节:{heading}") errors.append(f"{path.name} 缺少章节:{heading}")
@@ -161,11 +224,31 @@ def check_task_template(errors: list[str], root: Path = ROOT) -> None:
return return
content = path.read_text(encoding="utf-8") content = path.read_text(encoding="utf-8")
required = ( required = (
"## 依赖与并行",
"- 前置工单:无 / #编号",
"- 是否允许与前置工单并行:是 / 否",
"- 原因:",
"## 子项目影响",
"- 仅影响的子项目 / 交付单元:",
"- 是否跨子项目:是 / 否",
"- 是否修改共享接口或契约:是 / 否;唯一事实来源:",
"- 各子项目需要执行的验证:",
"## 原始需求",
"- 来源:用户对话 / Gitea / 其他",
"- 提出时间:",
"- 关键原话或脱敏摘要:",
"## 需求变化记录",
"| 日期 | 变化内容 | 原因 | 用户确认 |",
"## 文档影响", "## 文档影响",
"- [ ] 不影响长期文档,原因:", "- [ ] 不影响长期文档,原因:",
"- [ ] 更新架构与代码地图", "- [ ] 更新架构与代码地图",
"- [ ] 更新业务规则与术语", "- [ ] 更新业务规则与术语",
"- [ ] 更新常见修改或故障排查", "- [ ] 更新常见修改或故障排查",
"## 交付文档影响",
"- [ ] 无交付文档影响,原因:",
"- [ ] 更新已有交付文档,受众与页面:",
"- [ ] 新增交付文档,受众与页面:",
"- [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式:",
) )
for section in missing_sections(content, required): for section in missing_sections(content, required):
errors.append(f"单元任务模板缺少:{section}") errors.append(f"单元任务模板缺少:{section}")
@@ -185,8 +268,23 @@ def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None:
"单元任务是唯一正式实施单位", "单元任务是唯一正式实施单位",
"高风险修改必须停止", "高风险修改必须停止",
"用户没有明确验收通过前不得关闭", "用户没有明确验收通过前不得关闭",
"长期文档必须先修改 Wiki", "长期核心文档必须先修改 Wiki",
"提交只包含当前工单相关文件", "提交只包含当前工单相关文件",
"### 自然语言快捷指令",
"`只分析`",
"`建工单`",
"`执行工单 #N`",
"`建工单并做`",
"`继续工单 #N`",
"`检查工单 #N`",
"`同步文档`",
"`导出任务归档`",
"`导出全部任务归档`",
"`#N 验收通过`",
"### 需求记录与流转",
"不得臆造用户原话",
"不复制完整聊天",
"Gitea 工单全文不导出到仓库",
) )
for section in missing_sections(content, required): for section in missing_sections(content, required):
errors.append(f"AGENTS.md 缺少:{section}") errors.append(f"AGENTS.md 缺少:{section}")
@@ -229,7 +327,7 @@ def core_mapping_errors(configured_mappings: dict[str, str]) -> list[str]:
def check_wiki_mirrors(errors: list[str]) -> None: def check_wiki_mirrors(errors: list[str]) -> None:
"""检查每份本地文档都有显式映射和可追踪的镜像头。""" """检查核心映射与镜像头;任务快照由 check_archives 单独检查。"""
try: try:
config = load_config() config = load_config()
@@ -243,6 +341,7 @@ def check_wiki_mirrors(errors: list[str]) -> None:
mapped_paths = {mapping.path for mapping in config.mappings} mapped_paths = {mapping.path for mapping in config.mappings}
actual_paths = { actual_paths = {
path.relative_to(ROOT).as_posix() for path in (ROOT / "docs").rglob("*.md") path.relative_to(ROOT).as_posix() for path in (ROOT / "docs").rglob("*.md")
if path.parent != ROOT / "docs" / "task"
} }
for path in sorted(actual_paths - mapped_paths): for path in sorted(actual_paths - mapped_paths):
errors.append(f"docs 中存在未登记的 Wiki 镜像:{path}") errors.append(f"docs 中存在未登记的 Wiki 镜像:{path}")
+131
View File
@@ -0,0 +1,131 @@
"""把 Gitea Wiki 任务归档人工按需导出到 docs/task。"""
from __future__ import annotations
import argparse
import re
from pathlib import Path
from typing import Any
from new_task_archive import safe_title
from wiki_docs import (
DEFAULT_CONFIG,
ROOT,
WikiClient,
WikiDocsError,
dirty_paths,
load_config,
parse_mirror,
write_mirror,
)
TASK_PAGE_PATTERN = re.compile(r"^Task-(?P<number>\d+)-(?P<title>.+)$")
def task_revision(metadata: dict[str, Any], page_name: str) -> str:
last_commit = metadata.get("last_commit")
revision = last_commit.get("sha") if isinstance(last_commit, dict) else None
if not isinstance(revision, str) or not revision:
raise WikiDocsError(f"Wiki 页面缺少 revision:{page_name}")
return revision
def existing_task_mirrors(root: Path = ROOT) -> dict[str, Path]:
"""按镜像头匹配已有文件,兼容历史自定义文件名。"""
mirrors: dict[str, Path] = {}
task_dir = root / "docs" / "task"
if not task_dir.is_dir():
return mirrors
for path in task_dir.glob("*.md"):
try:
metadata, _ = parse_mirror(path.read_text(encoding="utf-8"))
except (OSError, UnicodeDecodeError, WikiDocsError) as exc:
raise WikiDocsError(f"已有任务镜像无效 {path.name}:{exc}") from exc
page_name = metadata.get("wiki_page", "")
if not TASK_PAGE_PATTERN.fullmatch(page_name):
raise WikiDocsError(f"已有任务镜像页面名无效 {path.name}:{page_name}")
if page_name in mirrors:
raise WikiDocsError(f"任务页面存在重复本地镜像:{page_name}")
mirrors[page_name] = path
return mirrors
def task_target(page_name: str, root: Path = ROOT) -> Path:
match = TASK_PAGE_PATTERN.fullmatch(page_name)
if match is None:
raise WikiDocsError(f"不是任务归档页面:{page_name}")
title = safe_title(match.group("title"))
if not title:
raise WikiDocsError(f"任务归档标题无效:{page_name}")
return root / "docs" / "task" / f"{match.group('number')}-{title}.md"
def export_task_archives(
client: WikiClient, *, export_all: bool = False, root: Path = ROOT
) -> list[str]:
"""增量或全量读取任务归档;绝不删除本地文件。"""
dirty = dirty_paths(["docs/task"], root)
if dirty:
raise WikiDocsError(
"本地任务镜像存在未提交改动,已停止以防覆盖:\n" + "\n".join(dirty)
)
existing = existing_task_mirrors(root)
pages = []
for metadata in client.list_pages():
title = metadata.get("title")
if isinstance(title, str) and TASK_PAGE_PATTERN.fullmatch(title):
pages.append((int(title.split("-", 2)[1]), title, metadata))
pages.sort(key=lambda item: (item[0], item[1]))
messages: list[str] = []
targets: set[Path] = set()
for _, page_name, metadata in pages:
target = existing.get(page_name, task_target(page_name, root))
if target in targets:
raise WikiDocsError(f"多个任务页面映射到同一本地路径:{target.name}")
targets.add(target)
revision = task_revision(metadata, page_name)
if not export_all and target.is_file():
local_metadata, _ = parse_mirror(target.read_text(encoding="utf-8"))
if (
local_metadata.get("wiki_page") == page_name
and local_metadata.get("wiki_revision") == revision
):
messages.append(f"跳过:{target.relative_to(root)} <- {page_name}@{revision[:12]}")
continue
page = client.get_page_from_metadata(metadata, page_name)
changed = write_mirror(target, page)
action = "已导出" if changed else "无变化"
messages.append(f"{action}:{target.relative_to(root)} <- {page_name}@{revision[:12]}")
return messages
def main() -> int:
parser = argparse.ArgumentParser(description="人工按需导出 Gitea Wiki 任务归档")
parser.add_argument(
"--all", action="store_true", help="全量读取全部线上任务归档;默认按 revision 增量"
)
parser.add_argument(
"--config", default=str(DEFAULT_CONFIG), help="核心 Wiki 映射配置"
)
args = parser.parse_args()
try:
config = load_config(Path(args.config).resolve())
messages = export_task_archives(
WikiClient(config), export_all=args.all
)
except WikiDocsError as exc:
print(f"错误:{exc}")
return 1
for message in messages:
print(message)
print("任务归档全量导出完成" if args.all else "任务归档增量导出完成")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+5 -19
View File
@@ -1,4 +1,4 @@
"""先在 Gitea Wiki 创建任务归档,再登记并导出本地镜像。""" """只在 Gitea Wiki 创建任务归档;本地镜像由人工按需导出。"""
from __future__ import annotations from __future__ import annotations
@@ -9,12 +9,9 @@ from pathlib import Path
from wiki_docs import ( from wiki_docs import (
DEFAULT_CONFIG, DEFAULT_CONFIG,
Mapping,
WikiClient, WikiClient,
WikiDocsError, WikiDocsError,
append_mapping,
load_config, load_config,
sync_all,
) )
@@ -43,7 +40,7 @@ def build_archive(
def main() -> int: def main() -> int:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="在 Gitea Wiki 创建任务归档并导出 docs/task 镜像" description="在 Gitea Wiki 创建任务归档,不自动导出本地镜像"
) )
parser.add_argument("issue_number", help="Gitea 工单号,例如 123") parser.add_argument("issue_number", help="Gitea 工单号,例如 123")
parser.add_argument("title", help="简短任务标题") parser.add_argument("title", help="简短任务标题")
@@ -61,15 +58,9 @@ def main() -> int:
try: try:
config = load_config(Path(args.config).resolve()) config = load_config(Path(args.config).resolve())
page_name = f"Task-{args.issue_number}-{short_title}" page_name = f"Task-{args.issue_number}-{short_title}"
local_path = f"docs/task/{args.issue_number}-{short_title}.md"
mapping = Mapping(page=page_name, path=local_path)
if any(
item.page == mapping.page or item.path == mapping.path
for item in config.mappings
):
raise WikiDocsError(f"任务归档已经登记:{page_name}")
client = WikiClient(config) client = WikiClient(config)
if any(item.get("title") == page_name for item in client.list_pages()):
raise WikiDocsError(f"任务归档已经存在:{page_name}")
template = client.get_page("Task-Archive-Template").text template = client.get_page("Task-Archive-Template").text
issue_url = ( issue_url = (
f"{config.gitea_url}/{config.owner}/{config.repository}/issues/" f"{config.gitea_url}/{config.owner}/{config.repository}/issues/"
@@ -83,17 +74,12 @@ def main() -> int:
content, content,
f"docs: 创建任务 #{args.issue_number} 归档草稿", f"docs: 创建任务 #{args.issue_number} 归档草稿",
) )
append_mapping(config, mapping)
updated_config = load_config(config.path)
messages = sync_all(updated_config, client)
except WikiDocsError as exc: except WikiDocsError as exc:
print(f"错误:{exc}") print(f"错误:{exc}")
return 1 return 1
print(f"已创建 Wiki:{page.html_url}") print(f"已创建 Wiki:{page.html_url}")
for message in messages: print("未导出本地任务归档;需要时运行 export_task_archives.py")
print(message)
print(f"已登记镜像:{local_path}")
return 0 return 0
+2 -2
View File
@@ -1,4 +1,4 @@
"""从 Gitea Wiki 单向导出本地 docs 镜像。""" """从 Gitea Wiki 单向导出配置中的核心 docs 镜像。"""
from __future__ import annotations from __future__ import annotations
@@ -9,7 +9,7 @@ from wiki_docs import DEFAULT_CONFIG, WikiClient, WikiDocsError, load_config, sy
def main() -> int: def main() -> int:
parser = argparse.ArgumentParser(description="从 Gitea Wiki 单向同步 docs 镜像") parser = argparse.ArgumentParser(description="从 Gitea Wiki 单向同步核心 docs 镜像")
parser.add_argument( parser.add_argument(
"--check", action="store_true", help="只检查 Wiki 与镜像是否一致,不写文件" "--check", action="store_true", help="只检查 Wiki 与镜像是否一致,不写文件"
) )
+34 -6
View File
@@ -210,6 +210,14 @@ class WikiClient:
raise WikiDocsError( raise WikiDocsError(
f"Wiki 页面不存在:{page_name};不会自动删除或重命名本地镜像" f"Wiki 页面不存在:{page_name};不会自动删除或重命名本地镜像"
) )
return self.get_page_from_metadata(metadata, page_name)
def get_page_from_metadata(
self, metadata: dict[str, Any], page_name: str | None = None
) -> WikiPage:
"""使用页面列表元数据读取正文,避免重复获取完整页面列表。"""
resolved_name = page_name or _required_string(metadata, "title")
sub_url = _required_string(metadata, "sub_url") sub_url = _required_string(metadata, "sub_url")
page = self._request( page = self._request(
"GET", "GET",
@@ -218,20 +226,22 @@ class WikiClient:
f"{quote(sub_url, safe='%')}", f"{quote(sub_url, safe='%')}",
) )
if not isinstance(page, dict): if not isinstance(page, dict):
raise WikiDocsError(f"Wiki 页面响应格式无效:{page_name}") raise WikiDocsError(f"Wiki 页面响应格式无效:{resolved_name}")
encoded_content = page.get("content_base64") encoded_content = page.get("content_base64")
if not isinstance(encoded_content, str): if not isinstance(encoded_content, str):
raise WikiDocsError(f"Wiki 页面没有 content_base64:{page_name}") raise WikiDocsError(f"Wiki 页面没有 content_base64:{resolved_name}")
try: try:
text = base64.b64decode(encoded_content, validate=True).decode("utf-8") text = base64.b64decode(encoded_content, validate=True).decode("utf-8")
except (ValueError, UnicodeDecodeError) as exc: except (ValueError, UnicodeDecodeError) as exc:
raise WikiDocsError(f"Wiki 页面不是有效的 UTF-8 Markdown:{page_name}") from exc raise WikiDocsError(
f"Wiki 页面不是有效的 UTF-8 Markdown:{resolved_name}"
) from exc
last_commit = page.get("last_commit") last_commit = page.get("last_commit")
revision = last_commit.get("sha") if isinstance(last_commit, dict) else None revision = last_commit.get("sha") if isinstance(last_commit, dict) else None
if not isinstance(revision, str) or not revision: if not isinstance(revision, str) or not revision:
raise WikiDocsError(f"Wiki 页面缺少 revision:{page_name}") raise WikiDocsError(f"Wiki 页面缺少 revision:{resolved_name}")
title = page.get("title") title = page.get("title")
resolved_title = title if isinstance(title, str) and title else page_name resolved_title = title if isinstance(title, str) and title else resolved_name
html_url = ( html_url = (
f"{self.config.gitea_url}/{quote(self.config.owner, safe='')}/" f"{self.config.gitea_url}/{quote(self.config.owner, safe='')}/"
f"{quote(self.config.repository, safe='')}/wiki/{quote(sub_url, safe='%')}" f"{quote(self.config.repository, safe='')}/wiki/{quote(sub_url, safe='%')}"
@@ -303,7 +313,14 @@ def render_mirror(page: WikiPage, existing: str | None = None) -> str:
def dirty_mirror_paths(config: Config, root: Path = ROOT) -> list[str]: def dirty_mirror_paths(config: Config, root: Path = ROOT) -> list[str]:
paths = [mapping.path for mapping in config.mappings] return dirty_paths([mapping.path for mapping in config.mappings], root)
def dirty_paths(paths: list[str], root: Path = ROOT) -> list[str]:
"""返回指定路径中已有、修改或未跟踪的工作区条目。"""
if not paths:
return []
result = subprocess.run( result = subprocess.run(
["git", "status", "--porcelain", "--", *paths], ["git", "status", "--porcelain", "--", *paths],
cwd=root, cwd=root,
@@ -329,6 +346,17 @@ def _write_atomic(path: Path, content: str) -> None:
raise raise
def write_mirror(path: Path, page: WikiPage) -> bool:
"""写入一份 Wiki 镜像;内容无变化时返回 False。"""
existing = path.read_text(encoding="utf-8") if path.is_file() else None
rendered = render_mirror(page, existing)
if existing == rendered:
return False
_write_atomic(path, rendered)
return True
def check_mirror(mapping: Mapping, page: WikiPage, path: Path) -> list[str]: def check_mirror(mapping: Mapping, page: WikiPage, path: Path) -> list[str]:
if not path.is_file(): if not path.is_file():
return [f"缺少镜像:{mapping.path}"] return [f"缺少镜像:{mapping.path}"]
+35 -8
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Project-Profile wiki_page: Project-Profile
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Project-Profile.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Project-Profile.-
wiki_revision: 2a81c9e4508cf6594f90d0b54368ec1f8a3be220 wiki_revision: 16456d6ed083197759d553b1033e3e5c8a6b8932
synchronized_at: 2026-08-08T01:16:47Z synchronized_at: 2026-08-16T11:49:52Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 项目档案 # 项目档案
@@ -23,6 +23,31 @@ synchronized_at: 2026-08-08T01:16:47Z
| 主要维护者 | `ila` | | 主要维护者 | `ila` |
| 文档适用范围 | 默认分支当前版本;具体镜像 revision 见每个本地文件头 | | 文档适用范围 | 默认分支当前版本;具体镜像 revision 见每个本地文件头 |
## DevHarness 来源与基线
每个采用 DevHarness 的业务项目都必须填写本节。它记录的是所采用的 DevHarness 上游版本,不是业务项目自己的提交。不得使用“最新版本”“当前 main”等动态描述代替完整提交哈希。
| 项目 | 内容 |
|---|---|
| DevHarness 来源仓库 | `http://ilaer.eicp.net:8418/opc/dev_harness` |
| 当前基线提交 | 本仓库是 DevHarness 上游源模板,不适用;复制到业务项目后必须替换为实际采用的完整提交哈希 |
| 最后接入或升级日期 | 2026-08-16 |
| 项目适配说明 | 本仓库维护源模板;业务项目填写保留、改写或未采用的 Harness 规则与工具 |
首次接入和后续升级都必须在目标项目工单中记录旧基线、新基线和差异分类。升级验收通过后,目标项目应把“当前基线提交”和日期更新为已采用的上游提交;未完成或已回退的升级不得更新基线。
## 子项目与交付单元
“子项目”是仓库中具有明确职责和规则边界的应用或模块;“交付单元”是能够独立构建、测试、版本化或发布的程序、服务、库或文档包。一个子项目可以对应一个交付单元,也可以包含多个交付单元。
| 子项目 / 交付单元 | 职责 | 技术栈 | 构建与测试 | 版本与发布方式 | 规则入口 | 共享边界 |
|---|---|---|---|---|---|---|
| DevHarness 模板 | 提供 Agent 开发流程、Wiki 镜像和结构检查 | Markdown、Python 3 标准库、Gitea 1.25 | `python dev_scripts/check_harness.py --strict`;`python -m unittest discover -s tests -v` | 跟随仓库 `main` 分支,不单独发布产品程序 | 根目录 `AGENTS.md` | Gitea 工单、Wiki、Git 和 `docs/` 的事实来源边界 |
单应用项目只填写一行。多应用单仓库必须逐个填写,并为技术栈、构建测试或安全规则不同的目录增加子目录 `AGENTS.md`。技术栈不同不等于必须拆分 Git 仓库;是否拆仓应根据团队、权限、发布周期、仓库效率、复用关系和共享接口稳定性判断。
跨子项目接口或契约必须指定唯一事实来源,并说明各交付单元的兼容范围和验证命令。不得在多个页面维护互不确认的“权威版本”。
## 技术栈与运行环境 ## 技术栈与运行环境
| 部分 | 技术 | 规则文件 | | 部分 | 技术 | 规则文件 |
@@ -51,9 +76,11 @@ synchronized_at: 2026-08-08T01:16:47Z
| 查看工作区 | `git status --short --branch` | 显示分支且没有无关修改 | | 查看工作区 | `git status --short --branch` | 显示分支且没有无关修改 |
| 检查模板结构 | `python dev_scripts/check_harness.py --strict` | 输出“DevHarness 检查通过” | | 检查模板结构 | `python dev_scripts/check_harness.py --strict` | 输出“DevHarness 检查通过” |
| 运行单元测试 | `python -m unittest discover -s tests -v` | 所有测试通过 | | 运行单元测试 | `python -m unittest discover -s tests -v` | 所有测试通过 |
| 导出 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py` | 映射页面写入 `docs/` | | 导出核心 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py` | 核心页面写入 `docs/`,不处理任务归档 |
| 检查 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py --check` | 输出镜像与 Wiki 一致 | | 检查核心 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py --check` | 输出核心镜像与 Wiki 一致 |
| 创建任务归档 | `python dev_scripts/new_task_archive.py 123 "修复登录超时"` | 先创建 Wiki 归档页,再登记并导出本地镜像 | | 创建任务归档 | `python dev_scripts/new_task_archive.py 123 "修复登录超时"` | 只创建 Wiki 归档页,不写入本地 |
| 增量导出任务归档 | `python dev_scripts/export_task_archives.py` | 只导出新增或 revision 已变化的任务归档 |
| 全量导出任务归档 | `python dev_scripts/export_task_archives.py --all` | 读取并导出全部线上任务归档 |
## 目录边界 ## 目录边界
@@ -61,13 +88,13 @@ synchronized_at: 2026-08-08T01:16:47Z
|---|---|---| |---|---|---|
| `.gitea/issue_template/` | Gitea 工单模板 | 凭据、任务最终归档 | | `.gitea/issue_template/` | Gitea 工单模板 | 凭据、任务最终归档 |
| `docs/` | Wiki 自动导出的只读镜像 | 人工直接维护的长期文档 | | `docs/` | Wiki 自动导出的只读镜像 | 人工直接维护的长期文档 |
| `docs/task/` | Wiki 任务归档页的只读镜像 | 讨论过程和临时方案 | | `docs/task/` | 人工按需导出的 Wiki 任务归档只读快照,可能不是完整历史 | 讨论过程和临时方案 |
| `dev_scripts/` | Harness 检查、Wiki 同步和归档工具 | 产品功能代码 | | `dev_scripts/` | Harness 检查、Wiki 同步和归档工具 | 产品功能代码 |
| `tests/` | Harness 工具自动化测试 | 生产数据 | | `tests/` | Harness 工具自动化测试 | 生产数据 |
## 环境、配置与凭据 ## 环境、配置与凭据
- Wiki 同步配置:仓库根目录 `wiki-docs.json`。 - 核心 Wiki 同步配置:仓库根目录 `wiki-docs.json`;任务归档不逐页登记,由按需导出工具动态发现。
- Gitea 地址可由配置提供,也可通过 `GITEA_URL` 覆盖。 - Gitea 地址可由配置提供,也可通过 `GITEA_URL` 覆盖。
- Gitea PAT 仅通过 `GITEA_TOKEN` 或 MCP 安全配置提供,不写入仓库。 - Gitea PAT 仅通过 `GITEA_TOKEN` 或 MCP 安全配置提供,不写入仓库。
- Token 至少需要读取仓库权限;创建或更新 Wiki 时还需要写仓库权限。 - Token 至少需要读取仓库权限;创建或更新 Wiki 时还需要写仓库权限。
@@ -78,7 +105,7 @@ synchronized_at: 2026-08-08T01:16:47Z
## 项目专用验收要求 ## 项目专用验收要求
- 长期文档必须先更新 Wiki,再导出本地镜像。 - 长期核心文档必须先更新 Wiki,再导出本地镜像;任务归档默认只保存在 Wiki,用户明确要求时才增量或全量导出。
- 镜像必须包含来源页面、revision 和同步时间。 - 镜像必须包含来源页面、revision 和同步时间。
- 页面删除、重命名和映射变更必须人工确认。 - 页面删除、重命名和映射变更必须人工确认。
- 新增核心文档时必须更新 Home、显式映射和 Harness 检查。 - 新增核心文档时必须更新 Home、显式映射和 Harness 检查。
+89 -13
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Development-Workflow wiki_page: Development-Workflow
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Development-Workflow.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Development-Workflow.-
wiki_revision: d00ceed847becc95439296f618bd8a461c0a4c0f wiki_revision: 3f50238b637bc2f896ceab6caa5ab8ab1ded2a4b
synchronized_at: 2026-08-08T01:36:38Z synchronized_at: 2026-08-16T11:18:52Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 开发工作流 # 开发工作流
@@ -37,6 +37,23 @@ synchronized_at: 2026-08-08T01:36:38Z
每个单元任务都应目标单一,能够独立测试、提交和回退。 每个单元任务都应目标单一,能够独立测试、提交和回退。
#### 依赖与并行
建立新工单不要求其他工单已经完成,也不按工单编号限制实施顺序。每个单元任务必须声明:
- 前置工单,没有时填写“无”;
- 是否允许与未完成的前置工单并行;
- 判断可以或不可以并行的原因。
开始修改前,Agent 检查工单声明的前置工单:
- 没有前置工单,或前置工单已经完成,可以进入“进行中”;
- 前置工单未完成且存在实际依赖时,不得开始实施,工单保持“待实施”;
- 与前置工单没有实施冲突、允许并行时,可以进入“进行中”,但必须在工单写明原因;
- 已经进入实施后出现计划外、当前无法解除的问题,才使用“阻塞”。
依赖不改变单元任务边界。依赖满足后,该任务仍须拥有独立的范围、提交、测试和回退方式。
### 3. 实施 ### 3. 实施
Agent 检查分支和工作区,只修改工单范围内的文件。发现新问题时先记录到工单;如果不影响当前验收,则另建工单,不扩大当前任务。 Agent 检查分支和工作区,只修改工单范围内的文件。发现新问题时先记录到工单;如果不影响当前验收,则另建工单,不扩大当前任务。
@@ -50,13 +67,13 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新
- Git 提交哈希; - Git 提交哈希;
- 相关 Wiki 页面及 revision。 - 相关 Wiki 页面及 revision。
长期文档遵循唯一顺序: 长期核心文档遵循唯一顺序:
```text ```text
修改 Wiki → 读取确认 → 导出 docs → 校验差异 → 提交镜像 修改 Wiki → 读取确认 → 导出核心 docs → 校验差异 → 提交镜像
``` ```
不得先编辑 `docs/` 再反向覆盖 Wiki。 任务归档默认只更新 Wiki,不自动导出到 `docs/task/`。不得先编辑本地镜像再反向覆盖 Wiki。
### 4. 待验收 ### 4. 待验收
@@ -64,21 +81,32 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新
### 5. 归档和关闭 ### 5. 归档和关闭
使用以下命令在 Wiki 创建任务归档页、登记显式映射并导出本地镜像: 使用以下命令只在 Wiki 创建任务归档页:
```powershell ```powershell
python dev_scripts/new_task_archive.py 123 "修复登录超时" python dev_scripts/new_task_archive.py 123 "修复登录超时"
``` ```
归档内容以 Wiki 页面为主源;本地 `docs/task/<编号>-<短标题>.md` 是镜像。归档镜像单独提交,再把 Wiki 页面、revision、镜像路径和提交哈希写回工单。用户明确验收通过后,关闭单元工单并勾选父工单中的任务。 归档内容以 Wiki 页面为事实来源。默认不修改 `wiki-docs.json`,也不写入 `docs/task/`。把 Wiki 页面、revision 和实现提交哈希写回工单;用户明确验收通过后,关闭单元工单并勾选父工单中的任务。
只有用户明确提出时才导出任务归档:
```powershell
python dev_scripts/export_task_archives.py # 增量:新增或 revision 变化
python dev_scripts/export_task_archives.py --all # 全量:读取全部线上任务归档
```
导出不得自动删除本地文件。`docs/task/` 只是人工按需生成的只读快照,可能不是完整或最新的任务历史。
## 文档同步规则 ## 文档同步规则
- 映射保存在 `wiki-docs.json`,每个 Wiki 页面对应唯一仓库路径。 - 核心页面映射保存在 `wiki-docs.json`;普通同步只处理这些核心长期文档。
- 同步脚本只实现 Wiki → `docs/`,不提供反向同步。 - 任务归档不逐页登记映射,由按需导出工具根据 `Task-<编号>-<标题>` 动态发现;已有镜像优先按镜像头匹配原页面。
- 所有同步和导出只实现 Wiki → `docs/`,不提供反向同步。
- 镜像头必须记录页面名、页面地址、revision 和同步时间。 - 镜像头必须记录页面名、页面地址、revision 和同步时间。
- 已跟踪镜像存在未提交改动时,同步必须停止;确认改动来源后再处理。 - 已跟踪镜像存在未提交改动时,同步必须停止;确认改动来源后再处理。
- `--check` 只检查,不写文件;页面缺失、revision 不一致或正文不一致均失败。 - 核心同步的 `--check` 只检查核心镜像,不要求线上任务归档全部存在于本地。
- 已经导出的任务镜像仍必须具有来源页面、revision 和同步时间,并通过 Harness 格式检查。
- 页面删除和重命名不会自动传播,必须先更新工单并人工确认映射变化。 - 页面删除和重命名不会自动传播,必须先更新工单并人工确认映射变化。
- Wiki 更新成功而导出失败时,在工单记录部分完成状态,不得把任务标为完成。 - Wiki 更新成功而导出失败时,在工单记录部分完成状态,不得把任务标为完成。
- 与具体代码版本强绑定的接口或迁移资料可直接随代码维护,但必须在 Wiki 提供入口或适用版本说明。 - 与具体代码版本强绑定的接口或迁移资料可直接随代码维护,但必须在 Wiki 提供入口或适用版本说明。
@@ -114,10 +142,32 @@ python dev_scripts/new_task_archive.py 123 "修复登录超时"
普通内部重构如果入口、行为、配置和验证方式均未改变,可以记录“不影响长期文档”及原因。 普通内部重构如果入口、行为、配置和验证方式均未改变,可以记录“不影响长期文档”及原因。
## 需求记录与流转
聊天用于分析和确认,不是正式需求的长期事实来源。创建单元任务工单时,Agent 应记录:
- 原始需求的来源和提出时间;
- 能表达用户目的、使用场景和限制的少量关键原话;
- 整理后的目标、非目标、确认方案、验收标准和文档影响;
- 实施期间影响范围、接口、数据、风险或验收的需求变化,以及变化原因和用户确认。
只摘录完成追踪所需的内容,不复制完整聊天,不保存 Agent 内部推理,不写入密码、令牌、个人数据或生产数据。包含敏感信息的原话必须删除敏感部分或改写为脱敏摘要。
需求按以下边界流转:
| 内容 | 事实来源 | 本地镜像 |
|---|---|---|
| 关键原始需求、确认后的单次任务需求 | Gitea 单元任务工单 | 无 |
| 讨论、决定和需求变化 | Gitea 工单正文或评论 | 无 |
| 长期有效的产品需求、业务规则和系统边界 | 对应 Gitea Wiki 主题页 | `docs/` |
| 完成后的实现、验证和遗留问题 | Wiki 任务归档 | 人工按需导出的 `docs/task/` 快照(可能不完整) |
任务产生长期结论时,先更新对应 Wiki 主题页,再导出本地镜像。Gitea 工单全文不导出到仓库,避免形成第二份任务过程记录。
## 稳定文档与任务归档 ## 稳定文档与任务归档
- Home、项目档案、代码地图、业务规则、开发验证、常见修改和故障排查描述项目现在怎样工作。 - Home、项目档案、代码地图、业务规则、开发验证、常见修改和故障排查描述项目现在怎样工作。
- 工单和任务归档解释某次为什么修改、实际改了什么以及如何验证。 - 工单和 Wiki 任务归档解释某次为什么修改、实际改了什么以及如何验证;本地任务快照不是完整历史。
- 新人先读稳定主题页,只有追查历史原因时才读任务归档。 - 新人先读稳定主题页,只有追查历史原因时才读任务归档。
- 任务产生的长期结论必须合并到主题页,不能只留在归档。 - 任务产生的长期结论必须合并到主题页,不能只留在归档。
@@ -153,6 +203,32 @@ python dev_scripts/new_task_archive.py 123 "修复登录超时"
- “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。 - “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。
- 未影响当前验收的相邻问题只提示或建单,不顺手处理。 - 未影响当前验收的相邻问题只提示或建单,不顺手处理。
## 自然语言快捷指令
快捷指令是对本工作流的自然语言别名,供 Claude Code、Codex 和维护者使用。它们只减少重复描述,不得绕过方案确认、前置依赖、安全规则、工单范围、Wiki 主源、必要验证或人工验收。
| 指令 | 执行动作 | 停止位置 |
|---|---|---|
| `只分析` | 只读检查需求、代码、日志和文档,区分事实与假设并给出方案 | 输出方案并等待确认;不建单、不修改 |
| `建工单` | 根据已经确认的方案创建单元任务工单 | 工单创建并记录完成;不修改代码 |
| `执行工单 #N` | 读取工单和前置依赖,实施、测试、提交、更新 Wiki、导出镜像、推送并回写证据 | 工单保持“待验收” |
| `建工单并做` | 依次执行“建工单”和“执行工单”;`建工单,做`、`建工单,做` 含义相同 | 工单保持“待验收” |
| `继续工单 #N` | 核对工单、Git 和 Wiki 证据,从首个未完成步骤继续,不重复仍然有效的检查 | 到达该工单当前流程的停止条件 |
| `检查工单 #N` | 只读对照范围、验收标准、测试和证据,报告通过项、缺失项及未验证部分 | 输出检查报告;不自动修复 |
| `同步文档` | 读取 Wiki,导出核心长期文档镜像并检查一致性,不处理任务归档 | 显示结果和差异;不修改 Wiki、不自动提交 |
| `导出任务归档` | 人工触发增量导出,只写入新增或 revision 已变化的任务归档 | 显示导出或跳过结果;不删除本地文件、不自动提交 |
| `导出全部任务归档` | 人工触发全量读取并导出线上全部任务归档 | 显示导出结果;不删除本地文件、不自动提交 |
| `#N 验收通过` | 记录明确验收,更新 Wiki 归档为“已完成”,同步必要的核心文档,推送、同步父工单并关闭任务;不自动导出任务归档 | 工单“已完成”并关闭 |
补充边界:
- 方案未确认时,`建工单`、`建工单并做` 和 `执行工单 #N` 不得绕过确认;Agent 应停在方案确认。
- 前置依赖未满足且不允许并行时,实施类指令停在“待实施”。
- `#N 验收通过` 必须来自用户明确表达;其他快捷指令不得关闭待验收工单。
- `同步文档` 或任务归档导出发现目标镜像有未提交改动时停止,不覆盖现有修改。
- `导出任务归档` 和 `导出全部任务归档` 必须由用户明确提出,其他快捷指令不隐式执行。
- Gitea 工单保留讨论和过程,不把工单全文导出到本地;`docs/task/` 只保存人工按需导出的 Wiki 最终任务归档快照。
## 什么时候重新确认方案 ## 什么时候重新确认方案
以下变化必须先更新工单,再由用户确认: 以下变化必须先更新工单,再由用户确认:
@@ -173,6 +249,6 @@ python dev_scripts/new_task_archive.py 123 "修复登录超时"
| 讨论过程和临时方案 | 是 | 否 | 否 | | 讨论过程和临时方案 | 是 | 否 | 否 |
| 实施进度和阻塞 | 是 | 否 | 否 | | 实施进度和阻塞 | 是 | 否 | 否 |
| 长期有效的最终方案 | 链接 | 是 | 镜像 | | 长期有效的最终方案 | 链接 | 是 | 镜像 |
| 测试结果与未验证内容 | 是 | 任务归档 | 镜像 | | 测试结果与未验证内容 | 是 | 任务归档 | 按需镜像 |
| 提交哈希 | 是 | 任务归档 | 镜像 | | 提交哈希 | 是 | 任务归档 | 按需镜像 |
| 与具体代码版本绑定的说明 | 可链接 | 提供入口 | 是 | | 与具体代码版本绑定的说明 | 可链接 | 提供入口 | 是 |
+11 -4
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Business-Rules-and-Glossary wiki_page: Business-Rules-and-Glossary
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Business-Rules-and-Glossary.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Business-Rules-and-Glossary.-
wiki_revision: 7534fd60157096dab2c6f06214acfff84d1a5370 wiki_revision: f78f2f92f563ec8dce5e399d4ee2b37896fa98dd
synchronized_at: 2026-08-08T00:58:06Z synchronized_at: 2026-08-10T03:51:38Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 业务规则与术语 # 业务规则与术语
@@ -19,6 +19,9 @@ synchronized_at: 2026-08-08T00:58:06Z
| Epic | 完整产品目标和长期路线 | 可以直接实施的单个任务 | | Epic | 完整产品目标和长期路线 | 可以直接实施的单个任务 |
| MVP | 第一个可交付范围及集成边界 | 任意里程碑名称 | | MVP | 第一个可交付范围及集成边界 | 任意里程碑名称 |
| 单元任务 | 唯一正式实施单位,可独立测试和回退 | 临时聊天待办 | | 单元任务 | 唯一正式实施单位,可独立测试和回退 | 临时聊天待办 |
| 关键原始需求 | 能表达用户目的、场景和限制的少量原话或脱敏摘要 | 完整聊天记录 |
| 正式任务需求 | 用户确认后写入单元工单的目标、非目标、方案和验收标准 | Agent 未确认的理解 |
| 需求变化记录 | 实施期间影响范围或验收的变化、原因及用户确认 | 每一句普通讨论 |
| 事实来源 | 某类信息被正式维护的位置 | 多处内容可以随意覆盖 | | 事实来源 | 某类信息被正式维护的位置 | 多处内容可以随意覆盖 |
| Wiki 主源 | 长期开发文档首先修改的位置 | 本地 docs 的备份副本 | | Wiki 主源 | 长期开发文档首先修改的位置 | 本地 docs 的备份副本 |
| docs 镜像 | 从 Wiki 单向生成的浏览副本 | 可以直接编辑并反向同步的文档 | | docs 镜像 | 从 Wiki 单向生成的浏览副本 | 可以直接编辑并反向同步的文档 |
@@ -30,9 +33,9 @@ synchronized_at: 2026-08-08T00:58:06Z
| 状态 | 含义 | 可以进入下一状态的条件 | | 状态 | 含义 | 可以进入下一状态的条件 |
|---|---|---| |---|---|---|
| 待确认 | 目标或方案仍需用户选择 | 用户明确确认方案 | | 待确认 | 目标或方案仍需用户选择 | 用户明确确认方案 |
| 待实施 | 方案已确认,尚未修改 | 工作区和范围检查完成 | | 待实施 | 方案已确认但尚未修改,或真实前置依赖尚未满足 | 前置依赖已满足或明确允许并行,且工作区和范围检查完成 |
| 进行中 | 正在实现、测试或同步文档 | 验收标准逐项检查完成 | | 进行中 | 正在实现、测试或同步文档 | 验收标准逐项检查完成 |
| 阻塞 | 满足规则定义的持续阻塞条件 | 阻塞解除并更新工单 | | 阻塞 | 实施过程中出现计划外、当前无法解除的问题 | 阻塞解除并更新工单 |
| 待验收 | 代码、测试、归档和证据已完成 | 用户明确验收 | | 待验收 | 代码、测试、归档和证据已完成 | 用户明确验收 |
| 已完成 | 用户已验收并完成父任务同步 | 无 | | 已完成 | 用户已验收并完成父任务同步 | 无 |
@@ -40,7 +43,11 @@ synchronized_at: 2026-08-08T00:58:06Z
- 没有确认方案和单元任务工单,不修改产品行为。 - 没有确认方案和单元任务工单,不修改产品行为。
- 一个单元任务只解决一个可独立验证和回退的问题。 - 一个单元任务只解决一个可独立验证和回退的问题。
- 建立后续工单不要求已有工单全部完成;实施前必须检查工单声明的前置依赖。
- 前置工单未完成且存在实际依赖时保持“待实施”;允许并行时必须写明原因。
- 需求、接口、数据、安全边界或验收标准变化时先更新工单。 - 需求、接口、数据、安全边界或验收标准变化时先更新工单。
- 工单只保存关键原始需求、确认后的正式需求和重要变化,不保存完整聊天或 Agent 内部推理。
- 长期有效的产品需求和业务规则进入 Wiki;Gitea 工单全文不导出到本地。
- 长期文档必须先修改 Wiki,再导出本地镜像。 - 长期文档必须先修改 Wiki,再导出本地镜像。
- 测试结果必须真实;未执行的验证必须明确记录。 - 测试结果必须真实;未执行的验证必须明确记录。
- 用户未明确验收前,工单保持开启。 - 用户未明确验收前,工单保持开启。
+105 -15
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: New-Project-Documentation-Setup wiki_page: New-Project-Documentation-Setup
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/New-Project-Documentation-Setup.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/New-Project-Documentation-Setup.-
wiki_revision: a0eeab23a41671b5dbfc3153e872b71647ea41c7 wiki_revision: 864d81b515b420d17fa4ff0fc7f528109b1a3d99
synchronized_at: 2026-08-08T01:16:59Z synchronized_at: 2026-08-16T11:38:04Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 新项目文档初始化 # 新项目文档初始化
@@ -26,19 +26,89 @@ synchronized_at: 2026-08-08T01:16:59Z
把项目专用红线写入根目录或子目录 `AGENTS.md`。 把项目专用红线写入根目录或子目录 `AGENTS.md`。
### 2. 建立 Gitea ### 2. 选择建设基线
确定技术方案前,优先评估是否存在功能和架构匹配、持续维护、许可证兼容且工程流程完善的开源项目。这里要求的是“先评估”,不是强制采用开源项目,也不能只根据知名度、Star 数量或演示效果决定。
至少检查:
- 核心功能、架构和支持平台是否匹配,哪些能力可以直接保留;
- 许可证是否允许预期的使用、修改、分发和商业模式;不确定时交由负责人或法律专业人员确认;
- 最近维护活跃度、发布频率、Issue 处理和社区或维护团队的持续性;
- 已知安全问题、依赖健康度、供应链风险和安全响应方式;
- 自动化测试、CI、发布、升级、回退和文档是否足以支持长期维护;
- 定制、学习、迁移和后续跟踪上游的总成本是否低于从零开发;
- 是否能够固定上游仓库和基线版本,并建立合并上游更新、兼容验证和退出方案。
满足适配、许可证、安全、维护和总成本条件时,优先在该基线上二次开发。不存在合适基线,或引入后会增加不可接受的许可证、安全、架构或维护风险时,可以从零开发,但必须记录排除候选项目和选择从零开发的主要原因。
采用开源基线时,在 Project-Profile 的“技术栈与运行环境”记录上游项目名称、仓库地址、基线版本或提交、许可证、保留能力、定制范围和上游升级策略。尚未确认的候选和取舍先写入首个技术方案工单,不得把假设写成项目事实。
#### 判断案例
以下案例用于说明判断方式,不代表必须选择某种技术或具体开源项目。
##### 案例一:适合基于成熟项目二次开发
计划开发企业内部管理系统。候选项目已经具备用户、权限、审计日志、基础数据管理和自动化测试;功能与目标架构基本匹配,许可证允许预期使用,项目持续维护,发布与升级流程完整,预计只需修改业务模块和界面。
- 结论:优先基于该项目二次开发。
- 原因:可以减少通用功能的开发和验证成本,定制范围可控。
- 记录:上游仓库、基线版本、许可证、保留功能、定制模块和上游升级方式。
##### 案例二:项目成熟但许可证不兼容
候选项目功能完整、维护活跃、文档充分,但许可证与当前产品的闭源分发、商业模式或交付条件不兼容。
- 结论:不采用该项目作为建设基线。
- 原因:技术成熟度不能消除许可证风险;不确定结论必须交由负责人或法律专业人员确认。
- 记录:候选项目、许可证限制、确认人员和排除原因。
##### 案例三:功能相似但改造成本过高
候选项目表面上覆盖大部分功能,但数据模型、权限体系和部署结构与目标项目差异很大,需要大量删除模块、重写主要接口,并长期维护上游冲突。
- 结论:不直接基于完整项目二次开发,可以评估只复用合适的组件或设计思路。
- 原因:二次开发的总成本、理解成本和长期维护风险已经高于自主实现核心业务。
- 记录:主要结构差异、改造估算、长期维护风险和最终选择。
##### 案例四:只复用成熟框架或组件
没有功能高度匹配的完整开源产品,但存在成熟的应用框架、更新组件、日志组件或通信库。
- 结论:从零开发业务功能,同时复用经过评估的成熟框架或组件。
- 原因:复用基础能力不等于必须采用完整产品,可以避免被不匹配的业务架构绑定。
- 记录:每个依赖的用途、版本、许可证、安全边界、升级方式和可替换方案。
每个案例的实际评估都必须记录候选项目、判断依据、最终选择、未采用原因,以及升级或退出方式。
### 3. 识别子项目与交付单元
先判断仓库中有几个应用、服务、客户端、库或其他可独立交付的部分。对每个部分确认:
- 职责和目录边界;
- 技术栈、依赖和支持环境;
- 构建、测试和运行命令;
- 是否拥有独立版本号和发布方式;
- 适用的根目录或子目录 `AGENTS.md`;
- 与其他子项目共享的接口、数据或业务流程;
- 共享契约的唯一事实来源和兼容要求。
把结果写入 Project-Profile 的“子项目与交付单元”。单应用项目只填写一个交付单元;多应用单仓库为规则不同的目录增加子目录 `AGENTS.md`,但不因为技术栈不同自动拆仓,也不强制统一版本和发布周期。
### 4. 建立 Gitea
创建远端仓库并完成允许的初始引导提交。开启工单和 Wiki。任何产品功能开发在引导提交后都必须先有单元任务工单。 创建远端仓库并完成允许的初始引导提交。开启工单和 Wiki。任何产品功能开发在引导提交后都必须先有单元任务工单。
### 3. 修改镜像配置 ### 5. 修改镜像配置
把 `wiki-docs.json` 中的地址、owner 和 repository 改成新项目;核心主题映射保留。 把 `wiki-docs.json` 中的地址、owner 和 repository 改成新项目;只保留核心主题映射,任务归档不逐页登记。
确认当前目录确实是新项目副本、且 DevHarness 历史归档不需要保留后,移除属于 DevHarness 的任务归档映射和对应 `docs/task/` 镜像。不要在原 DevHarness 仓库或已有业务项目中执行这项清理。 确认当前目录确实是新项目副本、且 DevHarness 历史归档快照不需要保留后,可以移除对应 `docs/task/` 文件。不要在原 DevHarness 仓库或已有业务项目中执行这项清理。
不要把 PAT 写入配置。 不要把 PAT 写入配置。
### 4. Agent 检查项目事实 ### 6. Agent 检查项目事实
Agent 只读检查: Agent 只读检查:
@@ -51,7 +121,19 @@ Agent 只读检查:
区分“代码中确认的事实”“负责人确认的业务规则”和“仍待确认的假设”。 区分“代码中确认的事实”“负责人确认的业务规则”和“仍待确认的假设”。
### 5. 先创建线上 Wiki ### 7. 确定交付对象和文档
由项目负责人确认哪些岗位或客户会实际使用、部署、管理、支持、集成或验收产品,并为每类对象确定:
- 需要完成的工作;
- 所需文档类型;
- 文档可见范围;
- 适用版本、负责人和验证人;
- 不得对外披露的内部信息。
按照[交付文档指南](Delivery-Documentation-Guide.-)选择文档,使用[岗位文档模板](Audience-Document-Template.-)按需创建。没有明确读者的文档不创建,不预建空白的用户手册、管理员手册或运维手册。
### 8. 先创建线上 Wiki
至少创建或填写: 至少创建或填写:
@@ -63,11 +145,13 @@ Agent 只读检查:
6. Common-Changes; 6. Common-Changes;
7. Troubleshooting; 7. Troubleshooting;
8. Development-Workflow; 8. Development-Workflow;
9. Task-Archive-Template。 9. Delivery-Documentation-Guide;
10. Audience-Document-Template;
11. Task-Archive-Template。
Home 给出建议阅读顺序;每个命令必须有预期结果;代码地图必须指出入口和测试位置。 Home 给出建议阅读顺序;每个命令必须有预期结果;代码地图必须指出入口和测试位置。具体岗位文档仅按第 7 步确认的受众创建。
### 6. 人工确认 ### 9. 人工确认
项目负责人至少确认: 项目负责人至少确认:
@@ -75,9 +159,10 @@ Home 给出建议阅读顺序;每个命令必须有预期结果;代码地图
- 关键业务规则和状态; - 关键业务规则和状态;
- 权限、安全和数据边界; - 权限、安全和数据边界;
- 真实运行、测试和部署命令; - 真实运行、测试和部署命令;
- 哪些修改属于高风险。 - 哪些修改属于高风险;
- 交付对象、文档可见范围和外部信息边界。
### 7. 导出镜像并检查 ### 10. 导出镜像并检查
```powershell ```powershell
python dev_scripts/sync_wiki_docs.py python dev_scripts/sync_wiki_docs.py
@@ -86,7 +171,7 @@ python dev_scripts/sync_wiki_docs.py --check
python -m unittest discover -s tests -v python -m unittest discover -s tests -v
``` ```
只有线上 Wiki 确认后才导出 `docs/`。旧项目的任务归档不能带入新项目历史。 只有线上 Wiki 确认后才导出核心 `docs/`。任务归档默认不导出;用户明确要求时再运行 `python dev_scripts/export_task_archives.py` 或加 `--all`。旧项目的任务归档快照不能带入新项目历史。
## 完成标准 ## 完成标准
@@ -96,6 +181,11 @@ python -m unittest discover -s tests -v
- 怎样启动和运行测试; - 怎样启动和运行测试;
- 常用功能从哪个目录和入口开始读; - 常用功能从哪个目录和入口开始读;
- 一个简单修改通常要改哪里、验证什么; - 一个简单修改通常要改哪里、验证什么;
- 哪些情况必须停止并交给 Agent 或负责人。 - 哪些情况必须停止并交给 Agent 或负责人;
- 项目采用哪个建设基线,为什么适合二次开发,或者为什么选择从零开发;
- 采用开源基线时,上游仓库、基线版本、许可证、定制范围和升级策略是什么;
- 项目包含哪些子项目和独立交付单元,各自怎样构建、测试和发布;
- 跨子项目共享什么接口或契约,其唯一事实来源在哪里;
- 项目需要向哪些岗位交付什么文档,以及哪些内容不能对外提供。
回答不了的问题应继续补充主题文档,而不是堆入任务归档。 回答不了的问题应继续补充主题文档,而不是堆入任务归档。
+235
View File
@@ -0,0 +1,235 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Existing-Project-Adoption-Guide
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Existing-Project-Adoption-Guide.-
wiki_revision: 2ef3d7cd26874f652e9bfab2a5c2f6c8273ab7ac
synchronized_at: 2026-08-16T11:50:18Z
<!-- gitea-wiki-mirror:end -->
# 已有项目接入 DevHarness 指南
## 本页用途
本页用于把 DevHarness 的文档模板和开发流程增量接入已经存在的项目。已有项目通常已经有代码、规则、文档、工单、Wiki、Git 历史和未完成工作,因此接入目标是补齐必要能力,不是把项目重置成 DevHarness 模板副本。
接入必须先只读盘点、确认差异方案,再建立单元任务工单实施。未经确认不得覆盖、删除、重命名或批量迁移已有内容。
## 与新项目初始化的区别
| 场景 | 新项目初始化 | 已有项目接入 |
|---|---|---|
| 项目事实 | 从代码骨架和负责人确认开始建立 | 优先保留并核对已有事实 |
| 规则文件 | 可以从模板建立第一版 | 必须合并已有规则,不能直接覆盖 |
| 文档 | 创建核心主题页 | 逐页判断保留、迁移、合并或停止维护 |
| 工单和 Wiki | 新建并开始使用 | 先检查已有工单、Wiki 和状态体系 |
| Git 历史 | 允许一次引导提交 | 保留全部历史,不使用引导提交例外 |
| 任务归档 | 从新项目任务开始 | 不复制 DevHarness 或其他项目的历史归档 |
| 接入方式 | 一次建立最小骨架 | 分阶段增量接入并逐步验收 |
从模板创建全新仓库时使用[新项目文档初始化](New-Project-Documentation-Setup.-);项目已有业务提交、用户或维护历史时使用本页。
## 接入前只读盘点
Agent 在提出方案前只读检查:
- 根目录和相关子目录中的 `AGENTS.md`、`CLAUDE.md` 及其他 Agent 规则;
- README、现有 `docs/`、Wiki 页面、工单模板和任务状态;
- Git 默认分支、远端、提交历史、未提交修改和忽略规则;
- 语言、框架、依赖、启动入口、主要模块和目录职责;
- 格式检查、静态检查、单元测试和必要集成测试命令;
- 配置、日志、接口、数据模型、权限、安全、部署和发布边界;
- 已完成、进行中、阻塞和待验收任务;
- 现有长期文档的事实来源、负责人和更新方式。
输出时区分:
1. 从代码、配置或现有系统确认的事实;
2. 项目负责人确认的业务规则;
3. 尚待确认的假设;
4. DevHarness 与现有规则的冲突;
5. 与接入无关、必须保留的工作区改动。
只读盘点不授权修改文件、创建 Wiki、迁移文档或改变工单状态。
## 已有内容保护原则
- 保留 Git 历史、分支、标签和当前任务状态。
- 保留已有 `AGENTS.md`、README、规则和项目专用红线;DevHarness 规则按冲突结果增量合并。
- 保留与接入无关的未提交改动,不重置、不覆盖、不混入提交。
- 不复制 DevHarness 的 `docs/task/`、任务归档映射和历史工单。
- 不因采用 Wiki-first 就立即删除原本地文档;先逐页确认事实来源和迁移状态。
- 不把模板占位值当成项目事实,不臆造技术栈、命令、业务规则、凭据或环境。
- 不把密码、令牌、Cookie、私钥、个人数据或生产数据带入工单、Wiki和镜像。
- 页面删除、重命名、历史清理和事实来源切换必须单独确认。
## 多应用单仓库判断
一个 Git 仓库可以包含多个技术栈不同、能够独立构建和发布的应用或终端。技术栈不同本身不是拆仓理由;先把每个子项目和交付单元记录到 Project-Profile,再根据实际协作边界判断。
### 适合继续单仓库
- 多个应用共同完成一条产品或业务链路;
- 由同一团队维护,仓库权限基本一致;
- 接口变更需要在一个工单中同步修改或验证多端;
- 共享契约、业务规则和任务归档放在一起更容易保持一致;
- 仓库体积、测试时间和工具性能尚未明显影响开发;
- 初级维护者和 Agent 能通过目录、子目录 `AGENTS.md` 和文档入口清楚定位。
### 可以考虑拆仓
- 长期由不同团队独立负责并需要不同访问权限;
- 发布周期、版本策略和验收负责人已经完全独立;
- 某个应用被多个产品复用或需要单独对外提供;
- 仓库体积、检出、索引或测试耗时已经持续影响效率;
- 共享接口已经版本化、兼容周期明确,并有跨仓契约测试;
- 跨应用任务很少,拆仓后的协调成本低于继续共仓。
不满足这些条件时,优先保持单仓库并完善边界,不为了目录整洁或技术栈不同而拆仓。
### 保持单仓库时的最小规则
- 根目录 `AGENTS.md` 只放共同流程、安全和跨项目规则,技术栈专用规则写入子目录 `AGENTS.md`。
- 每个交付单元拥有自己的构建、测试、版本和发布方式,不强制统一版本。
- 单元任务必须声明只影响哪个子项目、是否跨子项目、是否修改共享接口,以及各端需要执行的验证。
- 共享接口或契约只能指定一个事实来源;其他文档引用它,不复制一个“差不多”的版本。
- 跨子项目契约变更在同一工单中更新事实来源,并验证所有受影响端。
- 拆仓属于事实来源、任务和发布边界变化,必须另建工单、确认迁移和回退方案后实施。
## 增量接入顺序
### 1. 确认差异方案
根据盘点结果列出目标、非目标、复用项、改写项、冲突项、影响范围、风险、回退、验证和文档影响。方案得到用户明确确认前不实施。
### 2. 建立单元任务工单
使用目标项目的 Gitea 建立接入工单,记录原始需求、范围、依赖、方案和验收标准。目标项目没有可用 Gitea 时,先提交完整工单草稿并说明阻塞,不默认绕过。
### 3. 接入共同规则和工单流程
优先增量合并根规则、Claude 入口和单元任务模板。项目专用安全、业务和目录规则继续有效;冲突时由负责人决定最终表述。
### 4. 确定长期文档事实来源
为每份已有文档标记:
- 保留在 Git:与特定代码版本强绑定;
- 迁移到 Wiki:长期架构、业务规则、开发规范或操作说明;
- 合并:内容重复但各有有效事实;
- 暂不迁移:事实未确认或当前不影响接入;
- 停止维护:必须由负责人确认,不能由 Agent 自行删除。
切换到 Wiki-first 的页面必须先在线上创建或更新、读取确认,再建立 `wiki-docs.json` 映射并导出本地镜像。避免 Wiki 和手写本地文档长期形成双事实源。
### 5. 接入 Harness 工具
仅复制当前项目实际需要的 `dev_scripts/` 工具、配置和测试。业务脚本使用独立目录。根据目标项目调整核心页面、路径、命令和结构检查,不照搬 DevHarness 项目值。
### 6. 分阶段验证
先验证工单和规则入口,再验证 Wiki 映射,最后启用严格检查。每阶段采用“执行 → 首个真实错误 → 最小修复 → 继续”的闭环,不用一次接入全部旧文档。
### 7. 提交和验收
提交只包含当前接入工单相关文件。记录测试、未验证部分、Wiki revision 和提交哈希,创建任务归档并保持工单“待验收”,等待用户明确验收后再关闭。
## 后续升级
已接入的项目必须以 Project-Profile 中记录的 DevHarness 来源和当前基线为起点升级,不得重新复制整个模板,也不得用“最新版本”代替可复现的目标提交。
### 升级步骤
1. 读取目标项目的 Project-Profile,确认 DevHarness 来源仓库、当前基线完整提交、最后升级日期和项目适配说明;字段缺失时先补齐可验证事实,无法确认则停止。
2. 选择一个明确、已审阅的 DevHarness 目标提交,记录旧基线和新基线。先比较两个上游提交之间的变化,再判断这些变化如何作用于目标项目。
3. 只读比较与 Harness 有关的 `AGENTS.md`、`CLAUDE.md`、工单模板、`dev_scripts/`、Harness 测试和核心 Wiki 结构,把差异分为“直接采用、按项目改写、冲突待确认、不采用”。不得把 DevHarness 的项目事实、工单或任务归档带入目标项目。
4. 在目标项目建立单元任务工单,写明升级范围、差异分类、项目专用规则、风险、回退、验证和文档影响。会改变产品行为的内容必须拆成独立任务。
5. 按工单最小合并,保留目标项目更具体的业务、安全、权限和目录规则,以及 Git 历史和无关工作区修改。无法判断哪一方规则有效时停止并等待负责人确认。
6. 长期文档先更新目标项目 Wiki,读取确认后再同步目标项目的核心 `docs/` 镜像;不得用 DevHarness 的本地镜像覆盖目标项目文档。
7. 执行目标项目规定的必要检查和受影响测试,提交并回写证据。工单保持“待验收”。
8. 用户验收通过后,确认目标项目 Project-Profile 已记录新 DevHarness 基线完整提交和升级日期,再关闭工单。升级失败或回退时保留旧基线。
### 升级停止条件
除本页已有的冲突停止条件外,来源仓库与记录不一致、旧基线不存在、目标提交未明确、差异跨越过大而无法可靠分类,或升级需要覆盖项目专用安全规则时,都必须停止并请求确认。可以把升级拆成多个单元任务,但每个任务都要声明最终采用的同一目标基线。
### 可复制升级指令
```text
请把当前项目从 Project-Profile 记录的 DevHarness 基线升级到
<DevHarness 目标完整提交哈希>。
先只读比较来源仓库中“旧基线..目标基线”的 Harness 变化和当前项目
适配,列出直接采用、按项目改写、冲突待确认和不采用的内容,以及
风险、回退、验证和文档影响。不要覆盖项目专用规则、业务文档、Git
历史或无关改动,不复制 DevHarness 工单和任务归档。方案确认后在
当前项目建单并实施;长期文档先改当前项目 Wiki,再同步本地镜像。
工单保持待验收,验收通过后确认 Project-Profile 已记录新基线。
```
路径和目标完整提交哈希必须替换为真实值;目标提交未明确时只分析,不实施。
## 冲突处理和停止条件
出现以下情况时停止实施并请求负责人确认:
- 现有规则与 DevHarness 的安全、权限、事实来源或验收规则冲突;
- 无法判断某份文档应该保留、迁移、合并还是停止维护;
- 需要删除、重命名 Wiki 页面、覆盖已有文件或清理历史归档;
- 需要改变接口、数据库、权限、部署、发布或其他产品行为;
- 工作区存在可能与接入文件重叠的未知修改;
- Gitea、Wiki、凭据或远端权限不可用;
- 真实命令、环境或业务规则无法从证据或负责人确认。
相邻问题最多提示或另建工单,不混入接入任务。
## 可复制 Agent 指令
### 只分析
```text
请把 <DevHarness 路径> 的文档模板和开发流程接入当前已有项目。
先只分析,不修改文件、工单或 Wiki:
1. 阅读 DevHarness 的 AGENTS.md、README.md、项目档案、开发工作流、
新项目文档初始化和已有项目接入指南。
2. 阅读当前项目已有的 Agent 规则、README、docs、Gitea 工单模板、
Wiki 配置、代码入口、测试命令和目录结构。
3. 列出已有规则、文档、任务状态、Git 历史和未提交改动。
4. 对比后列出可复用项、必须改写项、冲突项、旧文档处理方式、
最小接入范围、风险、回退、验证和文档影响。
5. 不复制 DevHarness 任务归档,不覆盖、删除或重命名已有内容,
不把模板占位值当成项目事实。
6. 输出方案后停止,等待我确认。
```
### 方案确认后实施
```text
按照已确认方案建工单并做。
严格按工单范围增量接入 DevHarness,保留当前项目已有规则、历史、
任务状态和无关改动。长期文档先更新 Gitea Wiki,读取确认后再导出
本地 docs 镜像。执行必要测试,提交实现和任务归档,然后把工单保持
为“待验收”;未经我明确验收,不关闭工单。
```
路径、仓库地址和项目名称必须替换为当前环境的真实值。第二段指令只有在第一段方案已经明确确认后使用。
## 最小验收清单
- [ ] 已盘点规则、文档、任务、Git 历史和未提交改动。
- [ ] 已识别所有子项目和独立交付单元。
- [ ] 跨子项目共享契约已经指定唯一事实来源。
- [ ] 已明确复用、改写、冲突和暂不处理内容。
- [ ] 已保留项目专用规则、历史和无关改动。
- [ ] 未复制 DevHarness 历史归档或模板项目事实。
- [ ] 已为每类长期文档明确事实来源和迁移状态。
- [ ] Wiki-first 页面已经读取确认并具有显式镜像映射。
- [ ] Harness 检查已按目标项目调整并通过。
- [ ] 必要测试、未验证部分、提交和归档证据已记录。
- [ ] 工单处于待验收,未提前关闭。
## 回退原则
接入应拆成可回退的小提交。普通回退恢复本次新增或修改的规则、配置、检查和镜像映射,不触碰原有业务提交。Wiki 页面删除、重命名、历史清理或事实来源反向切换不是普通回退,必须另行建单并等待确认。
+14 -7
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Home wiki_page: Home
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Home wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Home
wiki_revision: f1baf5947fe4e8f08cfc3ccc129946964fbbc3e5 wiki_revision: 52e9a6f8fe4fe03db8c65792ef500cc9a5084384
synchronized_at: 2026-08-08T01:16:46Z synchronized_at: 2026-08-16T11:18:48Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# DevHarness 文档中心 # DevHarness 文档中心
@@ -22,7 +22,7 @@ DevHarness 是一个以 Gitea 工单管理开发任务、以 Wiki 管理长期
6. [故障排查](Troubleshooting):遇到错误时按什么顺序检查。 6. [故障排查](Troubleshooting):遇到错误时按什么顺序检查。
7. [开发工作流](Development-Workflow.-):完整建单、实施、验收和归档流程。 7. [开发工作流](Development-Workflow.-):完整建单、实施、验收和归档流程。
从模板创建新项目时先阅读[新项目文档初始化](New-Project-Documentation-Setup.-)。 从模板创建新项目时先阅读[新项目文档初始化](New-Project-Documentation-Setup.-);向已有项目增量接入本流程时阅读[已有项目接入 DevHarness 指南](Existing-Project-Adoption-Guide.-)。需要为客户或其他岗位准备说明时,阅读[交付文档指南](Delivery-Documentation-Guide.-),再按需使用[岗位文档模板](Audience-Document-Template.-)。
## 五分钟开始 ## 五分钟开始
@@ -49,6 +49,8 @@ python dev_scripts/sync_wiki_docs.py --check
| 想做什么 | 先读哪里 | 主要验证 | | 想做什么 | 先读哪里 | 主要验证 |
|---|---|---| |---|---|---|
| 修改文档 | 对应 Wiki 页面、Common-Changes | Wiki 同步检查 | | 修改文档 | 对应 Wiki 页面、Common-Changes | Wiki 同步检查 |
| 接入已有项目 | Existing-Project-Adoption-Guide | 只读盘点、差异确认和分阶段验证 |
| 准备交付文档 | Delivery-Documentation-Guide、Audience-Document-Template | 目标岗位验证和 Wiki 同步检查 |
| 调整工单字段 | `.gitea/issue_template/`、Development-Workflow | Harness 严格检查 | | 调整工单字段 | `.gitea/issue_template/`、Development-Workflow | Harness 严格检查 |
| 修改同步行为 | `dev_scripts/wiki_docs.py`、Architecture-and-Code-Map | 单元测试和真实 Wiki 检查 | | 修改同步行为 | `dev_scripts/wiki_docs.py`、Architecture-and-Code-Map | 单元测试和真实 Wiki 检查 |
| 增加结构检查 | `dev_scripts/check_harness.py` | 成功与失败测试 | | 增加结构检查 | `dev_scripts/check_harness.py` | 成功与失败测试 |
@@ -61,9 +63,10 @@ python dev_scripts/sync_wiki_docs.py --check
| 信息 | 事实来源 | | 信息 | 事实来源 |
|---|---| |---|---|
| 任务状态、讨论、阻塞、验收过程 | Gitea 工单 | | 任务状态、讨论、阻塞、验收过程 | Gitea 工单 |
| 架构、业务规则、开发规范、操作手册、任务归档 | Gitea Wiki | | 架构、业务规则、开发规范、操作手册、交付文档、任务归档 | Gitea Wiki |
| 源码和与特定代码版本强绑定的文档 | Git 仓库 | | 源码和与特定代码版本强绑定的文档 | Git 仓库 |
| 离线浏览副本 | Git 仓库中的 `docs/` Wiki 镜像 | | 核心长期文档的离线浏览副本 | Git 仓库中的 `docs/` Wiki 镜像 |
| 完整任务归档 | Gitea Wiki;`docs/task/` 仅是人工按需导出的快照 |
本地 `docs/` 不是编辑入口。长期文档必须先修改 Wiki,读取确认后再导出镜像。 本地 `docs/` 不是编辑入口。长期文档必须先修改 Wiki,读取确认后再导出镜像。
@@ -71,6 +74,9 @@ python dev_scripts/sync_wiki_docs.py --check
- [Gitea 工单](http://ilaer.eicp.net:8418/opc/dev_harness/issues) - [Gitea 工单](http://ilaer.eicp.net:8418/opc/dev_harness/issues)
- [代码仓库](http://ilaer.eicp.net:8418/opc/dev_harness) - [代码仓库](http://ilaer.eicp.net:8418/opc/dev_harness)
- [已有项目接入 DevHarness 指南](Existing-Project-Adoption-Guide.-)
- [交付文档指南](Delivery-Documentation-Guide.-)
- [岗位文档模板](Audience-Document-Template.-)
- [任务归档模板](Task-Archive-Template.-) - [任务归档模板](Task-Archive-Template.-)
## 同步原则 ## 同步原则
@@ -79,9 +85,10 @@ python dev_scripts/sync_wiki_docs.py --check
修改 Wiki → 读取确认 → 导出 docs → 校验差异 → 提交镜像 修改 Wiki → 读取确认 → 导出 docs → 校验差异 → 提交镜像
``` ```
- 页面和本地路径通过仓库中的 `wiki-docs.json` 显式映射。 - 核心页面和本地路径通过仓库中的 `wiki-docs.json` 显式映射;普通同步不处理任务归档。
- 任务归档默认只保存在 Wiki,只有用户明确提出时才增量或全量导出到 `docs/task/`。
- 镜像头记录来源页面、Wiki revision 和同步时间。 - 镜像头记录来源页面、Wiki revision 和同步时间。
- 已映射镜像存在未提交修改时同步必须停止。 - 已映射镜像存在未提交修改时同步必须停止。
- 页面删除、重命名和映射变更必须人工确认。 - 页面删除、重命名和映射变更必须人工确认。
- Wiki 或导出失败时,相关任务不能标记为完成。 - 核心 Wiki 或必要同步失败时,相关任务不能标记为完成;未请求任务归档导出不阻止任务完成。
- 凭据、个人数据和生产数据不得进入 Wiki 或镜像。 - 凭据、个人数据和生产数据不得进入 Wiki 或镜像。
+80
View File
@@ -0,0 +1,80 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Delivery-Documentation-Guide
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Delivery-Documentation-Guide.-
wiki_revision: d9de4f8d8abc40630069c67948ca2a5086f90e70
synchronized_at: 2026-08-10T06:23:38Z
<!-- gitea-wiki-mirror:end -->
# 交付文档指南
## 本页用途
本页规定项目开发完成后,怎样为客户、最终用户和其他岗位选择、编写、验证及维护交付文档。交付文档面向实际使用产品的人,不替代开发工作流、架构说明和任务归档。
最小原则:先确认交付对象,只创建对方完成工作确实需要的文档,不预建空白手册。
## 什么时候需要交付文档
出现以下任一情况时,应在单元任务工单中评估并更新交付文档:
- 新增或改变用户可见功能、操作步骤、界面、权限或限制;
- 改变安装、配置、部署、备份、恢复、监控或升级方法;
- 改变外部 API、数据格式、集成条件或兼容范围;
- 改变常见故障的识别、处理或支持方式;
- 发布新版本或交付客户验收。
纯内部重构只有在外部行为、操作方式、配置和支持边界均未改变时,才可选择“无交付文档影响”并说明原因。
## 受众与文档选择
| 交付对象 | 典型文档 | 需要回答的问题 |
|---|---|---|
| 最终用户 | 用户使用说明 | 怎样完成日常操作,失败后怎么办 |
| 管理员 | 管理员指南 | 怎样配置用户、权限和系统参数 |
| 运维人员 | 部署与运维指南 | 怎样安装、启停、监控、备份和恢复 |
| 客服或一线支持 | 支持与排错指南 | 怎样识别问题、收集信息和升级处理 |
| 集成人员 | 接口与集成指南 | 怎样认证、调用接口和处理兼容性 |
| 验收或项目负责人 | 发布、升级与验收说明 | 本次交付了什么,怎样验证和回退 |
一个项目只选择实际存在的交付对象。多个岗位需要相同内容时可共享一份文档,但必须明确各自可以执行的操作和权限边界。
## 内部文档与交付文档边界
交付文档可以包含用户完成工作所需的产品地址、公开接口、配置项、操作步骤、结果、限制和支持渠道。
面向客户或公开的文档不得包含:
- 内部工单链接、聊天记录、内部决策过程或任务归档;
- 内部网络地址、仓库路径、无必要的源码模块名和调试细节;
- 密码、令牌、Cookie、私钥、个人数据或生产数据;
- 未经确认的安全实现、漏洞细节或仅供内部使用的恢复手段;
- 未承诺的路线图、期限和功能。
交付前必须检查模板中的“可见范围”。同一主题同时存在内部版和客户版时,应分别维护并明确名称,不能依靠读者自行忽略内部内容。
## 编写和维护流程
1. 在项目初始化或需求确认时识别交付对象、可见范围和所需文档。
2. 使用[岗位文档模板](Audience-Document-Template.-)按需创建文档,不创建没有明确读者的空页面。
3. 单元任务在工单“交付文档影响”中选择无影响并说明原因,或列出需要更新的页面和受众。
4. 功能、配置或流程改变时,代码与对应交付文档在同一任务中更新。
5. 由熟悉该岗位但未参与实现的人按文档执行关键步骤;不能验证的环境和步骤必须明确标注。
6. 发布或交付前确认适用版本、最后验证日期、负责人、已知限制和支持渠道。
7. 长期维护仍遵循 Wiki-first:先修改 Wiki、读取确认,再导出本地 `docs/` 镜像。
具体项目创建的岗位文档应增加到 `wiki-docs.json` 的显式映射中。本模板自身的指南和模板镜像位于 `docs/delivery/`。
## 最小验收清单
- [ ] 文档有明确受众、适用版本、可见范围和负责人。
- [ ] 前置条件、操作步骤和预期结果完整且可以对应。
- [ ] 常见失败、恢复方法、安全提示和已知限制已说明。
- [ ] 关键步骤由目标岗位视角验证,或明确记录未验证项。
- [ ] 外部版本不含内部链接、敏感数据和无关实现细节。
- [ ] 本次功能变化涉及的交付文档已更新并与版本一致。
- [ ] Wiki 已读取确认,本地镜像检查一致。
## 不在本页解决的内容
开发任务怎样建单、实施和归档见[开发工作流](Development-Workflow.-);代码结构和维护入口见[架构与代码地图](Architecture-and-Code-Map.-)。本页不规定市场宣传、合同、法务或商务承诺。
@@ -0,0 +1,96 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Audience-Document-Template
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Audience-Document-Template.-
wiki_revision: 7a8f38df566fe639094497c9692e0559c9c080e6
synchronized_at: 2026-08-10T06:23:41Z
<!-- gitea-wiki-mirror:end -->
# 岗位文档模板
> 使用说明:复制本模板创建具体岗位文档,删除说明性文字并填写真实内容。没有明确受众时不要创建文档;不得保留“待填写”后直接交付。
## 文档信息
| 字段 | 内容 |
|---|---|
| 文档名称 | |
| 适用对象 | 最终用户 / 管理员 / 运维 / 客服 / 集成人员 / 验收人员 / 其他 |
| 适用版本 | |
| 最后验证日期 | YYYY-MM-DD |
| 负责人 | |
| 可见范围 | 内部 / 指定客户 / 公开 |
| 相关产品或模块 | |
## 目的与适用范围
说明读者完成什么工作,以及本文包含和不包含什么。用岗位语言描述结果,不复制内部需求分析。
## 前置条件
- 所需权限:
- 所需环境或设备:
- 已完成的准备:
- 需要提前获得的信息:
不得在这里填写真实密码、令牌、个人数据或生产数据。
## 操作步骤
### 任务一:<明确的操作目标>
1. <执行动作>
2. <执行动作>
3. <执行动作>
**预期结果**:<读者可以观察到的成功结果>
**失败时**:<先检查什么;何时停止并联系支持>
每个独立任务重复以上结构。命令和界面名称应与适用版本一致;危险或不可逆操作必须在执行前给出醒目警告、影响和回退条件。
## 常见错误与恢复
| 现象或错误信息 | 可能原因 | 处理步骤 | 何时升级 |
|---|---|---|---|
| | | | |
只记录经过确认的原因和恢复方法。不要让外部读者执行内部调试、绕过权限或可能扩大损失的操作。
## 安全与权限
- 本岗位允许执行的操作:
- 明确禁止或需要审批的操作:
- 敏感信息处理规则:
- 数据、日志和截图脱敏要求:
- 删除、发布、迁移或其他高风险操作的确认要求:
## 已知限制
- 支持的环境和版本:
- 当前不支持的场景:
- 兼容性限制:
- 未验证的环境或步骤:
## 支持与升级处理
- 支持渠道:
- 服务时间或响应约定:
- 联系支持前需要收集的信息:
- 不得提交的信息:
- 需要升级到下一岗位或负责人的条件:
## 版本记录
| 日期 | 适用版本 | 变更内容 | 验证人 |
|---|---|---|---|
| | | | |
## 交付前检查
- [ ] 目标岗位能够理解术语和步骤。
- [ ] 前置条件、步骤与预期结果一一对应。
- [ ] 关键流程已按目标岗位视角验证。
- [ ] 常见错误、恢复方法和升级条件清楚。
- [ ] 没有内部工单、内部地址、敏感数据或无关源码细节。
- [ ] 适用版本、最后验证日期、负责人和可见范围已填写。
@@ -0,0 +1,88 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-10-需求记录与流转规则
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-10-%E9%9C%80%E6%B1%82%E8%AE%B0%E5%BD%95%E4%B8%8E%E6%B5%81%E8%BD%AC%E8%A7%84%E5%88%99.-
wiki_revision: d1f9c3198f76216fe8013f9862c26b59f9c179dc
synchronized_at: 2026-08-10T04:00:18Z
<!-- gitea-wiki-mirror:end -->
# 10 需求记录与流转规则
- 类型:开发流程优化
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:已完成
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/10
- Wiki 页面:Task-10-需求记录与流转规则
- Wiki revision:见本地镜像头
## 背景与目标
工单原本能够记录目标、方案和验收标准,但没有固定字段保存需求来源、关键原始表达和实施期间的需求变化,未来可能难以追溯用户最初目的以及最终方案变化原因。
本任务以最小方式补强需求可追踪性,同时保持 Gitea 工单、Wiki 和本地镜像的事实来源边界。
## 最终方案
- 单元任务模板增加“原始需求”:来源、提出时间、关键原话或脱敏摘要。
- 只保存表达用户目的、场景和限制所需的少量原话,不臆造用户原话。
- 目标、非目标、已确认方案、验收标准和文档影响构成正式任务需求。
- 增加“需求变化记录”,记录影响范围、接口、数据、风险或验收的变化日期、内容、原因和用户确认。
- 会改变已确认结果的变化仍须先更新工单并等待再次确认。
- 不复制完整聊天,不保存 Agent 内部推理,不写入敏感信息;敏感原话必须脱敏。
- 关键原始需求、正式任务需求、讨论和变化保存在 Gitea 工单,不导出全文。
- 长期产品需求、业务规则和系统边界进入 Wiki 主题页并导出 `docs/`。
- 完成结果进入 Wiki 任务归档并导出 `docs/task/`。
- Harness 检查任务模板、Agent 规则和 Wiki 章节。
- 没有新增需求数据库、同步脚本、Skill 或聊天抓取功能。
实施结果与已确认方案一致。
## 修改文件
- `AGENTS.md`:增加需求记录和事实来源边界。
- `.gitea/issue_template/task.md`:增加原始需求和需求变化记录。
- `dev_scripts/check_harness.py`:检查需求追踪字段和规则。
- `tests/test_harness_docs.py`:验证缺失需求追踪字段会被报告。
- `docs/01-workflow.md`:Development-Workflow Wiki 的只读镜像。
- `docs/03-business-rules-and-glossary.md`:Business-Rules-and-Glossary Wiki 的只读镜像。
- `wiki-docs.json`:登记本任务 Wiki 归档镜像。
- `docs/task/10-需求记录与流转规则.md`:本页的自动导出镜像。
## 验收结果
用户于 2026-08-10 明确验收通过。
| 验收标准 | 结果 |
|---|---|
| 模板记录来源、时间和关键原话 | 通过 |
| 模板记录需求变化四项信息 | 通过 |
| 工单保存正式任务需求和变化 | 通过 |
| 长期结论进入 Wiki 和 docs 镜像 | 通过 |
| 不保存完整聊天、内部推理和敏感信息 | 通过 |
| 不导出 Gitea 工单全文 | 通过 |
| Harness 检测字段缺失 | 通过 |
| 未增加脚本或聊天抓取功能 | 通过 |
| Wiki 先更新、确认再导出 | 通过 |
| 测试和严格检查 | 通过 |
| 实现和归档提交分离 | 通过 |
## 测试
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:21/21 通过。
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:归档前 19/19 映射一致;归档后重新检查 20/20。
- 执行命令:`python -m compileall -q dev_scripts tests`
- 结果:通过。
- 执行命令:`git diff --check`
- 结果:通过。
- **未验证部分**:未实现聊天自动抓取或 Gitea 工单全文导出,这些是已确认的非目标。
## 相关提交
- `353bd97` `feat: 增加需求记录规则 (#10)`
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
@@ -0,0 +1,80 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-11-交付文档指南与岗位文档模板
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-11-%E4%BA%A4%E4%BB%98%E6%96%87%E6%A1%A3%E6%8C%87%E5%8D%97%E4%B8%8E%E5%B2%97%E4%BD%8D%E6%96%87%E6%A1%A3%E6%A8%A1%E6%9D%BF.-
wiki_revision: 4e5c30641d9bcbc69d4c235f33ff89dd47259f63
synchronized_at: 2026-08-10T06:29:01Z
<!-- gitea-wiki-mirror:end -->
# 11 交付文档指南与岗位文档模板
- 类型:开发流程优化
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:待验收
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/11
- Wiki 页面:Task-11-交付文档指南与岗位文档模板
- Wiki revision:见本地镜像头
## 背景与目标
DevHarness 已覆盖开发维护文档,但缺少面向客户、最终用户及其他岗位的交付文档选择、内外边界、编写和验收规则,也没有可以复用的岗位文档模板。
本任务以最小范围建立交付文档闭环:只增加一份指南和一份通用模板,并把交付文档影响接入工单和新项目初始化流程,不预建没有明确读者的空白手册。
## 最终方案
- 新增“交付文档指南”,规定适用时机、受众与文档选择、内部与外部信息边界、编写维护流程和最小验收清单。
- 新增“岗位文档模板”,覆盖文档受众、适用版本、最后验证日期、负责人、可见范围、目的、前置条件、操作步骤、预期结果、常见错误与恢复、安全、限制、支持渠道和版本记录。
- 明确根据实际受众按需创建用户、管理员、运维、支持、集成或验收文档,不创建没有明确读者的空页面。
- 单元任务模板增加“交付文档影响”,要求选择无影响并说明原因,或列出新增、更新页面及目标岗位验证方式。
- 新项目初始化流程增加识别交付对象、可见范围、所需文档和外部信息边界的步骤。
- Home 增加交付指南和岗位模板入口,并将交付文档纳入 Wiki 长期文档事实来源。
- 两个新增页面显式映射到 `docs/delivery/`,Harness 将其纳入核心映射和章节检查。
- 未生成具体岗位手册、PDF、HTML 或发布包,未增加新脚本、框架和第三方依赖。
实施结果与已确认方案一致。
## 修改文件
- `.gitea/issue_template/task.md`:增加交付文档影响字段。
- `dev_scripts/check_harness.py`:检查新增核心页面、章节和工单字段。
- `tests/test_harness_docs.py`:验证缺少交付文档影响字段时能够报告错误。
- `wiki-docs.json`:登记交付指南、岗位模板和本任务归档的镜像映射。
- `docs/README.md`:Home Wiki 的只读镜像,增加交付文档入口。
- `docs/07-new-project-documentation-setup.md`:新项目初始化 Wiki 的只读镜像。
- `docs/delivery/README.md`:交付文档指南的只读镜像。
- `docs/delivery/audience-document-template.md`:岗位文档模板的只读镜像。
- `docs/task/11-交付文档指南与岗位文档模板.md`:本页的自动导出镜像。
## 验收结果
| 验收标准 | 结果 |
|---|---|
| 指南覆盖选择规则、内外边界、流程和验收 | 通过 |
| 岗位模板字段完整且可复用 | 通过 |
| 工单模板要求评估交付文档影响 | 通过 |
| 新项目初始化识别交付对象并按需建文档 | 通过 |
| Home 可进入新增页面 | 通过 |
| 两页镜像到 `docs/delivery/` 并可追踪 revision | 通过 |
| Harness 严格检查和单元测试 | 通过 |
| 实现提交已推送且归档单独提交 | 进行中:归档提交后回写工单 |
| 用户明确验收 | 待验收 |
## 测试
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:22/22 通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:归档前 22/22 映射一致;归档完成后重新检查。
- 执行命令:`git diff --check`
- 结果:通过。
- **未验证部分**:未创建具体产品的岗位文档,因此没有真实目标岗位或客户环境可执行验证;这属于已确认非目标,具体项目创建实际文档时必须补充目标岗位验证。
## 相关提交
- `3474870` `docs: 建立最小交付文档体系 (#11)`
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
@@ -0,0 +1,87 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-12-已有项目接入DevHarness指南
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-12-%E5%B7%B2%E6%9C%89%E9%A1%B9%E7%9B%AE%E6%8E%A5%E5%85%A5DevHarness%E6%8C%87%E5%8D%97.-
wiki_revision: e4ed7d5fd6a9ac5d4bf97c93f509182f2a8a8a4f
synchronized_at: 2026-08-10T10:00:07Z
<!-- gitea-wiki-mirror:end -->
# 12 已有项目接入 DevHarness 指南
- 类型:开发流程优化
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:已完成
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/12
- Wiki 页面:Task-12-已有项目接入DevHarness指南
- Wiki revision:见本地镜像头
## 背景与目标
现有“新项目文档初始化”面向从模板创建的新项目,没有完整覆盖已有项目中现存规则、文档、工单、Wiki、Git 历史、未完成任务和工作区改动的保护与增量接入方式。
本任务新增独立的已有项目接入指南,让 Claude、Codex 等 Agent 能先只读盘点、识别冲突、等待方案确认,再通过单元任务安全地分阶段接入 DevHarness。
## 最终方案
- 新增 `Existing-Project-Adoption-Guide`,明确与新项目初始化的适用边界。
- 接入前盘点 Agent 规则、README、文档、Wiki、工单、Git 历史、未提交改动、技术栈、命令、权限、安全及任务状态。
- 区分代码或系统事实、负责人确认规则、待确认假设、规则冲突和必须保留的无关改动。
- 明确保留 Git 历史、项目专用规则、现有任务状态和无关工作区改动。
- 禁止复制 DevHarness 历史归档、覆盖已有规则、把模板占位值当成项目事实或自动清理旧文档。
- 采用“确认差异方案 → 建立单元工单 → 接入规则和工单流程 → 确定长期文档事实来源 → 接入必要 Harness 工具 → 分阶段验证 → 提交和验收”的顺序。
- 为已有文档提供保留在 Git、迁移到 Wiki、合并、暂不迁移和停止维护五种明确状态。
- 提供可直接发送给 Agent 的“只分析”和“方案确认后实施”两段指令。
- 规定冲突、删除重命名、产品行为变化、重叠修改、权限不可用和事实不明时的停止条件。
- Home 增加指南入口和已有项目接入导航。
- 页面映射到 `docs/08-existing-project-adoption.md`,并纳入 Harness 核心映射和章节检查。
- 未增加自动迁移脚本,未修改任何实际业务项目,未改变事实来源边界。
实施结果与已确认方案一致。
## 修改文件
- `dev_scripts/check_harness.py`:增加已有项目接入指南的核心映射和章节检查。
- `tests/test_harness_docs.py`:验证指南属于必需核心页面。
- `wiki-docs.json`:登记指南和本任务归档镜像。
- `docs/README.md`:Home Wiki 只读镜像,增加已有项目接入入口。
- `docs/08-existing-project-adoption.md`:已有项目接入指南只读镜像。
- `docs/task/12-已有项目接入DevHarness指南.md`:本页的自动导出镜像。
## 验收结果
用户于 2026-08-10 明确验收通过。
| 验收标准 | 结果 |
|---|---|
| Wiki 存在独立的已有项目接入指南 | 通过 |
| 明确区分已有项目接入与新项目初始化 | 通过 |
| 覆盖只读盘点、内容保护、冲突处理和停止条件 | 通过 |
| 给出分阶段增量接入顺序 | 通过 |
| 包含可直接复制的分析和实施指令 | 通过 |
| 禁止复制历史归档和覆盖已有项目内容 | 通过 |
| Home 可进入指南 | 通过 |
| 页面具有显式映射和有效 revision | 通过 |
| Harness 严格检查和单元测试 | 通过 |
| 实现和归档提交已推送 | 通过 |
| 用户明确验收 | 通过 |
## 测试
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:23/23 通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:25/25 映射一致。
- 执行命令:`git diff --check`
- 结果:通过。
- 人工检查:两段 Agent 指令未授权覆盖、删除、重命名或自动迁移已有项目内容。
- **未验证部分**:未在真实业务仓库执行完整接入,因为修改实际项目属于本任务非目标;首次实际接入时应按指南建立独立工单并记录项目专用验证。
## 相关提交
- `0271a3e` `docs: 新增已有项目接入指南 (#12)`
- `eba8515` `docs: archive task #12`
- 验收状态提交哈希回写 Gitea 工单,避免归档自引用。
@@ -0,0 +1,68 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-13-多子项目与独立交付单元
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-13-%E5%A4%9A%E5%AD%90%E9%A1%B9%E7%9B%AE%E4%B8%8E%E7%8B%AC%E7%AB%8B%E4%BA%A4%E4%BB%98%E5%8D%95%E5%85%83.-
wiki_revision: 92b493258075739341d1591069f6c79b143965e7
synchronized_at: 2026-08-11T02:22:51Z
<!-- gitea-wiki-mirror:end -->
# 13 多子项目与独立交付单元
- 类型:需求
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:已完成
- 日期:2026-08-10
- 验收日期:2026-08-11
- 验收结果:用户明确验收通过
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/13
- Wiki 页面:Task-13-多子项目与独立交付单元
- Wiki revision:见本地镜像头
## 背景与目标
DevHarness 需要兼容一个 Git 仓库包含多个终端、服务或其他独立交付单元的项目。目标是在不引入 monorepo 框架、不自动拆仓的前提下,让项目档案、任务范围和接入指南明确每个子项目的职责、构建测试、版本发布、规则入口及共享契约边界。
## 最终方案
- Project-Profile 增加“子项目与交付单元”表格,记录职责、技术栈、构建测试、版本发布、规则入口和共享边界。
- 新项目初始化流程先识别全部子项目与独立交付单元,并指定共享契约的唯一事实来源。
- 已有项目接入指南增加多应用单仓库判断:技术栈不同本身不要求拆仓;按团队、权限、发布周期、仓库效率、复用关系和契约稳定性决定是否拆分。
- 单元任务模板增加“子项目影响”,强制记录单端或跨端范围、共享契约变化及各端验证。
- Harness 严格检查上述核心章节与模板字段,并增加对应单元测试。
- 未增加 monorepo 工具、自动拆仓或迁移、统一版本机制、CI 生成器,也未修改实际业务项目。
## 修改文件
- `.gitea/issue_template/task.md`:增加子项目影响字段。
- `dev_scripts/check_harness.py`:检查多子项目核心文档结构和任务模板字段。
- `tests/test_harness_docs.py`:增加任务模板子项目影响测试。
- `docs/00-project-profile.md`:镜像项目档案的子项目与交付单元定义。
- `docs/07-new-project-documentation-setup.md`:镜像新项目识别交付单元的初始化步骤。
- `docs/08-existing-project-adoption.md`:镜像多应用单仓库判断与最小规则。
## 验收结果
| 验收标准 | 结果 |
|---|---|
| 项目档案可记录每个子项目和独立交付单元 | 通过 |
| 新项目和已有项目指南说明多应用单仓库的判断规则 | 通过 |
| 单元任务模板明确子项目、跨项目和共享契约影响 | 通过 |
| 共享契约要求指定唯一事实来源和各端验证 | 通过 |
| 严格检查、单元测试和 Wiki 镜像检查通过 | 通过 |
| 不引入拆仓自动化或修改实际业务项目 | 通过 |
## 测试
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:24 项测试全部通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:归档前 25 份 Wiki 镜像全部一致。
- 人工示例检查:以 Client 与 Admin 两个交付单元填写职责、独立构建测试、版本发布和共享接口时,新增字段能够表达单端与跨端影响。
- **未验证部分**:未在真实多应用业务仓库执行接入或发布验证;该项不属于本工单范围。
## 相关提交
- `4e1db45` docs: support multi-project delivery units (#13)
+5 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-5-Simplify-Agents wiki_page: Task-5-Simplify-Agents
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-5-Simplify-Agents.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-5-Simplify-Agents.-
wiki_revision: 28df4129a9d4d90c42cd24b14a69ab0bcbd6e210 wiki_revision: 2096d9eee938c7680c1188dd6a5fbe490d1fd69c
synchronized_at: 2026-08-08T02:04:59Z synchronized_at: 2026-08-08T03:26:17Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 5 精简 AGENTS 中重复的解释性内容 # 5 精简 AGENTS 中重复的解释性内容
@@ -11,7 +11,7 @@ synchronized_at: 2026-08-08T02:04:59Z
- 类型:重构 - 类型:重构
- 所属 Epic:无 - 所属 Epic:无
- 所属 MVP / 版本:无 - 所属 MVP / 版本:无
- 状态:待验收 - 状态:已完成
- 日期:2026-08-08 - 日期:2026-08-08
- Gitea 工单:[opc/dev_harness#5](http://ilaer.eicp.net:8418/opc/dev_harness/issues/5) - Gitea 工单:[opc/dev_harness#5](http://ilaer.eicp.net:8418/opc/dev_harness/issues/5)
- Wiki 页面:Task-5-Simplify-Agents - Wiki 页面:Task-5-Simplify-Agents
@@ -38,6 +38,8 @@ AGENTS 中部分工单层级、风险示例和核心文档说明已经由 Wiki
## 验收结果 ## 验收结果
用户于 2026-08-08 明确验收通过。
| 验收标准 | 结果 | | 验收标准 | 结果 |
|---|---| |---|---|
| 所有安全和交付强制规则保留 | 通过 | | 所有安全和交付强制规则保留 | 通过 |
+5 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-6-优化ClaudeCode规则入口 wiki_page: Task-6-优化ClaudeCode规则入口
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-6-%E4%BC%98%E5%8C%96ClaudeCode%E8%A7%84%E5%88%99%E5%85%A5%E5%8F%A3.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-6-%E4%BC%98%E5%8C%96ClaudeCode%E8%A7%84%E5%88%99%E5%85%A5%E5%8F%A3.-
wiki_revision: 42be5a8acfb2e31f57efbb2d0809b89f3a7c0665 wiki_revision: 321e7016b2fcdf39f5bc6453310b233d00e81f07
synchronized_at: 2026-08-08T02:17:30Z synchronized_at: 2026-08-08T03:26:20Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 6 优化 Claude Code 规则入口 # 6 优化 Claude Code 规则入口
@@ -11,7 +11,7 @@ synchronized_at: 2026-08-08T02:17:30Z
- 类型:重构 - 类型:重构
- 所属 Epic:无 - 所属 Epic:无
- 所属 MVP / 版本:无 - 所属 MVP / 版本:无
- 状态:待验收 - 状态:已完成
- 日期:2026-08-08 - 日期:2026-08-08
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/6 - Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/6
- Wiki 页面:Task-6-优化ClaudeCode规则入口 - Wiki 页面:Task-6-优化ClaudeCode规则入口
@@ -46,6 +46,8 @@ synchronized_at: 2026-08-08T02:17:30Z
## 验收结果 ## 验收结果
用户于 2026-08-08 明确验收通过。
| 验收标准 | 结果 | | 验收标准 | 结果 |
|---|---| |---|---|
| 根目录文件名为 `CLAUDE.md` | 通过 | | 根目录文件名为 `CLAUDE.md` | 通过 |
+5 -3
View File
@@ -2,8 +2,8 @@
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-7-ClaudeCode模型路由 wiki_page: Task-7-ClaudeCode模型路由
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-7-ClaudeCode%E6%A8%A1%E5%9E%8B%E8%B7%AF%E7%94%B1.- wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-7-ClaudeCode%E6%A8%A1%E5%9E%8B%E8%B7%AF%E7%94%B1.-
wiki_revision: 21200c65b99ff5cd5a27cae6116ed8b56f938a28 wiki_revision: cfd37f7beab92133e1528104df9553e3e7835aff
synchronized_at: 2026-08-08T03:20:04Z synchronized_at: 2026-08-08T03:26:21Z
<!-- gitea-wiki-mirror:end --> <!-- gitea-wiki-mirror:end -->
# 7 Claude Code 模型路由 # 7 Claude Code 模型路由
@@ -11,7 +11,7 @@ synchronized_at: 2026-08-08T03:20:04Z
- 类型:开发规则优化 - 类型:开发规则优化
- 所属 Epic:无 - 所属 Epic:无
- 所属 MVP / 版本:无 - 所属 MVP / 版本:无
- 状态:待验收 - 状态:已完成
- 日期:2026-08-08 - 日期:2026-08-08
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/7 - Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/7
- Wiki 页面:Task-7-ClaudeCode模型路由 - Wiki 页面:Task-7-ClaudeCode模型路由
@@ -47,6 +47,8 @@ Claude Code 已通过 `CLAUDE.md` 导入共同开发规则,但没有说明 Opu
## 验收结果 ## 验收结果
用户于 2026-08-08 明确验收通过。
| 验收标准 | 结果 | | 验收标准 | 结果 |
|---|---| |---|---|
| 保留 `@AGENTS.md` 导入和共同规则来源说明 | 通过 | | 保留 `@AGENTS.md` 导入和共同规则来源说明 | 通过 |
+85
View File
@@ -0,0 +1,85 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-8-最小工单依赖规则
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-8-%E6%9C%80%E5%B0%8F%E5%B7%A5%E5%8D%95%E4%BE%9D%E8%B5%96%E8%A7%84%E5%88%99.-
wiki_revision: e9a890b18380bfbc02b7a292b8bed95cba8468a0
synchronized_at: 2026-08-10T04:00:14Z
<!-- gitea-wiki-mirror:end -->
# 8 最小工单依赖规则
- 类型:开发流程优化
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:已完成
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/8
- Wiki 页面:Task-8-最小工单依赖规则
- Wiki revision:见本地镜像头
## 背景与目标
项目已经允许建立后续工单,并定义了“待实施”和“阻塞”,但单元任务模板没有前置依赖和并行信息,Agent 实施前也没有明确的依赖检查步骤。
本任务采用最小实现:工单显式声明依赖,Agent 实施前人工检查,Harness 只检查模板字段存在,不把 DevHarness 扩展为自动项目管理系统。
## 最终方案
- 单元任务模板增加“依赖与并行”章节,记录前置工单、是否允许并行和原因。
- 建立新工单不要求其他工单完成,也不按工单编号限制实施顺序。
- Agent 开始修改前检查已声明的前置工单。
- 没有前置工单、前置已完成或明确允许并行时,可以进入“进行中”。
- 前置未完成且存在真实依赖时不得实施,工单保持“待实施”。
- 允许并行必须说明不存在实施冲突的原因。
- 已进入实施后遇到计划外、当前无法解除的问题时才使用“阻塞”。
- 依赖满足后,任务仍须拥有独立范围、提交、测试和回退方式。
- Harness 检查模板章节及三个字段,并增加缺失字段测试。
- 没有增加自动依赖图、联网查询、自动状态门禁或新脚本。
实施结果与已确认方案一致。
## 修改文件
- `AGENTS.md`:增加实施前依赖检查及状态边界。
- `.gitea/issue_template/task.md`:增加“依赖与并行”字段。
- `dev_scripts/check_harness.py`:检查模板依赖字段。
- `tests/test_harness_docs.py`:验证缺失依赖字段会被报告。
- `docs/01-workflow.md`:Development-Workflow Wiki 的只读镜像。
- `docs/03-business-rules-and-glossary.md`:Business-Rules-and-Glossary Wiki 的只读镜像。
- `wiki-docs.json`:登记本任务 Wiki 归档镜像。
- `docs/task/8-最小工单依赖规则.md`:本页的自动导出镜像。
## 验收结果
用户于 2026-08-10 明确验收通过。
| 验收标准 | 结果 |
|---|---|
| 模板包含依赖与并行三个字段 | 通过 |
| 建单不受其他未完成工单限制 | 通过 |
| 实施前检查声明的前置工单 | 通过 |
| 待实施和阻塞边界明确 | 通过 |
| 允许并行必须写明原因 | 通过 |
| Harness 检测字段缺失 | 通过 |
| 未增加自动门禁或新脚本 | 通过 |
| Wiki 先更新、确认再导出 | 通过 |
| 测试和严格检查 | 通过 |
## 测试
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:20/20 通过。
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:归档前 17/17 映射一致;归档后重新检查 18/18。
- 执行命令:`python -m compileall -q dev_scripts tests`
- 结果:通过。
- 执行命令:`git diff --check`
- 结果:通过。
- **未验证部分**:没有自动查询 Gitea 前置工单状态;这是已确认的非目标,依赖由 Agent 在实施前人工检查。
## 相关提交
- `a59e3b5` `feat: 增加最小工单依赖规则 (#8)`
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
@@ -0,0 +1,94 @@
<!-- gitea-wiki-mirror:start -->
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
wiki_page: Task-9-Agent自然语言快捷指令
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-9-Agent%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%BF%AB%E6%8D%B7%E6%8C%87%E4%BB%A4.-
wiki_revision: 6aedbcf63ad86892681c5f9226c4679dbbe16646
synchronized_at: 2026-08-10T04:00:17Z
<!-- gitea-wiki-mirror:end -->
# 9 Agent 自然语言快捷指令
- 类型:开发流程优化
- 所属 Epic:无
- 所属 MVP / 版本:无
- 状态:已完成
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/9
- Wiki 页面:Task-9-Agent自然语言快捷指令
- Wiki revision:见本地镜像头
## 背景与目标
Agent 过去能够结合上下文理解“建工单,做”,但仓库没有正式定义快捷指令的名称、允许操作和停止位置,不同平台或会话可能产生不同理解。
本任务定义一组共享的自然语言快捷指令,让 Claude Code、Codex 和维护者使用同一套工作流语义,同时保持方案确认、依赖、安全、Wiki 主源和人工验收门禁。
## 最终方案
正式定义以下 8 个快捷指令:
- `只分析`:只读检查并给出方案,停在等待确认。
- `建工单`:根据已确认方案创建工单,建单后停止。
- `执行工单 #N`:实施现有工单并完成提交、归档和证据,停在“待验收”。
- `建工单并做`:依次建单和执行;`建工单,做`、`建工单,做` 是等价表达,停在“待验收”。
- `继续工单 #N`:从首个未完成步骤继续,不重复仍然有效的检查。
- `检查工单 #N`:只读核对范围、验收、测试和证据,不自动修复。
- `同步文档`:Wiki → `docs/` 同步并检查,不修改 Wiki、不自动提交。
- `#N 验收通过`:仅在用户明确验收后完成验收归档、推送、父工单同步并关闭任务。
补充边界:
- 快捷指令只是自然语言别名,不绕过任何强制规则。
- 方案未确认时,建单或实施类指令停在方案确认。
- 前置依赖未满足且不允许并行时,实施类指令停在“待实施”。
- 除 `#N 验收通过` 外,不关闭待验收工单。
- Gitea 工单保留讨论过程,本地只保存 Wiki 最终任务归档镜像。
- Harness 检查 Wiki 章节和 8 个指令名称。
- 没有增加脚本、Skill、Slash Command 或自动编排器。
实施结果与已确认方案一致。
## 修改文件
- `AGENTS.md`:增加 8 个共享自然语言快捷指令和强制边界。
- `dev_scripts/check_harness.py`:检查 Wiki 章节和快捷指令名称。
- `tests/test_harness_docs.py`:调整 Agent 规则测试名称以覆盖全部必需规则。
- `docs/01-workflow.md`:Development-Workflow Wiki 的只读镜像。
- `wiki-docs.json`:登记本任务 Wiki 归档镜像。
- `docs/task/9-Agent自然语言快捷指令.md`:本页的自动导出镜像。
## 验收结果
用户于 2026-08-10 明确验收通过。
| 验收标准 | 结果 |
|---|---|
| 8 个指令有明确语义和停止位置 | 通过 |
| 建工单并做及逗号变体停在待验收 | 通过 |
| 只有明确验收指令会关闭工单 | 通过 |
| 只分析和检查工单默认只读 | 通过 |
| 同步文档不修改 Wiki、不自动提交 | 通过 |
| 不绕过确认、依赖、安全和验收 | 通过 |
| 未新增平台专用命令或脚本 | 通过 |
| Wiki 先更新并确认再导出 | 通过 |
| Harness、测试和镜像检查 | 通过 |
| 实现和归档提交分离 | 通过 |
## 测试
- 执行命令:`python -m unittest discover -s tests -v`
- 结果:20/20 通过。
- 执行命令:`python dev_scripts/check_harness.py --strict`
- 结果:通过。
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
- 结果:归档前 18/18 映射一致;归档后重新检查 19/19。
- 执行命令:`python -m compileall -q dev_scripts tests`
- 结果:通过。
- 执行命令:`git diff --check`
- 结果:通过。
- **未验证部分**:没有实现或运行平台专用 Slash Command、Skill 或自动编排器,这些是已确认的非目标。
## 相关提交
- `10e82d6` `feat: 定义 Agent 快捷指令 (#9)`
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
+125 -1
View File
@@ -43,6 +43,41 @@ class CoreDocumentTests(unittest.TestCase):
for page, path in CORE_PAGE_PATHS.items(): for page, path in CORE_PAGE_PATHS.items():
self.assertEqual(mappings.get(page), path) self.assertEqual(mappings.get(page), path)
def test_task_archives_are_not_core_mappings(self) -> None:
config = load_config()
self.assertFalse(
any(mapping.path.startswith("docs/task/") for mapping in config.mappings)
)
def test_existing_project_adoption_guide_is_core_document(self) -> None:
path = "docs/08-existing-project-adoption.md"
self.assertEqual(
CORE_PAGE_PATHS.get("Existing-Project-Adoption-Guide"),
path,
)
self.assertIn(path, CORE_DOCUMENT_REQUIREMENTS)
self.assertIn("## 可复制 Agent 指令", CORE_DOCUMENT_REQUIREMENTS[path])
def test_existing_project_adoption_requires_upgrade_process(self) -> None:
required = CORE_DOCUMENT_REQUIREMENTS[
"docs/08-existing-project-adoption.md"
]
self.assertIn("## 后续升级", required)
self.assertIn("### 升级步骤", required)
self.assertIn("### 可复制升级指令", required)
def test_project_profile_requires_dev_harness_baseline(self) -> None:
required = CORE_DOCUMENT_REQUIREMENTS["docs/00-project-profile.md"]
self.assertIn("## DevHarness 来源与基线", required)
def test_new_project_setup_requires_baseline_selection(self) -> None:
required = CORE_DOCUMENT_REQUIREMENTS[
"docs/07-new-project-documentation-setup.md"
]
self.assertIn("### 2. 选择建设基线", required)
self.assertIn("#### 判断案例", required)
self.assertIn("### 3. 识别子项目与交付单元", required)
def test_missing_or_wrong_core_mapping_is_reported(self) -> None: def test_missing_or_wrong_core_mapping_is_reported(self) -> None:
errors = core_mapping_errors({"Home": "docs/wrong.md"}) errors = core_mapping_errors({"Home": "docs/wrong.md"})
self.assertTrue(any("Home -> docs/README.md" in error for error in errors)) self.assertTrue(any("Home -> docs/README.md" in error for error in errors))
@@ -57,9 +92,98 @@ class TaskTemplateTests(unittest.TestCase):
check_task_template(errors) check_task_template(errors)
self.assertEqual(errors, []) self.assertEqual(errors, [])
def test_task_template_requires_delivery_document_impact(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 依赖与并行\n"
"- 前置工单:无 / #编号\n"
"- 是否允许与前置工单并行:是 / 否\n"
"- 原因:\n"
"## 原始需求\n"
"- 来源:用户对话 / Gitea / 其他\n"
"- 提出时间:\n"
"- 关键原话或脱敏摘要:\n"
"## 需求变化记录\n"
"| 日期 | 变化内容 | 原因 | 用户确认 |\n"
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 交付文档影响", errors)
self.assertIn(
"单元任务模板缺少:- [ ] 无交付文档影响,原因:",
errors,
)
def test_task_template_requires_subproject_impact(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text("## 基本信息\n", encoding="utf-8")
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 子项目影响", errors)
self.assertIn(
"单元任务模板缺少:- 是否跨子项目:是 / 否",
errors,
)
self.assertIn(
"单元任务模板缺少:- 是否修改共享接口或契约:是 / 否;唯一事实来源:",
errors,
)
def test_task_template_requires_dependency_fields(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 依赖与并行", errors)
self.assertIn("单元任务模板缺少:- 前置工单:无 / #编号", errors)
def test_task_template_requires_requirement_traceability(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
template = root / ".gitea" / "issue_template" / "task.md"
template.parent.mkdir(parents=True)
template.write_text(
"## 依赖与并行\n"
"- 前置工单:无 / #编号\n"
"- 是否允许与前置工单并行:是 / 否\n"
"- 原因:\n"
"## 文档影响\n"
"- [ ] 不影响长期文档,原因:\n"
"- [ ] 更新架构与代码地图\n"
"- [ ] 更新业务规则与术语\n"
"- [ ] 更新常见修改或故障排查\n",
encoding="utf-8",
)
errors: list[str] = []
check_task_template(errors, root)
self.assertIn("单元任务模板缺少:## 原始需求", errors)
self.assertIn("单元任务模板缺少:## 需求变化记录", errors)
class AgentRuleTests(unittest.TestCase): class AgentRuleTests(unittest.TestCase):
def test_agent_efficiency_sections_are_required(self) -> None: def test_required_agent_rules_are_present(self) -> None:
errors: list[str] = [] errors: list[str] = []
check_agent_efficiency_rules(errors) check_agent_efficiency_rules(errors)
self.assertEqual(errors, []) self.assertEqual(errors, [])
+157 -1
View File
@@ -12,7 +12,16 @@ from unittest.mock import Mock, patch
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "dev_scripts")) sys.path.insert(0, str(ROOT / "dev_scripts"))
from new_task_archive import build_archive, safe_title # noqa: E402 from new_task_archive import ( # noqa: E402
build_archive,
main as new_archive_main,
safe_title,
)
from export_task_archives import ( # noqa: E402
existing_task_mirrors,
export_task_archives,
task_target,
)
from wiki_docs import ( # noqa: E402 from wiki_docs import ( # noqa: E402
Config, Config,
Mapping, Mapping,
@@ -158,6 +167,153 @@ class ArchiveTests(unittest.TestCase):
self.assertIn("Task-12-login", result) self.assertIn("Task-12-login", result)
self.assertNotIn("YYYY-MM-DD", result) self.assertNotIn("YYYY-MM-DD", result)
@patch("new_task_archive.WikiClient")
def test_create_archive_does_not_change_core_mapping(self, client_class) -> None:
with tempfile.TemporaryDirectory() as directory:
config_path = Path(directory) / "wiki-docs.json"
original = json.dumps(
{
"schema_version": 1,
"gitea_url": "http://gitea.example",
"owner": "o",
"repository": "r",
"mappings": [
{"page": "Home", "path": "docs/README.md"}
],
}
)
config_path.write_text(original, encoding="utf-8")
client = client_class.return_value
client.list_pages.return_value = []
client.get_page.return_value = WikiPage(
title="Task-Archive-Template",
sub_url="Task-Archive-Template.-",
text="# <工单号> <标题>\nYYYY-MM-DD\n<链接>\n<页面名>\n",
revision="a" * 40,
html_url="http://gitea.example/wiki/template",
)
client.create_page.return_value = WikiPage(
title="Task-14-按需导出",
sub_url="Task-14.-",
text="# 14 按需导出\n",
revision="b" * 40,
html_url="http://gitea.example/wiki/task-14",
)
with patch.object(
sys,
"argv",
[
"new_task_archive.py",
"14",
"按需导出",
"--config",
str(config_path),
],
):
result = new_archive_main()
self.assertEqual(config_path.read_text(encoding="utf-8"), original)
self.assertEqual(result, 0)
client.create_page.assert_called_once()
def test_task_target_uses_stable_safe_name(self) -> None:
with tempfile.TemporaryDirectory() as directory:
target = task_target("Task-14-修复:导出", Path(directory))
self.assertEqual(target.name, "14-修复-导出.md")
def test_existing_mirror_keeps_historical_custom_filename(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
path = root / "docs" / "task" / "2-初级维护者文档体系.md"
path.parent.mkdir(parents=True)
page = WikiPage(
title="Task-2-Junior-Maintainer-Docs",
sub_url="Task-2-Junior-Maintainer-Docs.-",
text="# 2 文档\n",
revision="c" * 40,
html_url="http://gitea.example/wiki/task-2",
)
path.write_text(render_mirror(page), encoding="utf-8")
mirrors = existing_task_mirrors(root)
self.assertEqual(
mirrors["Task-2-Junior-Maintainer-Docs"].name,
"2-初级维护者文档体系.md",
)
@patch("export_task_archives.dirty_paths", return_value=[])
def test_incremental_export_skips_same_revision(self, _dirty) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
path = root / "docs" / "task" / "14-按需导出.md"
path.parent.mkdir(parents=True)
page = WikiPage(
title="Task-14-按需导出",
sub_url="Task-14.-",
text="# 14 按需导出\n",
revision="d" * 40,
html_url="http://gitea.example/wiki/task-14",
)
path.write_text(render_mirror(page), encoding="utf-8")
client = Mock()
client.list_pages.return_value = [
{
"title": page.title,
"sub_url": page.sub_url,
"last_commit": {"sha": page.revision},
}
]
messages = export_task_archives(client, root=root)
self.assertTrue(messages[0].startswith("跳过:"))
client.get_page_from_metadata.assert_not_called()
@patch(
"export_task_archives.dirty_paths",
return_value=[" M docs/task/14-按需导出.md"],
)
def test_export_stops_before_wiki_read_when_task_mirror_is_dirty(
self, _dirty
) -> None:
client = Mock()
with self.assertRaisesRegex(WikiDocsError, "未提交改动"):
export_task_archives(client)
client.list_pages.assert_not_called()
@patch("export_task_archives.dirty_paths", return_value=[])
def test_full_export_reads_all_and_never_deletes_extra_file(self, _dirty) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
task_dir = root / "docs" / "task"
task_dir.mkdir(parents=True)
extra = task_dir / "99-历史快照.md"
extra_page = WikiPage(
title="Task-99-历史快照",
sub_url="Task-99.-",
text="# 99 历史快照\n",
revision="e" * 40,
html_url="http://gitea.example/wiki/task-99",
)
extra.write_text(render_mirror(extra_page), encoding="utf-8")
page = WikiPage(
title="Task-14-按需导出",
sub_url="Task-14.-",
text="# 14 按需导出\n",
revision="f" * 40,
html_url="http://gitea.example/wiki/task-14",
)
client = Mock()
metadata = {
"title": page.title,
"sub_url": page.sub_url,
"last_commit": {"sha": page.revision},
}
client.list_pages.return_value = [metadata]
client.get_page_from_metadata.return_value = page
messages = export_task_archives(client, export_all=True, root=root)
exported = root / "docs" / "task" / "14-按需导出.md"
self.assertTrue(exported.is_file())
self.assertTrue(extra.is_file())
self.assertTrue(messages[0].startswith("已导出:"))
client.get_page_from_metadata.assert_called_once_with(metadata, page.title)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+12 -28
View File
@@ -40,37 +40,21 @@
"page": "New-Project-Documentation-Setup", "page": "New-Project-Documentation-Setup",
"path": "docs/07-new-project-documentation-setup.md" "path": "docs/07-new-project-documentation-setup.md"
}, },
{
"page": "Existing-Project-Adoption-Guide",
"path": "docs/08-existing-project-adoption.md"
},
{
"page": "Delivery-Documentation-Guide",
"path": "docs/delivery/README.md"
},
{
"page": "Audience-Document-Template",
"path": "docs/delivery/audience-document-template.md"
},
{ {
"page": "Task-Archive-Template", "page": "Task-Archive-Template",
"path": "docs/templates/task-archive.md" "path": "docs/templates/task-archive.md"
},
{
"page": "Task-1-Wiki-文档主源",
"path": "docs/task/1-Wiki-文档主源.md"
},
{
"page": "Task-2-Junior-Maintainer-Docs",
"path": "docs/task/2-初级维护者文档体系.md"
},
{
"page": "Task-3-Dev-Scripts-Rename",
"path": "docs/task/3-dev_scripts目录重命名.md"
},
{
"page": "Task-4-Agent-Efficiency-Scope",
"path": "docs/task/4-Agent效率与范围控制.md"
},
{
"page": "Task-5-Simplify-Agents",
"path": "docs/task/5-精简AGENTS重复说明.md"
},
{
"page": "Task-6-优化ClaudeCode规则入口",
"path": "docs/task/6-优化ClaudeCode规则入口.md"
},
{
"page": "Task-7-ClaudeCode模型路由",
"path": "docs/task/7-ClaudeCode模型路由.md"
} }
] ]
} }