Compare commits
38
Commits
3aa73fcb1e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
947a06846e | ||
|
|
fe99ca52e3 | ||
|
|
a959fc385d | ||
|
|
d1f55f9df3 | ||
|
|
f23c2cf81f | ||
|
|
fb9229a74e | ||
|
|
4e1db4558c | ||
|
|
105328ee2e | ||
|
|
eba851561a | ||
|
|
0271a3ebd7 | ||
|
|
eb92fb3033 | ||
|
|
3474870499 | ||
|
|
4e9f2e1380 | ||
|
|
e9c9fb415b | ||
|
|
353bd97212 | ||
|
|
48404070d0 | ||
|
|
10e82d61e6 | ||
|
|
f652cbd46c | ||
|
|
a59e3b5374 | ||
|
|
d1136c2bc5 | ||
|
|
98df3a2dc5 | ||
|
|
3bfe752a92 | ||
|
|
c6f353cbbb | ||
|
|
2adb30ada2 | ||
|
|
2509d9ec2e | ||
|
|
c9f1bc8832 | ||
|
|
874ca626b3 | ||
|
|
e29b9e4391 | ||
|
|
d3df733fb0 | ||
|
|
e72b161fa8 | ||
|
|
1d3104c002 | ||
|
|
51278fa47f | ||
|
|
1c998673f3 | ||
|
|
c69c0fde03 | ||
|
|
5c432da6df | ||
|
|
c8ccb62a98 | ||
|
|
b09658ee15 | ||
|
|
250b0555e4 |
@@ -5,6 +5,29 @@
|
||||
- 所属 MVP / 版本:#
|
||||
- 阶段:
|
||||
|
||||
## 依赖与并行
|
||||
|
||||
- 前置工单:无 / #编号
|
||||
- 是否允许与前置工单并行:是 / 否
|
||||
- 原因:
|
||||
|
||||
## 子项目影响
|
||||
|
||||
<!-- 单应用项目填写唯一交付单元;多应用单仓库必须明确单端、跨端和共享契约影响。 -->
|
||||
|
||||
- 仅影响的子项目 / 交付单元:
|
||||
- 是否跨子项目:是 / 否
|
||||
- 是否修改共享接口或契约:是 / 否;唯一事实来源:
|
||||
- 各子项目需要执行的验证:
|
||||
|
||||
## 原始需求
|
||||
|
||||
- 来源:用户对话 / Gitea / 其他
|
||||
- 提出时间:
|
||||
- 关键原话或脱敏摘要:
|
||||
|
||||
<!-- 只保留表达用户目的、场景和限制所需的内容;不要复制完整聊天、内部推理或敏感信息。 -->
|
||||
|
||||
## 要解决什么
|
||||
|
||||
<!-- 描述现状和目标。缺陷需要写清复现步骤、实际结果和期望结果。 -->
|
||||
@@ -22,6 +45,34 @@
|
||||
|
||||
- <!-- 填写 -->
|
||||
|
||||
## 需求变化记录
|
||||
|
||||
<!-- 只记录影响范围、接口、数据、风险或验收的变化;没有变化时填写“无”。 -->
|
||||
|
||||
| 日期 | 变化内容 | 原因 | 用户确认 |
|
||||
|---|---|---|---|
|
||||
| | | | 是 / 否 |
|
||||
|
||||
## 文档影响
|
||||
|
||||
<!-- 至少选择一项;不影响长期文档时必须写明原因。 -->
|
||||
|
||||
- [ ] 不影响长期文档,原因:
|
||||
- [ ] 更新项目档案或本地开发与验证
|
||||
- [ ] 更新架构与代码地图
|
||||
- [ ] 更新业务规则与术语
|
||||
- [ ] 更新常见修改或故障排查
|
||||
- [ ] 更新其他 Wiki 页面:
|
||||
|
||||
## 交付文档影响
|
||||
|
||||
<!-- 至少选择一项;面向用户、客户或其他岗位的行为、配置、部署、接口或支持方式变化时,必须列出受众和页面。 -->
|
||||
|
||||
- [ ] 无交付文档影响,原因:
|
||||
- [ ] 更新已有交付文档,受众与页面:
|
||||
- [ ] 新增交付文档,受众与页面:
|
||||
- [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式:
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] <!-- 填写 -->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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`。目录越深的规则越具体,但不得削弱上级安全规则。
|
||||
|
||||
@@ -30,31 +30,82 @@
|
||||
## 3. 需求到实施
|
||||
|
||||
1. 先复述目标,阅读相关代码、日志和文档,区分事实与假设。
|
||||
2. 给出目标、非目标、方案、影响范围、风险、回退方式和验证方法。
|
||||
2. 给出目标、非目标、方案、影响范围、风险、回退方式、验证方法和文档影响。
|
||||
3. 方案没有得到用户明确确认前,只做只读诊断和方案整理,不实施正式代码。
|
||||
4. 方案确认后,先建立单元任务工单,再修改代码。
|
||||
5. 开始实施前检查分支和工作区,明确哪些现有改动不属于本任务。
|
||||
6. 严格按工单范围实现;新发现的问题先记录,不顺手混入当前任务。
|
||||
7. 执行与风险相称的测试,把关键结果和未验证部分更新到工单。
|
||||
8. 长期文档必须先修改 Wiki、读取确认,再运行 `python scripts/sync_wiki_docs.py` 导出本地镜像;不得直接编辑 `docs/` 后反向覆盖 Wiki。
|
||||
5. 建立新工单不要求其他工单已经完成;开始实施前检查工单声明的前置工单。真实依赖未满足时保持“待实施”,允许并行时必须写明原因。
|
||||
6. 开始实施前检查分支和工作区,明确哪些现有改动不属于本任务。
|
||||
7. 严格按工单范围实现;新发现的问题先记录,不顺手混入当前任务。
|
||||
8. 执行与风险相称的测试,把关键结果和未验证部分更新到工单。实施过程中出现计划外、当前无法解除的问题时才标记“阻塞”。
|
||||
9. 长期核心文档必须先修改 Wiki、读取确认,再运行 `python dev_scripts/sync_wiki_docs.py` 导出本地镜像;任务归档默认只更新 Wiki,不自动导出本地。不得直接编辑镜像后反向覆盖 Wiki。
|
||||
|
||||
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 提交和验收归档要求。
|
||||
|
||||
#### 严格控制范围
|
||||
|
||||
- 默认严格按用户确认的目标和单元任务范围执行,不主动扩展相邻问题。
|
||||
- 除非任务目标、仓库强制规则或已发现的真实阻塞需要,不新增额外文档、辅助脚本、备份文件、框架、重构或扩展性设计。
|
||||
- 不执行与本次验收无关的验证;安全检查、受影响范围测试、回归测试和仓库规定的闭环验证不属于“额外验证”。
|
||||
- 新发现的相邻问题最多用一句话提示或记录到独立工单,不自动修复或混入当前提交。
|
||||
|
||||
#### 渐进执行和修复
|
||||
|
||||
- 完成已知必要的安全与前置检查后,优先执行能够产生真实反馈的最小命令。
|
||||
- 一次执行后先处理首个可定位、可行动的真实错误,不同时猜测并修改多个可能原因。
|
||||
- 采用“执行 → 查看错误 → 最小修复 → 从失败点继续或按需重跑”的闭环。
|
||||
- 不在真实证据出现前堆叠与已知风险无关的预防性检查。
|
||||
- 涉及凭据、权限、安全、数据、迁移、并发、删除、发布或不可逆操作时,必须先完成相应前置检查,不得通过试错获取风险反馈。
|
||||
|
||||
#### 复用已验证事实
|
||||
|
||||
- 在同一任务和同一环境状态下,已经通过的路由、连接、恢复和环境检查不重复执行。
|
||||
- 只有会话、环境、代码、配置、依赖、凭据、远端状态或关键前提发生变化时才重新检查。
|
||||
- 代码修改后,受影响测试和最终验收必须重新执行;提交前工作区检查、推送前远端分支检查不得因为之前通过而省略。
|
||||
- Skill 和平台规则是否需要重新读取,按当前 Agent 平台和任务触发规则执行,不自行跳过。
|
||||
|
||||
#### 明确停止条件
|
||||
|
||||
- 完成用户确认的验收标准和仓库规定的必要闭环后立即停止,不主动继续优化。
|
||||
- “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。
|
||||
- 未影响当前验收的相邻问题只提示或建单,不顺手处理。
|
||||
|
||||
## 4. 工单层级
|
||||
|
||||
```text
|
||||
Epic:完整产品目标和长期路线
|
||||
└── MVP:第一个可交付版本
|
||||
└── 单元任务:唯一的实施单位
|
||||
```
|
||||
|
||||
- Epic 维护总体目标、范围、路线、风险和所有任务索引。
|
||||
- MVP 维护首个可交付范围、阶段、集成风险和任务清单。
|
||||
- 单元任务记录具体方案、修改范围、验收标准、过程和测试结果。
|
||||
- 父工单只维护 `- [ ] #编号` 或 `- [x] #编号` 的索引和汇总,不复制子工单全文。
|
||||
- 单元任务是唯一正式实施单位,记录方案、范围、验收标准、过程和测试结果。
|
||||
- Epic 和 MVP 只维护目标、风险、汇总及 `- [ ] #编号` / `- [x] #编号` 子工单索引,不复制单元任务全文。
|
||||
- 新任务先建单元工单,再把编号同步到所属 MVP 和 Epic。
|
||||
|
||||
工单模板位于 `.gitea/issue_template/`。
|
||||
- 详细层级、状态和模板入口见 [开发工作流](docs/01-workflow.md) 与 [业务规则和术语](docs/03-business-rules-and-glossary.md)。
|
||||
|
||||
## 5. 实施中的变化
|
||||
|
||||
@@ -75,17 +126,16 @@ Epic:完整产品目标和长期路线
|
||||
|
||||
## 7. 完成、验收和归档
|
||||
|
||||
1. 实现完成后逐项检查验收标准,并提交代码。
|
||||
2. 更新单元工单:最终方案、方案差异、测试结果、提交哈希和遗留问题。
|
||||
3. 工单保持“待验收”,用户没有明确验收通过前不得关闭。
|
||||
4. 运行 `python scripts/new_task_archive.py <编号> "<短标题>"`,先在 Wiki 创建任务归档,再登记映射并导出 `docs/task/<编号>-<短标题>.md` 镜像。
|
||||
5. 读取确认 Wiki 页面,运行 `python scripts/sync_wiki_docs.py --check` 校验镜像。
|
||||
6. 归档镜像单独提交,例如:`docs: 归档任务 #123`。
|
||||
7. 把 Wiki 页面、revision、镜像路径和提交哈希回写工单。
|
||||
8. 用户验收通过后关闭单元工单,并同步更新 MVP 和 Epic。
|
||||
1. 逐项完成验收、测试和实现提交,并把最终方案、差异、结果、提交及遗留问题写回工单。
|
||||
2. 工单保持“待验收”,用户没有明确验收通过前不得关闭。
|
||||
3. 运行 `python dev_scripts/new_task_archive.py <编号> "<短标题>"`,只创建 Wiki 任务归档,不登记或导出本地镜像。
|
||||
4. 读取确认 Wiki,运行 `python dev_scripts/sync_wiki_docs.py --check` 检查核心镜像,并把任务归档页面、revision 和提交哈希写回工单。只有用户明确提出时才增量或全量导出任务归档。
|
||||
5. 用户验收通过后关闭单元工单,并同步更新 MVP 和 Epic。
|
||||
|
||||
MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才能关闭 MVP。Epic 的全部范围完成后才能关闭 Epic。
|
||||
|
||||
详细归档顺序和字段见 [开发工作流](docs/01-workflow.md)。
|
||||
|
||||
## 8. 可维护性
|
||||
|
||||
- 优先使用直白、常见的实现;不要为了少写几行引入晦涩技巧。
|
||||
@@ -95,6 +145,19 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才
|
||||
- Wiki 文档先写结论和用途,再写步骤;示例命令应可直接复制,本地 `docs/` 由同步工具生成。
|
||||
- 面向初级维护者说明从哪里开始读、怎样运行和怎样验证。
|
||||
|
||||
### 修改风险
|
||||
|
||||
- 低风险修改可由初级程序员在 Agent 协助下处理;接口、配置、依赖、跨模块逻辑和数据结构由 Agent 实现并验证。
|
||||
- 权限、安全、并发、迁移、支付、删除数据和不可逆操作属于高风险;高风险修改必须停止,由 Agent 分析并等待人工确认。
|
||||
- 风险按影响范围判断,不按代码行数判断;示例见 [常见修改指南](docs/05-common-changes.md)。
|
||||
|
||||
### 文档影响
|
||||
|
||||
- 每个单元任务必须在工单中选择“无长期文档影响并说明原因”或列出需要更新的 Wiki 页面。
|
||||
- 启动、测试、部署、排错命令,模块入口、目录职责、主要调用路径,配置、API、数据结构、状态、业务规则、安全边界、日志位置发生变化时,必须更新对应 Wiki。
|
||||
- 普通内部重构只有在入口、行为、配置和验证方式均未改变时,才可以记录为不影响长期文档。
|
||||
- 必需核心页面及结构以 `python dev_scripts/check_harness.py --strict` 和 [新项目文档初始化](docs/07-new-project-documentation-setup.md) 为准;稳定文档与任务归档的分工见 [开发工作流](docs/01-workflow.md)。
|
||||
|
||||
## 9. 引导提交例外
|
||||
|
||||
从本模板创建全新仓库时,Gitea 远端和工单尚不存在,允许一次不带工单号的初始引导提交。该提交只能包含仓库骨架、Harness 规则和远端配置准备,不能包含产品功能。
|
||||
@@ -105,7 +168,9 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才
|
||||
|
||||
<!-- 在项目初始化时填写不可违反的技术、安全和业务约束。复杂子项目请在其目录中增加 AGENTS.md。 -->
|
||||
|
||||
- 长期开发文档以 Gitea Wiki 为事实来源,`docs/` 是显式映射生成的只读镜像。
|
||||
- Wiki 与镜像的固定顺序是:修改 Wiki → 读取确认 → 导出 `docs` → 校验差异 → 提交镜像。
|
||||
- 长期开发文档以 Gitea Wiki 为事实来源,`docs/` 默认保存显式映射生成的核心只读镜像;`docs/task/` 是人工按需快照,可能不完整或不是最新状态。
|
||||
- 核心 Wiki 与镜像的固定顺序是:修改 Wiki → 读取确认 → 导出核心 `docs` → 校验差异 → 提交镜像。
|
||||
- 任务归档默认只保存在 Wiki;`导出任务归档` 或 `导出全部任务归档` 必须由用户明确提出,且不得自动传播删除或重命名。
|
||||
- 同步配置只允许写入 `docs/` 下的 Markdown;发现镜像有未提交修改时必须停止。
|
||||
- Gitea 凭据只通过进程环境或 MCP 安全配置提供,不得写入仓库。
|
||||
- `dev_scripts/` 只存放 DevHarness 自身工具;业务项目的通用脚本必须使用独立目录,不得混放。
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
# Claude Code 项目入口
|
||||
|
||||
本仓库的完整开发规则以 [AGENTS.md](AGENTS.md) 为唯一事实来源。
|
||||
@AGENTS.md
|
||||
|
||||
Claude Code 开始任何工作前,必须按顺序阅读:
|
||||
## Claude Code 专用说明
|
||||
|
||||
1. 根目录的 `AGENTS.md`;
|
||||
2. Gitea Wiki 的项目档案;Wiki 不可用时读取 `docs/00-project-profile.md` 镜像并明确其 revision;
|
||||
3. 任务涉及目录中更具体的 `AGENTS.md`;
|
||||
4. 当前 Gitea 工单及其父级 MVP、Epic 工单。
|
||||
- 上方导入的 `AGENTS.md` 是所有编码 Agent 的共同规则事实来源,Claude Code 必须完整遵守。
|
||||
- 本文件只记录 Claude Code 特有的模型路由、工具和 Agent 协作规则。
|
||||
- 共同规则变化时只修改 `AGENTS.md`,不要在本文件重复维护。
|
||||
|
||||
必须遵守以下入口规则:
|
||||
## 模型路由
|
||||
|
||||
- 方案经用户确认并建立单元任务工单后,才能修改产品代码。
|
||||
- 只修改当前工单范围内的文件,保留用户已有和无关的改动。
|
||||
- 实现、测试、Git 提交、待验收、Wiki 任务归档、导出本地镜像和关闭工单的顺序不得跳过。
|
||||
- 长期文档先修改 Wiki,再导出 `docs/`;不得直接编辑镜像作为最终结果。
|
||||
- 未经用户明确验收,不得关闭工单。
|
||||
- 不得把密码、令牌、Cookie、私钥或生产数据写入代码、日志、工单和文档。
|
||||
- 目标、范围和修改位置已经明确时,默认使用 Sonnet 分析、建单和实施。
|
||||
- 需求模糊、根因不明,或涉及跨模块架构、安全、权限、并发、迁移和不可逆操作时,使用 Opus 或 `opusplan` 制定方案。
|
||||
- Opus 输出方案后必须等待用户确认;确认后由 Sonnet 根据方案创建工单并实施。
|
||||
- Haiku 只用于范围明确的只读任务,例如查找代码入口、读取项目文档、提取日志事实和整理调用关系。
|
||||
- 不让 Haiku 决定最终根因、技术方案、风险等级或验收结论。
|
||||
- 当前模型足以完成任务时不升级模型,也不为了形式固定依次调用三个模型。
|
||||
|
||||
不要在本文件复制完整工作流。流程发生变化时只更新 `AGENTS.md`,本文件保持为 Claude Code 的稳定入口,防止两套规则不一致。
|
||||
## Agent 交接
|
||||
|
||||
- Opus 向 Sonnet 交接目标、非目标、事实、假设、方案、修改范围、风险、回退方式和验收标准。
|
||||
- Haiku 向主 Agent 交接结论、证据位置和仍不确定的内容,不返回与任务无关的大段原文。
|
||||
- Sonnet 严格按照已确认方案和工单实施;发现范围变化时返回主流程重新确认。
|
||||
- 不同 Agent 复用仍然有效的检查结果;会话、环境或关键前提变化时才重新检查。
|
||||
|
||||
## Haiku 只读约束
|
||||
|
||||
- Haiku 子 Agent 只允许使用读取、搜索和只读代码图谱工具。
|
||||
- 禁止 Haiku 修改文件、创建或更新工单、提交 Git、更新 Wiki 或执行具有副作用的命令。
|
||||
- 只读必须通过子 Agent 工具权限实现,不能只依赖提示语;未配置只读权限时不得调用 Haiku 处理项目内容。
|
||||
|
||||
@@ -14,14 +14,14 @@ DevHarness 是一个以 Gitea 工单管理任务过程、以 Gitea Wiki 管理
|
||||
-> Agent 实现并测试
|
||||
-> 提交代码并更新工单
|
||||
-> 人工验收
|
||||
-> 先归档 Wiki,再导出 docs/task 镜像
|
||||
-> 归档 Wiki;任务快照仅在人工提出时导出
|
||||
-> 关闭工单并更新父工单
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 复制或克隆本仓库,并修改仓库名称。
|
||||
2. 在 Gitea Wiki 填写项目档案,再运行 `python scripts/sync_wiki_docs.py` 导出 [本地镜像](docs/00-project-profile.md)。
|
||||
2. 按 [新项目文档初始化](docs/07-new-project-documentation-setup.md) 在 Gitea Wiki 填写项目档案和核心主题页。
|
||||
3. 把项目不可违反的安全规则写入根目录或子项目的 `AGENTS.md`。
|
||||
4. 创建 Gitea 远端仓库并推送当前引导提交。
|
||||
5. 配置 `wiki-docs.json` 的页面映射;读取 Wiki 可匿名访问或使用 `GITEA_TOKEN`,写 Wiki 必须通过环境变量提供令牌。
|
||||
@@ -29,7 +29,7 @@ DevHarness 是一个以 Gitea 工单管理任务过程、以 Gitea Wiki 管理
|
||||
7. 开始产品代码前运行:
|
||||
|
||||
```powershell
|
||||
python scripts/check_harness.py --strict
|
||||
python dev_scripts/check_harness.py --strict
|
||||
```
|
||||
|
||||
新仓库在 Gitea 尚未建立前允许一次不关联工单的引导提交。远端和工单系统配置完成后,所有改变程序行为的工作都必须先有单元任务工单。
|
||||
@@ -42,18 +42,20 @@ CLAUDE.md Claude Code 的规则入口
|
||||
.gitea/issue_template/ Epic、MVP、单元任务工单模板
|
||||
docs/00-project-profile.md Wiki 项目档案的只读镜像
|
||||
docs/01-workflow.md Wiki 开发工作流的只读镜像
|
||||
docs/02-07*.md 代码地图、业务、验证、修改、排错和初始化镜像
|
||||
docs/templates/task-archive.md Wiki 任务归档模板的只读镜像
|
||||
docs/task/ Wiki 任务归档页的只读镜像
|
||||
wiki-docs.json Wiki 页面到本地镜像的显式映射
|
||||
scripts/check_harness.py 模板和归档的最小自检
|
||||
scripts/sync_wiki_docs.py 单向导出或检查 Wiki 镜像
|
||||
scripts/new_task_archive.py 先创建 Wiki 任务归档,再导出镜像
|
||||
docs/task/ 人工按需导出的 Wiki 任务归档快照
|
||||
wiki-docs.json 核心 Wiki 页面到本地镜像的显式映射
|
||||
dev_scripts/check_harness.py 模板和归档的最小自检
|
||||
dev_scripts/sync_wiki_docs.py 单向导出或检查 Wiki 镜像
|
||||
dev_scripts/new_task_archive.py 只创建 Wiki 任务归档
|
||||
dev_scripts/export_task_archives.py 人工增量或全量导出任务归档
|
||||
```
|
||||
|
||||
## 设计原则
|
||||
|
||||
- 人决定目标、范围和验收结果,Agent 负责检查、实现和验证。
|
||||
- 工单记录实施过程,Wiki 保存长期有效的最终事实,`docs/` 只保存可审查的镜像。
|
||||
- 工单记录实施过程,Wiki 保存长期有效的最终事实,`docs/` 默认保存核心镜像;任务归档快照按需导出。
|
||||
- 一个单元工单只解决一个可独立测试和回退的问题。
|
||||
- 实现提交与归档提交分开,便于审查与追溯。
|
||||
- 实现提交与必要的核心文档镜像提交分开,便于审查与追溯。
|
||||
- 凭据、个人数据和生产数据不得进入代码、工单或归档。
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
"""检查 DevHarness 必需文件、核心文档和任务归档的基本结构。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from wiki_docs import WikiDocsError, load_config, parse_mirror
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
CORE_PAGE_PATHS = {
|
||||
"Home": "docs/README.md",
|
||||
"Project-Profile": "docs/00-project-profile.md",
|
||||
"Development-Workflow": "docs/01-workflow.md",
|
||||
"Architecture-and-Code-Map": "docs/02-architecture-and-code-map.md",
|
||||
"Business-Rules-and-Glossary": "docs/03-business-rules-and-glossary.md",
|
||||
"Local-Development-and-Verification": (
|
||||
"docs/04-local-development-and-verification.md"
|
||||
),
|
||||
"Common-Changes": "docs/05-common-changes.md",
|
||||
"Troubleshooting": "docs/06-troubleshooting.md",
|
||||
"New-Project-Documentation-Setup": (
|
||||
"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",
|
||||
}
|
||||
CORE_DOCUMENT_REQUIREMENTS = {
|
||||
"docs/README.md": (
|
||||
"## 第一次阅读",
|
||||
"## 五分钟开始",
|
||||
"## 简单修改从哪里开始",
|
||||
"## 事实来源",
|
||||
),
|
||||
"docs/00-project-profile.md": (
|
||||
"## 基本信息",
|
||||
"## DevHarness 来源与基线",
|
||||
"## 子项目与交付单元",
|
||||
"## 技术栈与运行环境",
|
||||
"## 阅读入口",
|
||||
"## 常用命令",
|
||||
"## 环境、配置与凭据",
|
||||
),
|
||||
"docs/01-workflow.md": (
|
||||
"## 面向初级维护者的修改边界",
|
||||
"## 每个任务的文档影响",
|
||||
"## 需求记录与流转",
|
||||
"## 稳定文档与任务归档",
|
||||
"## 自然语言快捷指令",
|
||||
"## 效率与范围控制",
|
||||
"### 严格控制范围",
|
||||
"### 渐进执行和修复",
|
||||
"### 复用已验证事实",
|
||||
"### 明确停止条件",
|
||||
),
|
||||
"docs/02-architecture-and-code-map.md": (
|
||||
"## 项目定位",
|
||||
"## 代码地图",
|
||||
"## 两条主要执行路径",
|
||||
"## 不可破坏的边界",
|
||||
),
|
||||
"docs/03-business-rules-and-glossary.md": (
|
||||
"## 核心术语",
|
||||
"## 工单状态",
|
||||
"## 稳定业务规则",
|
||||
"## 新项目需要补充什么",
|
||||
),
|
||||
"docs/04-local-development-and-verification.md": (
|
||||
"## 环境要求",
|
||||
"## 第一次运行",
|
||||
"## 常用调试方式",
|
||||
"## 完成修改前",
|
||||
),
|
||||
"docs/05-common-changes.md": (
|
||||
"## 风险分级",
|
||||
"## 修改 Wiki 文案",
|
||||
"## 调整 Harness 检查",
|
||||
"## 看懂 Agent 的修改",
|
||||
),
|
||||
"docs/06-troubleshooting.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 = (
|
||||
"AGENTS.md",
|
||||
"CLAUDE.md",
|
||||
"README.md",
|
||||
"docs/00-project-profile.md",
|
||||
"docs/01-workflow.md",
|
||||
"docs/templates/task-archive.md",
|
||||
*CORE_DOCUMENT_REQUIREMENTS,
|
||||
"wiki-docs.json",
|
||||
"dev_scripts/wiki_docs.py",
|
||||
"dev_scripts/sync_wiki_docs.py",
|
||||
"dev_scripts/export_task_archives.py",
|
||||
".gitea/issue_template/epic.md",
|
||||
".gitea/issue_template/mvp.md",
|
||||
".gitea/issue_template/task.md",
|
||||
)
|
||||
ARCHIVE_HEADINGS = (
|
||||
"## 背景与目标",
|
||||
"## 最终方案",
|
||||
"## 修改文件",
|
||||
"## 验收结果",
|
||||
"## 测试",
|
||||
"## 相关提交",
|
||||
)
|
||||
|
||||
|
||||
def check_required_files(errors: list[str]) -> None:
|
||||
for relative_path in REQUIRED_FILES:
|
||||
if not (ROOT / relative_path).is_file():
|
||||
errors.append(f"缺少必需文件:{relative_path}")
|
||||
|
||||
|
||||
def check_project_profile(errors: list[str], warnings: list[str], strict: bool) -> None:
|
||||
profile = ROOT / "docs" / "00-project-profile.md"
|
||||
if not profile.is_file():
|
||||
return
|
||||
if "<填写" in profile.read_text(encoding="utf-8"):
|
||||
message = "项目档案仍有未填写内容"
|
||||
(errors if strict else warnings).append(message)
|
||||
|
||||
|
||||
def check_archives(errors: list[str]) -> None:
|
||||
task_dir = ROOT / "docs" / "task"
|
||||
for path in task_dir.glob("*.md"):
|
||||
if not re.match(r"^\d+-.+\.md$", path.name):
|
||||
errors.append(f"归档文件名不符合 <编号>-<标题>.md:{path.name}")
|
||||
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:
|
||||
if heading not in content:
|
||||
errors.append(f"{path.name} 缺少章节:{heading}")
|
||||
if "**未验证部分**:" not in content:
|
||||
errors.append(f"{path.name} 没有记录未验证部分")
|
||||
|
||||
|
||||
def missing_sections(content: str, required: tuple[str, ...]) -> list[str]:
|
||||
return [section for section in required if section not in content]
|
||||
|
||||
|
||||
def check_core_documents(errors: list[str], root: Path = ROOT) -> None:
|
||||
"""检查初级维护者所需主题页的固定结构。"""
|
||||
|
||||
for relative_path, required in CORE_DOCUMENT_REQUIREMENTS.items():
|
||||
path = root / relative_path
|
||||
if not path.is_file():
|
||||
continue
|
||||
try:
|
||||
_, body = parse_mirror(path.read_text(encoding="utf-8"))
|
||||
except (OSError, UnicodeDecodeError, WikiDocsError):
|
||||
continue
|
||||
for section in missing_sections(body, required):
|
||||
errors.append(f"{relative_path} 缺少核心章节:{section}")
|
||||
|
||||
|
||||
def check_task_template(errors: list[str], root: Path = ROOT) -> None:
|
||||
path = root / ".gitea" / "issue_template" / "task.md"
|
||||
if not path.is_file():
|
||||
return
|
||||
content = path.read_text(encoding="utf-8")
|
||||
required = (
|
||||
"## 依赖与并行",
|
||||
"- 前置工单:无 / #编号",
|
||||
"- 是否允许与前置工单并行:是 / 否",
|
||||
"- 原因:",
|
||||
"## 子项目影响",
|
||||
"- 仅影响的子项目 / 交付单元:",
|
||||
"- 是否跨子项目:是 / 否",
|
||||
"- 是否修改共享接口或契约:是 / 否;唯一事实来源:",
|
||||
"- 各子项目需要执行的验证:",
|
||||
"## 原始需求",
|
||||
"- 来源:用户对话 / Gitea / 其他",
|
||||
"- 提出时间:",
|
||||
"- 关键原话或脱敏摘要:",
|
||||
"## 需求变化记录",
|
||||
"| 日期 | 变化内容 | 原因 | 用户确认 |",
|
||||
"## 文档影响",
|
||||
"- [ ] 不影响长期文档,原因:",
|
||||
"- [ ] 更新架构与代码地图",
|
||||
"- [ ] 更新业务规则与术语",
|
||||
"- [ ] 更新常见修改或故障排查",
|
||||
"## 交付文档影响",
|
||||
"- [ ] 无交付文档影响,原因:",
|
||||
"- [ ] 更新已有交付文档,受众与页面:",
|
||||
"- [ ] 新增交付文档,受众与页面:",
|
||||
"- [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式:",
|
||||
)
|
||||
for section in missing_sections(content, required):
|
||||
errors.append(f"单元任务模板缺少:{section}")
|
||||
|
||||
|
||||
def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None:
|
||||
path = root / "AGENTS.md"
|
||||
if not path.is_file():
|
||||
return
|
||||
content = path.read_text(encoding="utf-8")
|
||||
required = (
|
||||
"### 效率与范围控制",
|
||||
"#### 严格控制范围",
|
||||
"#### 渐进执行和修复",
|
||||
"#### 复用已验证事实",
|
||||
"#### 明确停止条件",
|
||||
"单元任务是唯一正式实施单位",
|
||||
"高风险修改必须停止",
|
||||
"用户没有明确验收通过前不得关闭",
|
||||
"长期核心文档必须先修改 Wiki",
|
||||
"提交只包含当前工单相关文件",
|
||||
"### 自然语言快捷指令",
|
||||
"`只分析`",
|
||||
"`建工单`",
|
||||
"`执行工单 #N`",
|
||||
"`建工单并做`",
|
||||
"`继续工单 #N`",
|
||||
"`检查工单 #N`",
|
||||
"`同步文档`",
|
||||
"`导出任务归档`",
|
||||
"`导出全部任务归档`",
|
||||
"`#N 验收通过`",
|
||||
"### 需求记录与流转",
|
||||
"不得臆造用户原话",
|
||||
"不复制完整聊天",
|
||||
"Gitea 工单全文不导出到仓库",
|
||||
)
|
||||
for section in missing_sections(content, required):
|
||||
errors.append(f"AGENTS.md 缺少:{section}")
|
||||
|
||||
|
||||
def check_claude_code_entry(errors: list[str], root: Path = ROOT) -> None:
|
||||
"""检查 Claude Code 入口直接复用共同 Agent 规则。"""
|
||||
|
||||
path = root / "CLAUDE.md"
|
||||
if not path.is_file():
|
||||
return
|
||||
content = path.read_text(encoding="utf-8")
|
||||
lines = {line.strip() for line in content.splitlines()}
|
||||
if "@AGENTS.md" not in lines:
|
||||
errors.append("CLAUDE.md 缺少独立的 @AGENTS.md 导入")
|
||||
required = (
|
||||
"共同规则事实来源",
|
||||
"只记录 Claude Code 特有",
|
||||
"只修改 `AGENTS.md`",
|
||||
"## 模型路由",
|
||||
"## Agent 交接",
|
||||
"## Haiku 只读约束",
|
||||
"当前模型足以完成任务时不升级模型",
|
||||
"Opus 输出方案后必须等待用户确认",
|
||||
"不让 Haiku 决定最终根因",
|
||||
"只读必须通过子 Agent 工具权限实现",
|
||||
)
|
||||
for section in missing_sections(content, required):
|
||||
errors.append(f"CLAUDE.md 缺少:{section}")
|
||||
|
||||
|
||||
def core_mapping_errors(configured_mappings: dict[str, str]) -> list[str]:
|
||||
errors: list[str] = []
|
||||
for page, expected_path in CORE_PAGE_PATHS.items():
|
||||
if configured_mappings.get(page) != expected_path:
|
||||
errors.append(
|
||||
f"核心 Wiki 页面映射缺失或路径错误:{page} -> {expected_path}"
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def check_wiki_mirrors(errors: list[str]) -> None:
|
||||
"""检查核心映射与镜像头;任务快照由 check_archives 单独检查。"""
|
||||
|
||||
try:
|
||||
config = load_config()
|
||||
except WikiDocsError as exc:
|
||||
errors.append(str(exc))
|
||||
return
|
||||
|
||||
configured_mappings = {mapping.page: mapping.path for mapping in config.mappings}
|
||||
errors.extend(core_mapping_errors(configured_mappings))
|
||||
|
||||
mapped_paths = {mapping.path for mapping in config.mappings}
|
||||
actual_paths = {
|
||||
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):
|
||||
errors.append(f"docs 中存在未登记的 Wiki 镜像:{path}")
|
||||
|
||||
for mapping in config.mappings:
|
||||
path = ROOT / mapping.path
|
||||
if not path.is_file():
|
||||
errors.append(f"缺少 Wiki 镜像:{mapping.path}")
|
||||
continue
|
||||
try:
|
||||
metadata, _ = parse_mirror(path.read_text(encoding="utf-8"))
|
||||
except (OSError, UnicodeDecodeError, WikiDocsError) as exc:
|
||||
errors.append(f"Wiki 镜像无效 {mapping.path}:{exc}")
|
||||
continue
|
||||
if metadata.get("generated") != "true (请先修改 Gitea Wiki,禁止直接编辑本文件)":
|
||||
errors.append(f"{mapping.path} 没有只读镜像标记")
|
||||
if metadata.get("wiki_page") != mapping.page:
|
||||
errors.append(f"{mapping.path} 的 wiki_page 与映射不一致")
|
||||
revision = metadata.get("wiki_revision", "")
|
||||
if re.fullmatch(r"[0-9a-f]{40,64}", revision) is None:
|
||||
errors.append(f"{mapping.path} 的 wiki_revision 无效")
|
||||
if not metadata.get("synchronized_at"):
|
||||
errors.append(f"{mapping.path} 缺少 synchronized_at")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="检查 DevHarness 项目结构")
|
||||
parser.add_argument(
|
||||
"--strict",
|
||||
action="store_true",
|
||||
help="项目档案有占位内容时返回失败",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
errors: list[str] = []
|
||||
warnings: list[str] = []
|
||||
check_required_files(errors)
|
||||
check_project_profile(errors, warnings, args.strict)
|
||||
check_wiki_mirrors(errors)
|
||||
check_core_documents(errors)
|
||||
check_task_template(errors)
|
||||
check_agent_efficiency_rules(errors)
|
||||
check_claude_code_entry(errors)
|
||||
check_archives(errors)
|
||||
|
||||
for warning in warnings:
|
||||
print(f"警告:{warning}")
|
||||
for error in errors:
|
||||
print(f"错误:{error}")
|
||||
|
||||
if errors:
|
||||
print(f"检查失败:{len(errors)} 个问题")
|
||||
return 1
|
||||
print("DevHarness 检查通过")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -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())
|
||||
@@ -1,4 +1,4 @@
|
||||
"""先在 Gitea Wiki 创建任务归档,再登记并导出本地镜像。"""
|
||||
"""只在 Gitea Wiki 创建任务归档;本地镜像由人工按需导出。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -9,12 +9,9 @@ from pathlib import Path
|
||||
|
||||
from wiki_docs import (
|
||||
DEFAULT_CONFIG,
|
||||
Mapping,
|
||||
WikiClient,
|
||||
WikiDocsError,
|
||||
append_mapping,
|
||||
load_config,
|
||||
sync_all,
|
||||
)
|
||||
|
||||
|
||||
@@ -43,7 +40,7 @@ def build_archive(
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="在 Gitea Wiki 创建任务归档并导出 docs/task 镜像"
|
||||
description="在 Gitea Wiki 创建任务归档,不自动导出本地镜像"
|
||||
)
|
||||
parser.add_argument("issue_number", help="Gitea 工单号,例如 123")
|
||||
parser.add_argument("title", help="简短任务标题")
|
||||
@@ -61,15 +58,9 @@ def main() -> int:
|
||||
try:
|
||||
config = load_config(Path(args.config).resolve())
|
||||
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)
|
||||
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
|
||||
issue_url = (
|
||||
f"{config.gitea_url}/{config.owner}/{config.repository}/issues/"
|
||||
@@ -83,17 +74,12 @@ def main() -> int:
|
||||
content,
|
||||
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:
|
||||
print(f"错误:{exc}")
|
||||
return 1
|
||||
|
||||
print(f"已创建 Wiki:{page.html_url}")
|
||||
for message in messages:
|
||||
print(message)
|
||||
print(f"已登记镜像:{local_path}")
|
||||
print("未导出本地任务归档;需要时运行 export_task_archives.py")
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""从 Gitea Wiki 单向导出本地 docs 镜像。"""
|
||||
"""从 Gitea Wiki 单向导出配置中的核心 docs 镜像。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -9,7 +9,7 @@ from wiki_docs import DEFAULT_CONFIG, WikiClient, WikiDocsError, load_config, sy
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="从 Gitea Wiki 单向同步 docs 镜像")
|
||||
parser = argparse.ArgumentParser(description="从 Gitea Wiki 单向同步核心 docs 镜像")
|
||||
parser.add_argument(
|
||||
"--check", action="store_true", help="只检查 Wiki 与镜像是否一致,不写文件"
|
||||
)
|
||||
@@ -210,6 +210,14 @@ class WikiClient:
|
||||
raise WikiDocsError(
|
||||
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")
|
||||
page = self._request(
|
||||
"GET",
|
||||
@@ -218,20 +226,22 @@ class WikiClient:
|
||||
f"{quote(sub_url, safe='%')}",
|
||||
)
|
||||
if not isinstance(page, dict):
|
||||
raise WikiDocsError(f"Wiki 页面响应格式无效:{page_name}")
|
||||
raise WikiDocsError(f"Wiki 页面响应格式无效:{resolved_name}")
|
||||
encoded_content = page.get("content_base64")
|
||||
if not isinstance(encoded_content, str):
|
||||
raise WikiDocsError(f"Wiki 页面没有 content_base64:{page_name}")
|
||||
raise WikiDocsError(f"Wiki 页面没有 content_base64:{resolved_name}")
|
||||
try:
|
||||
text = base64.b64decode(encoded_content, validate=True).decode("utf-8")
|
||||
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")
|
||||
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}")
|
||||
raise WikiDocsError(f"Wiki 页面缺少 revision:{resolved_name}")
|
||||
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 = (
|
||||
f"{self.config.gitea_url}/{quote(self.config.owner, 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]:
|
||||
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(
|
||||
["git", "status", "--porcelain", "--", *paths],
|
||||
cwd=root,
|
||||
@@ -329,6 +346,17 @@ def _write_atomic(path: Path, content: str) -> None:
|
||||
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]:
|
||||
if not path.is_file():
|
||||
return [f"缺少镜像:{mapping.path}"]
|
||||
+64
-17
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Project-Profile
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Project-Profile.-
|
||||
wiki_revision: 845266496196a4fc33462dfda779d0f899fa4c18
|
||||
synchronized_at: 2026-08-07T15:53:58Z
|
||||
wiki_revision: 16456d6ed083197759d553b1033e3e5c8a6b8932
|
||||
synchronized_at: 2026-08-16T11:49:52Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 项目档案
|
||||
@@ -16,17 +16,56 @@ synchronized_at: 2026-08-07T15:53:58Z
|
||||
|---|---|
|
||||
| 项目名称 | DevHarness |
|
||||
| 一句话目标 | 提供以 Gitea 工单、Wiki 和 Git 为事实来源的 AI 辅助开发工作流模板 |
|
||||
| 主要使用者 | 项目负责人、Claude/Codex Agent、接手简单维护的初级程序员 |
|
||||
| Gitea 地址 | http://ilaer.eicp.net:8418 |
|
||||
| 仓库 | `opc/dev_harness` |
|
||||
| 默认分支 | `main` |
|
||||
| 主要维护者 | `ila` |
|
||||
| 文档适用范围 | 默认分支当前版本;具体镜像 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 仓库;是否拆仓应根据团队、权限、发布周期、仓库效率、复用关系和共享接口稳定性判断。
|
||||
|
||||
跨子项目接口或契约必须指定唯一事实来源,并说明各交付单元的兼容范围和验证命令。不得在多个页面维护互不确认的“权威版本”。
|
||||
|
||||
## 技术栈与运行环境
|
||||
|
||||
| 部分 | 技术 | 规则文件 |
|
||||
|---|---|---|
|
||||
| Harness 规则和模板 | Markdown、Gitea | `AGENTS.md` |
|
||||
| Harness 规则和模板 | Markdown、Gitea 1.25 | `AGENTS.md` |
|
||||
| Wiki 镜像与结构检查 | Python 3 标准库 | `AGENTS.md` |
|
||||
| 主要开发环境 | Windows、PowerShell、Git | `AGENTS.md` |
|
||||
|
||||
本项目不需要安装第三方 Python 包。复制到业务项目后,必须把真实语言、框架、版本和支持平台写入本节。
|
||||
|
||||
## 阅读入口
|
||||
|
||||
- 新人入口:Home。
|
||||
- 代码入口:[架构与代码地图](Architecture-and-Code-Map.-)。
|
||||
- 业务边界:[业务规则与术语](Business-Rules-and-Glossary.-)。
|
||||
- 运行验证:[本地开发与验证](Local-Development-and-Verification.-)。
|
||||
- 简单维护:[常见修改指南](Common-Changes.-)。
|
||||
- 错误定位:[故障排查](Troubleshooting)。
|
||||
|
||||
## 常用命令
|
||||
|
||||
@@ -34,11 +73,14 @@ synchronized_at: 2026-08-07T15:53:58Z
|
||||
|
||||
| 用途 | 命令 | 预期结果 |
|
||||
|---|---|---|
|
||||
| 检查模板结构 | `python scripts/check_harness.py --strict` | 输出“DevHarness 检查通过” |
|
||||
| 查看工作区 | `git status --short --branch` | 显示分支且没有无关修改 |
|
||||
| 检查模板结构 | `python dev_scripts/check_harness.py --strict` | 输出“DevHarness 检查通过” |
|
||||
| 运行单元测试 | `python -m unittest discover -s tests -v` | 所有测试通过 |
|
||||
| 导出 Wiki 镜像 | `python scripts/sync_wiki_docs.py` | 映射页面写入 `docs/` |
|
||||
| 检查 Wiki 镜像 | `python scripts/sync_wiki_docs.py --check` | 输出镜像与 Wiki 一致 |
|
||||
| 创建任务归档 | `python scripts/new_task_archive.py 123 "修复登录超时"` | 先创建 Wiki 归档页,再登记并导出本地镜像 |
|
||||
| 导出核心 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py` | 核心页面写入 `docs/`,不处理任务归档 |
|
||||
| 检查核心 Wiki 镜像 | `python dev_scripts/sync_wiki_docs.py --check` | 输出核心镜像与 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` | 读取并导出全部线上任务归档 |
|
||||
|
||||
## 目录边界
|
||||
|
||||
@@ -46,23 +88,28 @@ synchronized_at: 2026-08-07T15:53:58Z
|
||||
|---|---|---|
|
||||
| `.gitea/issue_template/` | Gitea 工单模板 | 凭据、任务最终归档 |
|
||||
| `docs/` | Wiki 自动导出的只读镜像 | 人工直接维护的长期文档 |
|
||||
| `docs/task/` | Wiki 任务归档页的只读镜像 | 讨论过程和临时方案 |
|
||||
| `scripts/` | Harness 检查、Wiki 同步和归档工具 | 产品功能代码 |
|
||||
| `docs/task/` | 人工按需导出的 Wiki 任务归档只读快照,可能不是完整历史 | 讨论过程和临时方案 |
|
||||
| `dev_scripts/` | Harness 检查、Wiki 同步和归档工具 | 产品功能代码 |
|
||||
| `tests/` | Harness 工具自动化测试 | 生产数据 |
|
||||
|
||||
## 环境与凭据
|
||||
## 环境、配置与凭据
|
||||
|
||||
- Wiki 同步配置:仓库根目录 `wiki-docs.json`。
|
||||
- 核心 Wiki 同步配置:仓库根目录 `wiki-docs.json`;任务归档不逐页登记,由按需导出工具动态发现。
|
||||
- Gitea 地址可由配置提供,也可通过 `GITEA_URL` 覆盖。
|
||||
- Gitea Personal Access Token 仅通过 `GITEA_TOKEN` 环境变量提供,不写入仓库。
|
||||
- Token 至少需要读取仓库权限;创建 Wiki 任务归档时还需要写仓库权限。
|
||||
- 日志和构建产物:本项目不持久化运行日志;Python 缓存不提交。
|
||||
- Gitea PAT 仅通过 `GITEA_TOKEN` 或 MCP 安全配置提供,不写入仓库。
|
||||
- Token 至少需要读取仓库权限;创建或更新 Wiki 时还需要写仓库权限。
|
||||
- 配置示例:`wiki-docs.json` 只保存非敏感仓库信息。
|
||||
- 日志:本项目不持久化运行日志,命令行错误是主要诊断信息。
|
||||
- 测试数据:只使用测试构造的字符串、路径和模拟响应,不使用生产数据。
|
||||
- 构建产物:Python 缓存和临时文件不提交。
|
||||
|
||||
## 项目专用验收要求
|
||||
|
||||
- 长期文档必须先更新 Wiki,再导出本地镜像。
|
||||
- 长期核心文档必须先更新 Wiki,再导出本地镜像;任务归档默认只保存在 Wiki,用户明确要求时才增量或全量导出。
|
||||
- 镜像必须包含来源页面、revision 和同步时间。
|
||||
- 页面删除、重命名和映射变更必须人工确认。
|
||||
- `python scripts/check_harness.py --strict` 必须通过。
|
||||
- 新增核心文档时必须更新 Home、显式映射和 Harness 检查。
|
||||
- 代码入口、命令、配置、业务规则或排错方式变化时必须评估文档影响。
|
||||
- `python dev_scripts/check_harness.py --strict` 必须通过。
|
||||
- `python -m unittest discover -s tests -v` 必须通过。
|
||||
- 未执行或无法覆盖的验证必须记录到工单。
|
||||
|
||||
+159
-13
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Development-Workflow
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Development-Workflow.-
|
||||
wiki_revision: ae9f9aac5df77f1e3e1c2a34bd00c849c1f63cbf
|
||||
synchronized_at: 2026-08-07T15:54:03Z
|
||||
wiki_revision: 3f50238b637bc2f896ceab6caa5ab8ab1ded2a4b
|
||||
synchronized_at: 2026-08-16T11:18:52Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 开发工作流
|
||||
@@ -37,6 +37,23 @@ synchronized_at: 2026-08-07T15:54:03Z
|
||||
|
||||
每个单元任务都应目标单一,能够独立测试、提交和回退。
|
||||
|
||||
#### 依赖与并行
|
||||
|
||||
建立新工单不要求其他工单已经完成,也不按工单编号限制实施顺序。每个单元任务必须声明:
|
||||
|
||||
- 前置工单,没有时填写“无”;
|
||||
- 是否允许与未完成的前置工单并行;
|
||||
- 判断可以或不可以并行的原因。
|
||||
|
||||
开始修改前,Agent 检查工单声明的前置工单:
|
||||
|
||||
- 没有前置工单,或前置工单已经完成,可以进入“进行中”;
|
||||
- 前置工单未完成且存在实际依赖时,不得开始实施,工单保持“待实施”;
|
||||
- 与前置工单没有实施冲突、允许并行时,可以进入“进行中”,但必须在工单写明原因;
|
||||
- 已经进入实施后出现计划外、当前无法解除的问题,才使用“阻塞”。
|
||||
|
||||
依赖不改变单元任务边界。依赖满足后,该任务仍须拥有独立的范围、提交、测试和回退方式。
|
||||
|
||||
### 3. 实施
|
||||
|
||||
Agent 检查分支和工作区,只修改工单范围内的文件。发现新问题时先记录到工单;如果不影响当前验收,则另建工单,不扩大当前任务。
|
||||
@@ -50,13 +67,13 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新
|
||||
- Git 提交哈希;
|
||||
- 相关 Wiki 页面及 revision。
|
||||
|
||||
长期文档遵循唯一顺序:
|
||||
长期核心文档遵循唯一顺序:
|
||||
|
||||
```text
|
||||
修改 Wiki → 读取确认 → 导出 docs → 校验差异 → 提交镜像
|
||||
修改 Wiki → 读取确认 → 导出核心 docs → 校验差异 → 提交镜像
|
||||
```
|
||||
|
||||
不得先编辑 `docs/` 再反向覆盖 Wiki。
|
||||
任务归档默认只更新 Wiki,不自动导出到 `docs/task/`。不得先编辑本地镜像再反向覆盖 Wiki。
|
||||
|
||||
### 4. 待验收
|
||||
|
||||
@@ -64,25 +81,154 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新
|
||||
|
||||
### 5. 归档和关闭
|
||||
|
||||
使用以下命令在 Wiki 创建任务归档页、登记显式映射并导出本地镜像:
|
||||
使用以下命令只在 Wiki 创建任务归档页:
|
||||
|
||||
```powershell
|
||||
python 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/`,不提供反向同步。
|
||||
- 核心页面映射保存在 `wiki-docs.json`;普通同步只处理这些核心长期文档。
|
||||
- 任务归档不逐页登记映射,由按需导出工具根据 `Task-<编号>-<标题>` 动态发现;已有镜像优先按镜像头匹配原页面。
|
||||
- 所有同步和导出只实现 Wiki → `docs/`,不提供反向同步。
|
||||
- 镜像头必须记录页面名、页面地址、revision 和同步时间。
|
||||
- 已跟踪镜像存在未提交改动时,同步必须停止;确认改动来源后再处理。
|
||||
- `--check` 只检查,不写文件;页面缺失、revision 不一致或正文不一致均失败。
|
||||
- 核心同步的 `--check` 只检查核心镜像,不要求线上任务归档全部存在于本地。
|
||||
- 已经导出的任务镜像仍必须具有来源页面、revision 和同步时间,并通过 Harness 格式检查。
|
||||
- 页面删除和重命名不会自动传播,必须先更新工单并人工确认映射变化。
|
||||
- Wiki 更新成功而导出失败时,在工单记录部分完成状态,不得把任务标为完成。
|
||||
- 与具体代码版本强绑定的接口或迁移资料可直接随代码维护,但必须在 Wiki 提供入口或适用版本说明。
|
||||
|
||||
## 面向初级维护者的修改边界
|
||||
|
||||
| 风险 | 示例 | 处理方式 |
|
||||
|---|---|---|
|
||||
| 低 | 文案、简单校验、查询条件、独立 UI、小范围回归 Bug | 初级程序员可在 Agent 协助下理解、修改和验证 |
|
||||
| 中 | API、配置、依赖、跨模块逻辑、数据结构 | 由 Agent 实现,程序员检查差异并执行验证 |
|
||||
| 高 | 权限、安全、并发、迁移、支付、删除数据、不可逆操作 | 停止修改,由 Agent 分析并等待人工确认 |
|
||||
|
||||
风险由影响范围决定,不按代码行数判断。
|
||||
|
||||
## 每个任务的文档影响
|
||||
|
||||
单元任务必须明确选择:
|
||||
|
||||
- 不影响长期文档,并说明原因;
|
||||
- 更新项目档案或运行验证;
|
||||
- 更新架构与代码地图;
|
||||
- 更新业务规则与术语;
|
||||
- 更新常见修改或故障排查;
|
||||
- 新增或调整其他 Wiki 页面。
|
||||
|
||||
以下变化必须更新相关 Wiki:
|
||||
|
||||
- 启动、测试、部署或排错命令变化;
|
||||
- 模块入口、目录职责或主要调用路径变化;
|
||||
- 配置项、API、数据结构或状态变化;
|
||||
- 业务规则、安全边界或权限变化;
|
||||
- 日志位置、错误定位或常见处理方式变化。
|
||||
|
||||
普通内部重构如果入口、行为、配置和验证方式均未改变,可以记录“不影响长期文档”及原因。
|
||||
|
||||
## 需求记录与流转
|
||||
|
||||
聊天用于分析和确认,不是正式需求的长期事实来源。创建单元任务工单时,Agent 应记录:
|
||||
|
||||
- 原始需求的来源和提出时间;
|
||||
- 能表达用户目的、使用场景和限制的少量关键原话;
|
||||
- 整理后的目标、非目标、确认方案、验收标准和文档影响;
|
||||
- 实施期间影响范围、接口、数据、风险或验收的需求变化,以及变化原因和用户确认。
|
||||
|
||||
只摘录完成追踪所需的内容,不复制完整聊天,不保存 Agent 内部推理,不写入密码、令牌、个人数据或生产数据。包含敏感信息的原话必须删除敏感部分或改写为脱敏摘要。
|
||||
|
||||
需求按以下边界流转:
|
||||
|
||||
| 内容 | 事实来源 | 本地镜像 |
|
||||
|---|---|---|
|
||||
| 关键原始需求、确认后的单次任务需求 | Gitea 单元任务工单 | 无 |
|
||||
| 讨论、决定和需求变化 | Gitea 工单正文或评论 | 无 |
|
||||
| 长期有效的产品需求、业务规则和系统边界 | 对应 Gitea Wiki 主题页 | `docs/` |
|
||||
| 完成后的实现、验证和遗留问题 | Wiki 任务归档 | 人工按需导出的 `docs/task/` 快照(可能不完整) |
|
||||
|
||||
任务产生长期结论时,先更新对应 Wiki 主题页,再导出本地镜像。Gitea 工单全文不导出到仓库,避免形成第二份任务过程记录。
|
||||
|
||||
## 稳定文档与任务归档
|
||||
|
||||
- Home、项目档案、代码地图、业务规则、开发验证、常见修改和故障排查描述项目现在怎样工作。
|
||||
- 工单和 Wiki 任务归档解释某次为什么修改、实际改了什么以及如何验证;本地任务快照不是完整历史。
|
||||
- 新人先读稳定主题页,只有追查历史原因时才读任务归档。
|
||||
- 任务产生的长期结论必须合并到主题页,不能只留在归档。
|
||||
|
||||
## 效率与范围控制
|
||||
|
||||
本节用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、Wiki 同步、Git 提交和验收归档要求。
|
||||
|
||||
### 严格控制范围
|
||||
|
||||
- 默认严格按用户确认的目标和单元任务范围执行,不主动扩展相邻问题。
|
||||
- 除非任务目标、仓库强制规则或已发现的真实阻塞需要,不新增额外文档、辅助脚本、备份文件、框架、重构或扩展性设计。
|
||||
- 不执行与本次验收无关的验证;安全检查、受影响范围测试、回归测试和仓库规定的闭环验证不属于“额外验证”。
|
||||
- 新发现的相邻问题最多用一句话提示或记录到独立工单,不自动修复或混入当前提交。
|
||||
|
||||
### 渐进执行和修复
|
||||
|
||||
- 完成已知必要的安全与前置检查后,优先执行能够产生真实反馈的最小命令。
|
||||
- 一次执行后先处理首个可定位、可行动的真实错误,不同时猜测并修改多个可能原因。
|
||||
- 采用“执行 → 查看错误 → 最小修复 → 从失败点继续或按需重跑”的闭环。
|
||||
- 不在真实证据出现前堆叠与已知风险无关的预防性检查。
|
||||
- 涉及凭据、权限、安全、数据、迁移、并发、删除、发布或不可逆操作时,必须先完成相应前置检查,不得通过试错获取风险反馈。
|
||||
|
||||
### 复用已验证事实
|
||||
|
||||
- 在同一任务和同一环境状态下,已经通过的路由、连接、恢复和环境检查不重复执行。
|
||||
- 只有会话、环境、代码、配置、依赖、凭据、远端状态或关键前提发生变化时才重新检查。
|
||||
- 代码修改后,受影响测试和最终验收必须重新执行;提交前工作区检查、推送前远端分支检查不得因为之前通过而省略。
|
||||
- Skill 和平台规则是否需要重新读取,按当前 Agent 平台和任务触发规则执行,不自行跳过。
|
||||
|
||||
### 明确停止条件
|
||||
|
||||
- 完成用户确认的验收标准和仓库规定的必要闭环后立即停止,不主动继续优化。
|
||||
- “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。
|
||||
- 未影响当前验收的相邻问题只提示或建单,不顺手处理。
|
||||
|
||||
## 自然语言快捷指令
|
||||
|
||||
快捷指令是对本工作流的自然语言别名,供 Claude Code、Codex 和维护者使用。它们只减少重复描述,不得绕过方案确认、前置依赖、安全规则、工单范围、Wiki 主源、必要验证或人工验收。
|
||||
|
||||
| 指令 | 执行动作 | 停止位置 |
|
||||
|---|---|---|
|
||||
| `只分析` | 只读检查需求、代码、日志和文档,区分事实与假设并给出方案 | 输出方案并等待确认;不建单、不修改 |
|
||||
| `建工单` | 根据已经确认的方案创建单元任务工单 | 工单创建并记录完成;不修改代码 |
|
||||
| `执行工单 #N` | 读取工单和前置依赖,实施、测试、提交、更新 Wiki、导出镜像、推送并回写证据 | 工单保持“待验收” |
|
||||
| `建工单并做` | 依次执行“建工单”和“执行工单”;`建工单,做`、`建工单,做` 含义相同 | 工单保持“待验收” |
|
||||
| `继续工单 #N` | 核对工单、Git 和 Wiki 证据,从首个未完成步骤继续,不重复仍然有效的检查 | 到达该工单当前流程的停止条件 |
|
||||
| `检查工单 #N` | 只读对照范围、验收标准、测试和证据,报告通过项、缺失项及未验证部分 | 输出检查报告;不自动修复 |
|
||||
| `同步文档` | 读取 Wiki,导出核心长期文档镜像并检查一致性,不处理任务归档 | 显示结果和差异;不修改 Wiki、不自动提交 |
|
||||
| `导出任务归档` | 人工触发增量导出,只写入新增或 revision 已变化的任务归档 | 显示导出或跳过结果;不删除本地文件、不自动提交 |
|
||||
| `导出全部任务归档` | 人工触发全量读取并导出线上全部任务归档 | 显示导出结果;不删除本地文件、不自动提交 |
|
||||
| `#N 验收通过` | 记录明确验收,更新 Wiki 归档为“已完成”,同步必要的核心文档,推送、同步父工单并关闭任务;不自动导出任务归档 | 工单“已完成”并关闭 |
|
||||
|
||||
补充边界:
|
||||
|
||||
- 方案未确认时,`建工单`、`建工单并做` 和 `执行工单 #N` 不得绕过确认;Agent 应停在方案确认。
|
||||
- 前置依赖未满足且不允许并行时,实施类指令停在“待实施”。
|
||||
- `#N 验收通过` 必须来自用户明确表达;其他快捷指令不得关闭待验收工单。
|
||||
- `同步文档` 或任务归档导出发现目标镜像有未提交改动时停止,不覆盖现有修改。
|
||||
- `导出任务归档` 和 `导出全部任务归档` 必须由用户明确提出,其他快捷指令不隐式执行。
|
||||
- Gitea 工单保留讨论和过程,不把工单全文导出到本地;`docs/task/` 只保存人工按需导出的 Wiki 最终任务归档快照。
|
||||
|
||||
## 什么时候重新确认方案
|
||||
|
||||
以下变化必须先更新工单,再由用户确认:
|
||||
@@ -103,6 +249,6 @@ python scripts/new_task_archive.py 123 "修复登录超时"
|
||||
| 讨论过程和临时方案 | 是 | 否 | 否 |
|
||||
| 实施进度和阻塞 | 是 | 否 | 否 |
|
||||
| 长期有效的最终方案 | 链接 | 是 | 镜像 |
|
||||
| 测试结果与未验证内容 | 是 | 任务归档 | 镜像 |
|
||||
| 提交哈希 | 是 | 任务归档 | 镜像 |
|
||||
| 测试结果与未验证内容 | 是 | 任务归档 | 按需镜像 |
|
||||
| 提交哈希 | 是 | 任务归档 | 按需镜像 |
|
||||
| 与具体代码版本绑定的说明 | 可链接 | 提供入口 | 是 |
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Architecture-and-Code-Map
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Architecture-and-Code-Map.-
|
||||
wiki_revision: f93132ddd5bbc8fe233270579a63fc182db3b795
|
||||
synchronized_at: 2026-08-08T01:16:49Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 架构与代码地图
|
||||
|
||||
## 本页用途
|
||||
|
||||
帮助第一次接触项目的人回答三个问题:
|
||||
|
||||
1. 项目由哪些部分组成;
|
||||
2. 一个功能应该从哪里开始读;
|
||||
3. 修改后应该运行哪些验证。
|
||||
|
||||
阅读代码前先看本页;目录、入口或主要数据流变化时必须更新本页。
|
||||
|
||||
## 项目定位
|
||||
|
||||
DevHarness 不是业务应用,而是一套开发工作流模板。它约束 Agent 和维护者如何讨论需求、建立工单、修改代码、更新 Wiki、测试、提交、验收和归档。
|
||||
|
||||
```text
|
||||
用户确认方案
|
||||
→ Gitea 单元任务工单
|
||||
→ Agent 修改代码与测试
|
||||
→ 长期结论更新 Wiki
|
||||
→ Wiki 单向导出 docs 镜像
|
||||
→ Git 提交并回写工单
|
||||
→ 用户验收
|
||||
```
|
||||
|
||||
## 代码地图
|
||||
|
||||
| 能力 | 路径 | 阅读入口 | 主要对象或函数 | 验证位置 | 风险 |
|
||||
|---|---|---|---|---|---|
|
||||
| Agent 工作规则 | `AGENTS.md` | “需求到实施” | 工作流条款 | 人工审查、Harness 检查 | 高 |
|
||||
| 工单结构 | `.gitea/issue_template/` | `task.md` | Epic、MVP、Task 模板 | 创建测试工单或检查模板 | 中 |
|
||||
| Wiki 页面映射 | `wiki-docs.json` | `mappings` | 页面名、本地路径 | `sync_wiki_docs.py --check` | 中 |
|
||||
| Wiki API 和镜像生成 | `dev_scripts/wiki_docs.py` | `WikiClient`、`sync_all` | 配置、页面、镜像元数据 | `tests/test_wiki_docs.py` | 中 |
|
||||
| 手动同步入口 | `dev_scripts/sync_wiki_docs.py` | `main()` | `--check` | 线上 Wiki 对照检查 | 低 |
|
||||
| 任务归档 | `dev_scripts/new_task_archive.py` | `main()` | 创建页面、登记映射 | 单元测试和正式归档 | 中 |
|
||||
| Harness 结构检查 | `dev_scripts/check_harness.py` | `main()` | 必需文件、镜像、归档检查 | `--strict` | 中 |
|
||||
| 本地文档镜像 | `docs/` | `docs/README.md` | 生成元数据和 Wiki 正文 | 同步检查 | 低 |
|
||||
| 自动化测试 | `tests/` | `test_wiki_docs.py` | 映射、同步和安全边界 | `unittest discover` | 低 |
|
||||
|
||||
## 两条主要执行路径
|
||||
|
||||
### Wiki 镜像
|
||||
|
||||
```text
|
||||
wiki-docs.json
|
||||
→ WikiClient 列出并解析页面
|
||||
→ 读取 Markdown 与 last_commit.sha
|
||||
→ 检查本地镜像是否有未提交修改
|
||||
→ 写入来源、URL、revision、同步时间
|
||||
→ --check 对照正文和 revision
|
||||
```
|
||||
|
||||
### 任务归档
|
||||
|
||||
```text
|
||||
读取 Wiki 归档模板
|
||||
→ 创建 Task-<编号>-<标题> 页面
|
||||
→ 追加显式页面映射
|
||||
→ 导出 docs/task 镜像
|
||||
→ 提交镜像并回写工单
|
||||
```
|
||||
|
||||
## 修改影响判断
|
||||
|
||||
| 修改内容 | 通常还要检查 |
|
||||
|---|---|
|
||||
| 修改 Agent 工作流 | `README.md`、`CLAUDE.md`、Development-Workflow、工单模板 |
|
||||
| 修改 Wiki 页面名称 | `wiki-docs.json`、Home 链接、同步测试;必须人工确认 |
|
||||
| 修改镜像格式 | 解析器、检查器、已有镜像、单元测试 |
|
||||
| 增加核心文档 | Wiki、显式映射、Home、Harness 必需页面检查 |
|
||||
| 修改归档字段 | Wiki 归档模板、归档脚本、归档检查和测试 |
|
||||
|
||||
## 不可破坏的边界
|
||||
|
||||
- 工单管理过程,Wiki 管理长期文档,Git 管理代码和镜像。
|
||||
- `docs/` 不是长期文档编辑入口。
|
||||
- 同步只允许写入 `docs/` 下的 Markdown。
|
||||
- 页面删除、重命名和本地脏镜像不能被静默处理。
|
||||
- 凭据不得进入代码、Wiki、工单、日志或镜像。
|
||||
@@ -0,0 +1,68 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Business-Rules-and-Glossary
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Business-Rules-and-Glossary.-
|
||||
wiki_revision: f78f2f92f563ec8dce5e399d4ee2b37896fa98dd
|
||||
synchronized_at: 2026-08-10T03:51:38Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 业务规则与术语
|
||||
|
||||
## 本页用途
|
||||
|
||||
解释 DevHarness 中容易混淆的术语、状态和不可破坏的流程规则。新项目复制模板后,应把项目自身的业务术语、状态和关键约束补充到本页。
|
||||
|
||||
## 核心术语
|
||||
|
||||
| 术语 | 含义 | 不要误解为 |
|
||||
|---|---|---|
|
||||
| Epic | 完整产品目标和长期路线 | 可以直接实施的单个任务 |
|
||||
| MVP | 第一个可交付范围及集成边界 | 任意里程碑名称 |
|
||||
| 单元任务 | 唯一正式实施单位,可独立测试和回退 | 临时聊天待办 |
|
||||
| 关键原始需求 | 能表达用户目的、场景和限制的少量原话或脱敏摘要 | 完整聊天记录 |
|
||||
| 正式任务需求 | 用户确认后写入单元工单的目标、非目标、方案和验收标准 | Agent 未确认的理解 |
|
||||
| 需求变化记录 | 实施期间影响范围或验收的变化、原因及用户确认 | 每一句普通讨论 |
|
||||
| 事实来源 | 某类信息被正式维护的位置 | 多处内容可以随意覆盖 |
|
||||
| Wiki 主源 | 长期开发文档首先修改的位置 | 本地 docs 的备份副本 |
|
||||
| docs 镜像 | 从 Wiki 单向生成的浏览副本 | 可以直接编辑并反向同步的文档 |
|
||||
| 待验收 | 实现和测试已完成,等待用户确认 | 已完成并可关闭 |
|
||||
| 未验证部分 | 本次无法真实覆盖的行为 | 可以省略的测试备注 |
|
||||
|
||||
## 工单状态
|
||||
|
||||
| 状态 | 含义 | 可以进入下一状态的条件 |
|
||||
|---|---|---|
|
||||
| 待确认 | 目标或方案仍需用户选择 | 用户明确确认方案 |
|
||||
| 待实施 | 方案已确认但尚未修改,或真实前置依赖尚未满足 | 前置依赖已满足或明确允许并行,且工作区和范围检查完成 |
|
||||
| 进行中 | 正在实现、测试或同步文档 | 验收标准逐项检查完成 |
|
||||
| 阻塞 | 实施过程中出现计划外、当前无法解除的问题 | 阻塞解除并更新工单 |
|
||||
| 待验收 | 代码、测试、归档和证据已完成 | 用户明确验收 |
|
||||
| 已完成 | 用户已验收并完成父任务同步 | 无 |
|
||||
|
||||
## 稳定业务规则
|
||||
|
||||
- 没有确认方案和单元任务工单,不修改产品行为。
|
||||
- 一个单元任务只解决一个可独立验证和回退的问题。
|
||||
- 建立后续工单不要求已有工单全部完成;实施前必须检查工单声明的前置依赖。
|
||||
- 前置工单未完成且存在实际依赖时保持“待实施”;允许并行时必须写明原因。
|
||||
- 需求、接口、数据、安全边界或验收标准变化时先更新工单。
|
||||
- 工单只保存关键原始需求、确认后的正式需求和重要变化,不保存完整聊天或 Agent 内部推理。
|
||||
- 长期有效的产品需求和业务规则进入 Wiki;Gitea 工单全文不导出到本地。
|
||||
- 长期文档必须先修改 Wiki,再导出本地镜像。
|
||||
- 测试结果必须真实;未执行的验证必须明确记录。
|
||||
- 用户未明确验收前,工单保持开启。
|
||||
- 初级程序员可以理解和验证低风险修改,但高风险决策仍由 Agent 分析并等待人工确认。
|
||||
|
||||
## 新项目需要补充什么
|
||||
|
||||
复制模板后,至少补充:
|
||||
|
||||
- 项目的用户和核心目标;
|
||||
- 业务名词及容易混淆的概念;
|
||||
- 主要对象和状态;
|
||||
- 关键状态流转;
|
||||
- 必须始终满足的业务规则;
|
||||
- 数据保留、权限和安全边界;
|
||||
- 典型输入、输出和失败示例。
|
||||
|
||||
业务规则必须由项目负责人确认,Agent 可以整理和举例,但不能根据代码自行臆造。
|
||||
@@ -0,0 +1,85 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Local-Development-and-Verification
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Local-Development-and-Verification.-
|
||||
wiki_revision: b31ef962e1a0a368f067b18bace3071bab60a20d
|
||||
synchronized_at: 2026-08-08T01:18:31Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 本地开发与验证
|
||||
|
||||
## 本页用途
|
||||
|
||||
让维护者能够安装、运行、检查和验证项目。所有命令默认在仓库根目录执行,示例以 Windows PowerShell 为主。
|
||||
|
||||
## 环境要求
|
||||
|
||||
| 工具 | 用途 | 检查命令 |
|
||||
|---|---|---|
|
||||
| Git | 版本管理和脏文件保护 | `git --version` |
|
||||
| Python 3 | Harness 脚本和测试 | `python --version` |
|
||||
| Gitea 连接 | 工单和 Wiki | 浏览仓库或调用 MCP |
|
||||
| Gitea PAT | 写 Wiki 时使用 | 仅通过 MCP 安全配置或 `GITEA_TOKEN` 提供 |
|
||||
|
||||
不要打印或提交 PAT。
|
||||
|
||||
## 第一次运行
|
||||
|
||||
### 1. 检查工作区
|
||||
|
||||
- 目的:确认没有混入其他任务的修改。
|
||||
- 命令:`git status --short --branch`
|
||||
- 预期:显示当前分支;开始新任务时没有无关文件。
|
||||
- 失败检查:确认变更归属,不要擅自重置或覆盖。
|
||||
|
||||
### 2. 检查 Harness
|
||||
|
||||
- 目的:验证必需文件、项目档案、Wiki 映射和归档结构。
|
||||
- 命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 预期:输出“DevHarness 检查通过”。
|
||||
- 失败检查:按错误提示检查缺失页面、未填占位符或损坏的镜像头。
|
||||
|
||||
### 3. 运行测试
|
||||
|
||||
- 目的:验证同步、路径和安全保护。
|
||||
- 命令:`python -m unittest discover -s tests -v`
|
||||
- 预期:所有测试显示 `ok`。
|
||||
- 失败检查:先单独运行失败测试,再查看最近修改的对应脚本。
|
||||
|
||||
### 4. 对照线上 Wiki
|
||||
|
||||
- 目的:确认本地 docs 是最新镜像。
|
||||
- 命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 预期:所有映射显示“一致”。
|
||||
- 失败检查:先读取线上页面;确认页面名、revision、网络和 `GITEA_URL`。
|
||||
|
||||
## 常用调试方式
|
||||
|
||||
- 只检查 Python 语法:`python -m compileall -q dev_scripts tests`。
|
||||
- 查看一个脚本帮助:`python dev_scripts/sync_wiki_docs.py --help`。
|
||||
- 查看未提交差异:`git diff --check` 和 `git diff`。
|
||||
- 查看最近提交:`git log -5 --oneline`。
|
||||
- 调试失败测试时优先运行单个测试文件,不要先修改多个模块。
|
||||
|
||||
## 测试数据与日志
|
||||
|
||||
DevHarness 不使用生产数据,也不需要固定业务测试数据。命令输出是主要诊断信息,不应包含令牌。如果复制到业务项目,应在本节写明:
|
||||
|
||||
- 合成或脱敏测试数据的创建方式;
|
||||
- 日志路径和日志级别;
|
||||
- 请求或任务标识如何追踪;
|
||||
- 禁止使用的数据来源。
|
||||
|
||||
## 完成修改前
|
||||
|
||||
依次执行:
|
||||
|
||||
```powershell
|
||||
python -m unittest discover -s tests -v
|
||||
python dev_scripts/check_harness.py --strict
|
||||
python dev_scripts/sync_wiki_docs.py --check
|
||||
git diff --check
|
||||
git status --short
|
||||
```
|
||||
|
||||
无法执行的命令必须写入工单“未验证部分”。
|
||||
@@ -0,0 +1,78 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Common-Changes
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Common-Changes.-
|
||||
wiki_revision: 9b223d2feada753a6d38bffce6eb0848c4067b85
|
||||
synchronized_at: 2026-08-08T01:16:55Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 常见修改指南
|
||||
|
||||
## 本页用途
|
||||
|
||||
帮助初级程序员在 Claude/Codex Agent 协助下处理简单 Bug 和小需求。这里说明常见入口、验证方法和停止条件,不代替工单和方案确认。
|
||||
|
||||
## 风险分级
|
||||
|
||||
| 等级 | 常见修改 | 处理方式 |
|
||||
|---|---|---|
|
||||
| 低风险 | 文案、简单校验、查询条件、独立 UI、小范围回归 Bug | 初级程序员可在 Agent 协助下修改和验证 |
|
||||
| 中风险 | API、配置、依赖、跨模块逻辑、数据结构 | 由 Agent 实现,程序员理解差异并执行验证 |
|
||||
| 高风险 | 权限、安全、并发、迁移、支付、删除数据、不可逆操作 | 停止修改,由 Agent 分析并等待人工确认 |
|
||||
|
||||
“代码行数少”不等于低风险。
|
||||
|
||||
## 修改 Wiki 文案
|
||||
|
||||
1. 在相关工单确认目标。
|
||||
2. 读取线上 Wiki 页面和当前 revision。
|
||||
3. 修改线上 Wiki,不直接编辑 `docs/`。
|
||||
4. 运行 `python dev_scripts/sync_wiki_docs.py`。
|
||||
5. 运行 `python dev_scripts/sync_wiki_docs.py --check`。
|
||||
6. 审查本地镜像差异并提交。
|
||||
|
||||
停止条件:页面需要删除、重命名或改变事实源边界。
|
||||
|
||||
## 增加工单字段
|
||||
|
||||
1. 阅读 `.gitea/issue_template/task.md` 和 Development-Workflow。
|
||||
2. 判断字段是否影响所有任务,避免只为一个任务增加永久字段。
|
||||
3. 修改模板和对应流程说明。
|
||||
4. 为 Harness 检查增加或调整测试。
|
||||
5. 创建一份示例工单草稿检查可读性。
|
||||
|
||||
停止条件:字段改变权限、审批或关闭条件。
|
||||
|
||||
## 调整 Harness 检查
|
||||
|
||||
1. 从 `dev_scripts/check_harness.py` 的 `main()` 开始读。
|
||||
2. 新检查应输出具体文件和缺失内容。
|
||||
3. 检查结构事实,不声称自动判断文档语义质量。
|
||||
4. 在 `tests/` 添加成功和失败用例。
|
||||
5. 运行严格检查及全部测试。
|
||||
|
||||
停止条件:检查会删除、重写文件或依赖生产环境。
|
||||
|
||||
## 修复 Wiki 同步 Bug
|
||||
|
||||
1. 从 `dev_scripts/wiki_docs.py` 的 `WikiClient`、`parse_mirror` 和 `sync_all` 开始读。
|
||||
2. 先编写能复现问题的测试。
|
||||
3. 保持 Wiki → docs 单向关系。
|
||||
4. 验证中文、路径编码、revision 和脏文件保护。
|
||||
5. 使用测试页面验证时,不删除正式页面。
|
||||
|
||||
停止条件:需要自动删除/重命名页面、覆盖本地未提交修改或输出令牌。
|
||||
|
||||
## 看懂 Agent 的修改
|
||||
|
||||
审查时至少回答:
|
||||
|
||||
- 这次解决了哪个工单目标;
|
||||
- 修改入口和调用路径在哪里;
|
||||
- 有哪些行为变化;
|
||||
- 增加或修改了哪些测试;
|
||||
- 哪些内容没有验证;
|
||||
- 是否更新了受影响的 Wiki 页面;
|
||||
- 怎样回退。
|
||||
|
||||
回答不了时,让 Agent补充说明,不要仅凭“测试通过”验收。
|
||||
@@ -0,0 +1,40 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Troubleshooting
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Troubleshooting
|
||||
wiki_revision: e1a806bb8c6b6c32a4e271c94a9bcaaed36003db
|
||||
synchronized_at: 2026-08-08T00:58:12Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 故障排查
|
||||
|
||||
## 本页用途
|
||||
|
||||
按“现象 → 原因 → 检查 → 处理”定位 DevHarness 常见问题。处理后如果形成稳定结论,应更新本页;临时过程记录在工单。
|
||||
|
||||
| 现象 | 常见原因 | 检查方法 | 处理 |
|
||||
|---|---|---|---|
|
||||
| `--strict` 提示项目档案未填写 | 新项目仍有占位内容 | 搜索 `<填写` | 先在 Wiki 填写真实内容,再导出镜像 |
|
||||
| 同步提示镜像有未提交改动 | 有人直接修改 docs,或上次镜像尚未提交 | `git status --short -- docs` | 确认来源;保留人工内容并先更新 Wiki,不要强制覆盖 |
|
||||
| Wiki 页面不存在 | 页面未创建、标题或映射错误 | 查看 Wiki 页面列表和 `wiki-docs.json` | 修正明确的页面或映射;不要自动删除本地文件 |
|
||||
| API 路径出现重复 `/api/v1` | `GITEA_URL` 已包含 API 后缀 | 查看非敏感 URL 配置 | 同步器会规范化;新工具也应接受两种写法 |
|
||||
| 公共仓库读取返回 401/403/404 | 环境令牌失效或属于其他实例 | 不打印令牌;尝试浏览公开页面 | 只读请求可安全降级匿名;写请求必须使用正确 PAT |
|
||||
| 中文 Wiki 页面读取 404 | `sub_url` 被重复百分号编码 | 查看页面列表返回的 `sub_url` | 保留已有 `%`,不要再次编码 |
|
||||
| Wiki 页面标题多出 `.-` | Gitea 1.25 的页面规范路径或更新时未显式传标题 | 对照页面 title 和 `sub_url` | 更新中文页面时显式保留原 title;不要猜测路径 |
|
||||
| `--check` 正文不一致 | Wiki 已更新但镜像未导出,或本地被修改 | 对照 revision 和 Git 差异 | 确认 Wiki 后运行正式同步 |
|
||||
| 单元测试能过但真实同步失败 | 测试使用模拟数据,网络或 Gitea 行为不同 | 查看工单“未验证部分” | 增加最小真实验证并记录服务端版本 |
|
||||
| Git 工作区包含无关修改 | 同时存在其他任务或人工工作 | `git status --short` | 保留并隔离无关修改,不重置用户工作 |
|
||||
|
||||
## 排查顺序
|
||||
|
||||
1. 读取完整错误信息,不只看最后一行。
|
||||
2. 检查当前工单、分支和工作区。
|
||||
3. 检查项目档案中的真实命令和环境。
|
||||
4. 用最小命令复现。
|
||||
5. 对照最近提交和 Wiki revision。
|
||||
6. 修复后增加回归测试或稳定排错条目。
|
||||
7. 无法验证的部分写回工单。
|
||||
|
||||
## 必须停止的情况
|
||||
|
||||
出现凭据泄露、数据损坏风险、权限边界变化、不可逆操作或不明来源的工作区改动时,立即停止并说明影响,不继续尝试破坏性修复。
|
||||
@@ -0,0 +1,191 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: New-Project-Documentation-Setup
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/New-Project-Documentation-Setup.-
|
||||
wiki_revision: 864d81b515b420d17fa4ff0fc7f528109b1a3d99
|
||||
synchronized_at: 2026-08-16T11:38:04Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 新项目文档初始化
|
||||
|
||||
## 本页用途
|
||||
|
||||
从 DevHarness 创建新项目时,指导 Claude/Codex Agent快速建立可供初级程序员阅读的项目文档。初始化只生成可靠的第一版,不允许 Agent 臆造业务规则、凭据、部署环境或生产数据。
|
||||
|
||||
## 初始化顺序
|
||||
|
||||
### 1. 建立项目边界
|
||||
|
||||
由项目负责人确认:
|
||||
|
||||
- 项目名称和一句话目标;
|
||||
- 用户和主要使用场景;
|
||||
- 技术栈和支持环境;
|
||||
- Gitea 仓库、默认分支和维护者;
|
||||
- 安全、权限、数据和发布红线。
|
||||
|
||||
把项目专用红线写入根目录或子目录 `AGENTS.md`。
|
||||
|
||||
### 2. 选择建设基线
|
||||
|
||||
确定技术方案前,优先评估是否存在功能和架构匹配、持续维护、许可证兼容且工程流程完善的开源项目。这里要求的是“先评估”,不是强制采用开源项目,也不能只根据知名度、Star 数量或演示效果决定。
|
||||
|
||||
至少检查:
|
||||
|
||||
- 核心功能、架构和支持平台是否匹配,哪些能力可以直接保留;
|
||||
- 许可证是否允许预期的使用、修改、分发和商业模式;不确定时交由负责人或法律专业人员确认;
|
||||
- 最近维护活跃度、发布频率、Issue 处理和社区或维护团队的持续性;
|
||||
- 已知安全问题、依赖健康度、供应链风险和安全响应方式;
|
||||
- 自动化测试、CI、发布、升级、回退和文档是否足以支持长期维护;
|
||||
- 定制、学习、迁移和后续跟踪上游的总成本是否低于从零开发;
|
||||
- 是否能够固定上游仓库和基线版本,并建立合并上游更新、兼容验证和退出方案。
|
||||
|
||||
满足适配、许可证、安全、维护和总成本条件时,优先在该基线上二次开发。不存在合适基线,或引入后会增加不可接受的许可证、安全、架构或维护风险时,可以从零开发,但必须记录排除候选项目和选择从零开发的主要原因。
|
||||
|
||||
采用开源基线时,在 Project-Profile 的“技术栈与运行环境”记录上游项目名称、仓库地址、基线版本或提交、许可证、保留能力、定制范围和上游升级策略。尚未确认的候选和取舍先写入首个技术方案工单,不得把假设写成项目事实。
|
||||
|
||||
#### 判断案例
|
||||
|
||||
以下案例用于说明判断方式,不代表必须选择某种技术或具体开源项目。
|
||||
|
||||
##### 案例一:适合基于成熟项目二次开发
|
||||
|
||||
计划开发企业内部管理系统。候选项目已经具备用户、权限、审计日志、基础数据管理和自动化测试;功能与目标架构基本匹配,许可证允许预期使用,项目持续维护,发布与升级流程完整,预计只需修改业务模块和界面。
|
||||
|
||||
- 结论:优先基于该项目二次开发。
|
||||
- 原因:可以减少通用功能的开发和验证成本,定制范围可控。
|
||||
- 记录:上游仓库、基线版本、许可证、保留功能、定制模块和上游升级方式。
|
||||
|
||||
##### 案例二:项目成熟但许可证不兼容
|
||||
|
||||
候选项目功能完整、维护活跃、文档充分,但许可证与当前产品的闭源分发、商业模式或交付条件不兼容。
|
||||
|
||||
- 结论:不采用该项目作为建设基线。
|
||||
- 原因:技术成熟度不能消除许可证风险;不确定结论必须交由负责人或法律专业人员确认。
|
||||
- 记录:候选项目、许可证限制、确认人员和排除原因。
|
||||
|
||||
##### 案例三:功能相似但改造成本过高
|
||||
|
||||
候选项目表面上覆盖大部分功能,但数据模型、权限体系和部署结构与目标项目差异很大,需要大量删除模块、重写主要接口,并长期维护上游冲突。
|
||||
|
||||
- 结论:不直接基于完整项目二次开发,可以评估只复用合适的组件或设计思路。
|
||||
- 原因:二次开发的总成本、理解成本和长期维护风险已经高于自主实现核心业务。
|
||||
- 记录:主要结构差异、改造估算、长期维护风险和最终选择。
|
||||
|
||||
##### 案例四:只复用成熟框架或组件
|
||||
|
||||
没有功能高度匹配的完整开源产品,但存在成熟的应用框架、更新组件、日志组件或通信库。
|
||||
|
||||
- 结论:从零开发业务功能,同时复用经过评估的成熟框架或组件。
|
||||
- 原因:复用基础能力不等于必须采用完整产品,可以避免被不匹配的业务架构绑定。
|
||||
- 记录:每个依赖的用途、版本、许可证、安全边界、升级方式和可替换方案。
|
||||
|
||||
每个案例的实际评估都必须记录候选项目、判断依据、最终选择、未采用原因,以及升级或退出方式。
|
||||
|
||||
### 3. 识别子项目与交付单元
|
||||
|
||||
先判断仓库中有几个应用、服务、客户端、库或其他可独立交付的部分。对每个部分确认:
|
||||
|
||||
- 职责和目录边界;
|
||||
- 技术栈、依赖和支持环境;
|
||||
- 构建、测试和运行命令;
|
||||
- 是否拥有独立版本号和发布方式;
|
||||
- 适用的根目录或子目录 `AGENTS.md`;
|
||||
- 与其他子项目共享的接口、数据或业务流程;
|
||||
- 共享契约的唯一事实来源和兼容要求。
|
||||
|
||||
把结果写入 Project-Profile 的“子项目与交付单元”。单应用项目只填写一个交付单元;多应用单仓库为规则不同的目录增加子目录 `AGENTS.md`,但不因为技术栈不同自动拆仓,也不强制统一版本和发布周期。
|
||||
|
||||
### 4. 建立 Gitea
|
||||
|
||||
创建远端仓库并完成允许的初始引导提交。开启工单和 Wiki。任何产品功能开发在引导提交后都必须先有单元任务工单。
|
||||
|
||||
### 5. 修改镜像配置
|
||||
|
||||
把 `wiki-docs.json` 中的地址、owner 和 repository 改成新项目;只保留核心主题映射,任务归档不逐页登记。
|
||||
|
||||
确认当前目录确实是新项目副本、且 DevHarness 历史归档快照不需要保留后,可以移除对应 `docs/task/` 文件。不要在原 DevHarness 仓库或已有业务项目中执行这项清理。
|
||||
|
||||
不要把 PAT 写入配置。
|
||||
|
||||
### 6. Agent 检查项目事实
|
||||
|
||||
Agent 只读检查:
|
||||
|
||||
- README、配置和依赖文件;
|
||||
- 启动入口;
|
||||
- 主要模块和目录规则;
|
||||
- 测试、格式和静态检查命令;
|
||||
- 日志、示例配置和测试数据;
|
||||
- 已存在的接口、数据模型和状态。
|
||||
|
||||
区分“代码中确认的事实”“负责人确认的业务规则”和“仍待确认的假设”。
|
||||
|
||||
### 7. 确定交付对象和文档
|
||||
|
||||
由项目负责人确认哪些岗位或客户会实际使用、部署、管理、支持、集成或验收产品,并为每类对象确定:
|
||||
|
||||
- 需要完成的工作;
|
||||
- 所需文档类型;
|
||||
- 文档可见范围;
|
||||
- 适用版本、负责人和验证人;
|
||||
- 不得对外披露的内部信息。
|
||||
|
||||
按照[交付文档指南](Delivery-Documentation-Guide.-)选择文档,使用[岗位文档模板](Audience-Document-Template.-)按需创建。没有明确读者的文档不创建,不预建空白的用户手册、管理员手册或运维手册。
|
||||
|
||||
### 8. 先创建线上 Wiki
|
||||
|
||||
至少创建或填写:
|
||||
|
||||
1. Home;
|
||||
2. Project-Profile;
|
||||
3. Architecture-and-Code-Map;
|
||||
4. Business-Rules-and-Glossary;
|
||||
5. Local-Development-and-Verification;
|
||||
6. Common-Changes;
|
||||
7. Troubleshooting;
|
||||
8. Development-Workflow;
|
||||
9. Delivery-Documentation-Guide;
|
||||
10. Audience-Document-Template;
|
||||
11. Task-Archive-Template。
|
||||
|
||||
Home 给出建议阅读顺序;每个命令必须有预期结果;代码地图必须指出入口和测试位置。具体岗位文档仅按第 7 步确认的受众创建。
|
||||
|
||||
### 9. 人工确认
|
||||
|
||||
项目负责人至少确认:
|
||||
|
||||
- 一句话目标和业务术语;
|
||||
- 关键业务规则和状态;
|
||||
- 权限、安全和数据边界;
|
||||
- 真实运行、测试和部署命令;
|
||||
- 哪些修改属于高风险;
|
||||
- 交付对象、文档可见范围和外部信息边界。
|
||||
|
||||
### 10. 导出镜像并检查
|
||||
|
||||
```powershell
|
||||
python dev_scripts/sync_wiki_docs.py
|
||||
python dev_scripts/check_harness.py --strict
|
||||
python dev_scripts/sync_wiki_docs.py --check
|
||||
python -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
只有线上 Wiki 确认后才导出核心 `docs/`。任务归档默认不导出;用户明确要求时再运行 `python dev_scripts/export_task_archives.py` 或加 `--all`。旧项目的任务归档快照不能带入新项目历史。
|
||||
|
||||
## 完成标准
|
||||
|
||||
初级程序员应能仅依靠 Home 和链接页面回答:
|
||||
|
||||
- 项目解决什么问题;
|
||||
- 怎样启动和运行测试;
|
||||
- 常用功能从哪个目录和入口开始读;
|
||||
- 一个简单修改通常要改哪里、验证什么;
|
||||
- 哪些情况必须停止并交给 Agent 或负责人;
|
||||
- 项目采用哪个建设基线,为什么适合二次开发,或者为什么选择从零开发;
|
||||
- 采用开源基线时,上游仓库、基线版本、许可证、定制范围和升级策略是什么;
|
||||
- 项目包含哪些子项目和独立交付单元,各自怎样构建、测试和发布;
|
||||
- 跨子项目共享什么接口或契约,其唯一事实来源在哪里;
|
||||
- 项目需要向哪些岗位交付什么文档,以及哪些内容不能对外提供。
|
||||
|
||||
回答不了的问题应继续补充主题文档,而不是堆入任务归档。
|
||||
@@ -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 页面删除、重命名、历史清理或事实来源反向切换不是普通回退,必须另行建单并等待确认。
|
||||
+64
-15
@@ -2,44 +2,93 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Home
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Home
|
||||
wiki_revision: 448de2a90fc237f6d5df6a5e8da1f94df2665a30
|
||||
synchronized_at: 2026-08-07T15:57:30Z
|
||||
wiki_revision: 52e9a6f8fe4fe03db8c65792ef500cc9a5084384
|
||||
synchronized_at: 2026-08-16T11:18:48Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# DevHarness 文档中心
|
||||
|
||||
DevHarness 是一个以 Gitea 工单管理开发任务、以 Wiki 管理长期开发文档、以 Git 记录代码变更的 AI 辅助开发模板。
|
||||
DevHarness 是一个以 Gitea 工单管理开发任务、以 Wiki 管理长期开发文档、以 Git 记录代码变更的 AI 辅助开发模板。目标是让初级程序员能够理解项目、运行验证,并在 Claude/Codex Agent 协助下处理简单 Bug 和需求。
|
||||
|
||||
## 第一次阅读
|
||||
|
||||
建议按以下顺序,用 10~20 分钟建立整体认识:
|
||||
|
||||
1. [项目档案](Project-Profile.-):项目目标、环境、命令和目录边界。
|
||||
2. [架构与代码地图](Architecture-and-Code-Map.-):功能从哪里开始读、测试在哪里。
|
||||
3. [业务规则与术语](Business-Rules-and-Glossary.-):重要名词、状态和不能破坏的规则。
|
||||
4. [本地开发与验证](Local-Development-and-Verification.-):怎样运行、测试和排错。
|
||||
5. [常见修改指南](Common-Changes.-):简单修改的步骤和停止条件。
|
||||
6. [故障排查](Troubleshooting):遇到错误时按什么顺序检查。
|
||||
7. [开发工作流](Development-Workflow.-):完整建单、实施、验收和归档流程。
|
||||
|
||||
从模板创建新项目时先阅读[新项目文档初始化](New-Project-Documentation-Setup.-);向已有项目增量接入本流程时阅读[已有项目接入 DevHarness 指南](Existing-Project-Adoption-Guide.-)。需要为客户或其他岗位准备说明时,阅读[交付文档指南](Delivery-Documentation-Guide.-),再按需使用[岗位文档模板](Audience-Document-Template.-)。
|
||||
|
||||
## 五分钟开始
|
||||
|
||||
在仓库根目录执行:
|
||||
|
||||
```powershell
|
||||
git status --short --branch
|
||||
python dev_scripts/check_harness.py --strict
|
||||
python -m unittest discover -s tests -v
|
||||
python dev_scripts/sync_wiki_docs.py --check
|
||||
```
|
||||
|
||||
预期结果:
|
||||
|
||||
- 工作区没有不属于当前任务的修改;
|
||||
- Harness 输出“DevHarness 检查通过”;
|
||||
- 所有单元测试通过;
|
||||
- 所有 Wiki 映射显示“一致”。
|
||||
|
||||
如果失败,先看[故障排查](Troubleshooting),不要直接重置工作区或覆盖本地文档。
|
||||
|
||||
## 简单修改从哪里开始
|
||||
|
||||
| 想做什么 | 先读哪里 | 主要验证 |
|
||||
|---|---|---|
|
||||
| 修改文档 | 对应 Wiki 页面、Common-Changes | Wiki 同步检查 |
|
||||
| 接入已有项目 | Existing-Project-Adoption-Guide | 只读盘点、差异确认和分阶段验证 |
|
||||
| 准备交付文档 | Delivery-Documentation-Guide、Audience-Document-Template | 目标岗位验证和 Wiki 同步检查 |
|
||||
| 调整工单字段 | `.gitea/issue_template/`、Development-Workflow | Harness 严格检查 |
|
||||
| 修改同步行为 | `dev_scripts/wiki_docs.py`、Architecture-and-Code-Map | 单元测试和真实 Wiki 检查 |
|
||||
| 增加结构检查 | `dev_scripts/check_harness.py` | 成功与失败测试 |
|
||||
| 排查运行错误 | Troubleshooting、项目档案 | 最小复现命令 |
|
||||
|
||||
权限、安全、并发、迁移、支付、删除数据或不可逆操作不属于简单修改,必须停止并交给 Agent 分析、等待人工确认。
|
||||
|
||||
## 事实来源
|
||||
|
||||
| 信息 | 事实来源 |
|
||||
|---|---|
|
||||
| 任务状态、讨论、阻塞、验收过程 | Gitea 工单 |
|
||||
| 架构说明、开发规范、操作手册、任务归档 | Gitea Wiki |
|
||||
| 架构、业务规则、开发规范、操作手册、交付文档、任务归档 | Gitea Wiki |
|
||||
| 源码和与特定代码版本强绑定的文档 | Git 仓库 |
|
||||
| 离线浏览副本 | Git 仓库中的 `docs/` Wiki 镜像 |
|
||||
| 核心长期文档的离线浏览副本 | Git 仓库中的 `docs/` Wiki 镜像 |
|
||||
| 完整任务归档 | Gitea Wiki;`docs/task/` 仅是人工按需导出的快照 |
|
||||
|
||||
本地 `docs/` 不是编辑入口。长期文档必须先修改 Wiki,读取确认后再导出镜像。
|
||||
|
||||
## 文档入口
|
||||
## 项目入口
|
||||
|
||||
- [项目档案](Project-Profile.-)
|
||||
- [开发工作流](Development-Workflow.-)
|
||||
- [任务归档模板](Task-Archive-Template.-)
|
||||
- [Gitea 工单](http://ilaer.eicp.net:8418/opc/dev_harness/issues)
|
||||
- [代码仓库](http://ilaer.eicp.net:8418/opc/dev_harness)
|
||||
- [已有项目接入 DevHarness 指南](Existing-Project-Adoption-Guide.-)
|
||||
- [交付文档指南](Delivery-Documentation-Guide.-)
|
||||
- [岗位文档模板](Audience-Document-Template.-)
|
||||
- [任务归档模板](Task-Archive-Template.-)
|
||||
|
||||
## 同步原则
|
||||
|
||||
固定顺序:
|
||||
|
||||
```text
|
||||
修改 Wiki → 读取确认 → 导出 docs → 校验差异 → 提交镜像
|
||||
```
|
||||
|
||||
- 页面和本地路径通过仓库中的 `wiki-docs.json` 显式映射。
|
||||
- 核心页面和本地路径通过仓库中的 `wiki-docs.json` 显式映射;普通同步不处理任务归档。
|
||||
- 任务归档默认只保存在 Wiki,只有用户明确提出时才增量或全量导出到 `docs/task/`。
|
||||
- 镜像头记录来源页面、Wiki revision 和同步时间。
|
||||
- 同步工具发现已跟踪镜像存在未提交修改时必须停止。
|
||||
- 页面删除、重命名和映射变更必须人工确认,不自动传播。
|
||||
- Wiki 或导出失败时,相关任务不能标记为完成。
|
||||
- 已映射镜像存在未提交修改时同步必须停止。
|
||||
- 页面删除、重命名和映射变更必须人工确认。
|
||||
- 核心 Wiki 或必要同步失败时,相关任务不能标记为完成;未请求任务归档导出不阻止任务完成。
|
||||
- 凭据、个人数据和生产数据不得进入 Wiki 或镜像。
|
||||
|
||||
@@ -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. <执行动作>
|
||||
|
||||
**预期结果**:<读者可以观察到的成功结果>
|
||||
|
||||
**失败时**:<先检查什么;何时停止并联系支持>
|
||||
|
||||
每个独立任务重复以上结构。命令和界面名称应与适用版本一致;危险或不可逆操作必须在执行前给出醒目警告、影响和回退条件。
|
||||
|
||||
## 常见错误与恢复
|
||||
|
||||
| 现象或错误信息 | 可能原因 | 处理步骤 | 何时升级 |
|
||||
|---|---|---|---|
|
||||
| | | | |
|
||||
|
||||
只记录经过确认的原因和恢复方法。不要让外部读者执行内部调试、绕过权限或可能扩大损失的操作。
|
||||
|
||||
## 安全与权限
|
||||
|
||||
- 本岗位允许执行的操作:
|
||||
- 明确禁止或需要审批的操作:
|
||||
- 敏感信息处理规则:
|
||||
- 数据、日志和截图脱敏要求:
|
||||
- 删除、发布、迁移或其他高风险操作的确认要求:
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 支持的环境和版本:
|
||||
- 当前不支持的场景:
|
||||
- 兼容性限制:
|
||||
- 未验证的环境或步骤:
|
||||
|
||||
## 支持与升级处理
|
||||
|
||||
- 支持渠道:
|
||||
- 服务时间或响应约定:
|
||||
- 联系支持前需要收集的信息:
|
||||
- 不得提交的信息:
|
||||
- 需要升级到下一岗位或负责人的条件:
|
||||
|
||||
## 版本记录
|
||||
|
||||
| 日期 | 适用版本 | 变更内容 | 验证人 |
|
||||
|---|---|---|---|
|
||||
| | | | |
|
||||
|
||||
## 交付前检查
|
||||
|
||||
- [ ] 目标岗位能够理解术语和步骤。
|
||||
- [ ] 前置条件、步骤与预期结果一一对应。
|
||||
- [ ] 关键流程已按目标岗位视角验证。
|
||||
- [ ] 常见错误、恢复方法和升级条件清楚。
|
||||
- [ ] 没有内部工单、内部地址、敏感数据或无关源码细节。
|
||||
- [ ] 适用版本、最后验证日期、负责人和可见范围已填写。
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Task-1-Wiki-文档主源
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-1-Wiki-%E6%96%87%E6%A1%A3%E4%B8%BB%E6%BA%90.-
|
||||
wiki_revision: 3d546bcad27498e7a263b0c4f124239490cc9f50
|
||||
synchronized_at: 2026-08-07T16:01:58Z
|
||||
wiki_revision: dbbf9ddfb2e703486c7054f275538e8e03a570b3
|
||||
synchronized_at: 2026-08-08T01:11:20Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 1 引入 Gitea Wiki 作为长期开发文档主源
|
||||
@@ -11,7 +11,7 @@ synchronized_at: 2026-08-07T16:01:58Z
|
||||
- 类型:需求
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:待验收
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-07
|
||||
- Gitea 工单:[opc/dev_harness#1](http://ilaer.eicp.net:8418/opc/dev_harness/issues/1)
|
||||
- Wiki 页面:Task-1-Wiki-文档主源
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,81 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Task-2-Junior-Maintainer-Docs
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-2-Junior-Maintainer-Docs.-
|
||||
wiki_revision: 9bf07c395c959501d995cfe7250623438c53dba7
|
||||
synchronized_at: 2026-08-08T01:11:23Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 2 建立面向初级维护者的轻量项目文档体系
|
||||
|
||||
- 类型:需求
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:[opc/dev_harness#2](http://ilaer.eicp.net:8418/opc/dev_harness/issues/2)
|
||||
- Wiki 页面:Task-2-Junior-Maintainer-Docs
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
DevHarness 已具备工单、Wiki 主源和本地镜像流程,但缺少面向初级维护者的代码入口、业务规则、运行验证、简单修改和故障排查。目标是让初级程序员理解项目文档,并在 Claude/Codex Agent 协助下处理简单 Bug 和需求;大部分代码仍由 Agent 实现。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- Home 提供 10~20 分钟阅读路径、五分钟验证命令、修改入口和停止条件。
|
||||
- 新增架构与代码地图、业务规则与术语、本地开发与验证、常见修改、故障排查、新项目文档初始化六个稳定主题页。
|
||||
- 项目档案补充使用者、环境、适用版本、日志、测试数据和阅读入口。
|
||||
- 开发工作流和 Agent 规则采用低/中/高风险分级,不以代码行数判断风险。
|
||||
- 单元任务模板增加“文档影响”,入口、命令、配置、数据、业务和排错变化必须更新 Wiki。
|
||||
- Harness 检查核心页面映射、固定章节及任务模板字段;不把结构检查误认为语义质量判断。
|
||||
- 新项目使用明确初始化说明,不增加额外 Wiki 生成框架。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `AGENTS.md`:增加风险边界、核心文档和更新条件。
|
||||
- `CLAUDE.md`:增加代码地图、业务规则阅读顺序和文档影响要求。
|
||||
- `.gitea/issue_template/task.md`:增加文档影响检查项。
|
||||
- `README.md`:链接新项目初始化和新增镜像目录。
|
||||
- `wiki-docs.json`:登记六个新增核心页面。
|
||||
- `scripts/check_harness.py`:检查核心映射、章节和工单模板。
|
||||
- `tests/test_harness_docs.py`:覆盖成功、缺失章节和错误映射。
|
||||
- `docs/README.md`、`docs/00-project-profile.md`、`docs/01-workflow.md`:更新后的 Wiki 镜像。
|
||||
- `docs/02-architecture-and-code-map.md` 至 `docs/07-new-project-documentation-setup.md`:新增 Wiki 镜像。
|
||||
|
||||
## 验收结果
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| Home 提供阅读顺序、启动、测试和代码入口 | 通过 |
|
||||
| 核心页面职责明确且保持轻量结构 | 通过 |
|
||||
| 简单修改和高风险停止边界清楚 | 通过 |
|
||||
| 单元任务必须声明文档影响 | 通过 |
|
||||
| 严格检查能发现页面、映射和章节问题 | 通过 |
|
||||
| Wiki 与本地镜像一致 | 通过 |
|
||||
| 自动化测试和严格检查通过 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:16/16 通过。
|
||||
- 执行命令:`python scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python scripts/sync_wiki_docs.py --check`
|
||||
- 结果:11/11 映射一致。
|
||||
- 执行命令:`python -m compileall -q scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:`git diff --check`
|
||||
- 结果:通过。
|
||||
- 人工验证:六个新增 Wiki 页面均可访问,Home 阅读路径、风险分级和初始化顺序完整。
|
||||
- **未验证部分**:尚未在全新业务仓库完整执行初始化,也未由真实初级程序员完成可用性测试。
|
||||
|
||||
## 遗留问题
|
||||
|
||||
首个采用该模板的业务项目应把“新人能否根据 Home 找到入口、运行测试并理解一次简单修改”纳入实际验收,再根据反馈精简或补充主题页。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `250b055` feat: 建立初级维护者文档体系 (#2)
|
||||
- `b09658e` docs: 修正文档命令与初始化边界 (#2)
|
||||
- `c8ccb62` test: 覆盖核心文档映射错误 (#2)
|
||||
@@ -0,0 +1,72 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Task-3-Dev-Scripts-Rename
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-3-Dev-Scripts-Rename.-
|
||||
wiki_revision: 15e71e5f540039f3947754a4a17971e12604dff7
|
||||
synchronized_at: 2026-08-08T01:24:35Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 3 将 DevHarness 工具目录重命名为 dev_scripts
|
||||
|
||||
- 类型:重构
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:[opc/dev_harness#3](http://ilaer.eicp.net:8418/opc/dev_harness/issues/3)
|
||||
- Wiki 页面:Task-3-Dev-Scripts-Rename
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
DevHarness 自身工具原来放在根目录 `scripts/`,容易和后续业务项目的脚本混淆。本任务把 Harness 检查、Wiki 同步和任务归档工具统一迁移到 `dev_scripts/`,不保留旧路径兼容入口。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- `scripts/check_harness.py` → `dev_scripts/check_harness.py`。
|
||||
- `scripts/wiki_docs.py` → `dev_scripts/wiki_docs.py`。
|
||||
- `scripts/sync_wiki_docs.py` → `dev_scripts/sync_wiki_docs.py`。
|
||||
- `scripts/new_task_archive.py` → `dev_scripts/new_task_archive.py`。
|
||||
- 更新测试导入路径、必需文件检查、AGENTS、README 和稳定 Wiki 页面。
|
||||
- Wiki 先修改并读取确认,再导出本地镜像。
|
||||
- 历史任务 #1、#2 保留旧路径,避免改写历史事实。
|
||||
- 旧 `scripts/` 目录不保留包装器,未来业务脚本必须与 `dev_scripts/` 分开。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `scripts/**` → `dev_scripts/**`:整体目录重命名。
|
||||
- `dev_scripts/check_harness.py`:必需工具路径改为新目录。
|
||||
- `tests/test_wiki_docs.py`、`tests/test_harness_docs.py`:导入新目录。
|
||||
- `AGENTS.md`:更新同步、归档命令和目录边界。
|
||||
- `README.md`:更新快速开始和目录说明。
|
||||
- `docs/README.md`、项目档案、工作流、代码地图、开发验证、常见修改和新项目初始化:线上 Wiki 的更新镜像。
|
||||
|
||||
## 验收结果
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| 四个工具位于 dev_scripts,旧目录不存在 | 通过 |
|
||||
| 新命令可运行且不保留旧兼容入口 | 通过 |
|
||||
| 测试导入和必需文件检查使用新路径 | 通过 |
|
||||
| 稳定 Wiki 与本地镜像使用新路径 | 通过 |
|
||||
| 非历史内容没有旧路径引用 | 通过 |
|
||||
| 测试、严格检查、同步和编译通过 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:16/16 通过。
|
||||
- 执行命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 结果:12/12 映射一致。
|
||||
- 执行命令:`python -m compileall -q dev_scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:旧目录和非历史旧路径搜索。
|
||||
- 结果:旧目录不存在;非历史旧路径无残留。
|
||||
- **未验证部分**:仓库外部未纳入版本管理的自动化如果仍使用旧命令,需要使用方自行更新。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `1c99867` refactor: 将 Harness 工具移至 dev_scripts (#3)
|
||||
- `51278fa` docs: 修正 dev_scripts 编译检查命令 (#3)
|
||||
@@ -0,0 +1,70 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Task-4-Agent-Efficiency-Scope
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-4-Agent-Efficiency-Scope.-
|
||||
wiki_revision: 3c2d8b9e5d82a0d3da5b71ef9d889e11d813d27d
|
||||
synchronized_at: 2026-08-08T01:59:47Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 4 增加 Agent 效率与范围控制规则
|
||||
|
||||
- 类型:需求
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:[opc/dev_harness#4](http://ilaer.eicp.net:8418/opc/dev_harness/issues/4)
|
||||
- Wiki 页面:Task-4-Agent-Efficiency-Scope
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
DevHarness 已有完整安全和交付闭环,但缺少对无关扩展、重复检查、预防性验证和完成后继续优化的限制。本任务在不削弱安全、测试和归档的前提下增加效率规则。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- 严格控制范围:默认按用户确认目标和工单执行,只限制无关产物、无关验证和相邻问题。
|
||||
- 渐进执行和修复:完成必要前置检查后,用最小命令获得真实反馈,一次处理首个可行动错误。
|
||||
- 复用已验证事实:只在同一任务和同一环境状态下复用,关键前提变化时重检。
|
||||
- 明确停止条件:完成用户验收标准和仓库必要闭环后停止,首次运行成功不等于完成。
|
||||
- 安全、高风险前置检查、代码修改后的测试、提交前状态、推送前远端检查和 Skill 规则不允许省略。
|
||||
- Harness 检查开发工作流镜像和 AGENTS 中四组章节是否存在。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `AGENTS.md`:增加效率与范围控制的完整规则。
|
||||
- `CLAUDE.md`:增加简明执行入口。
|
||||
- `Development-Workflow` Wiki:增加长期工作流说明。
|
||||
- `docs/01-workflow.md`:Wiki 更新后的只读镜像。
|
||||
- `dev_scripts/check_harness.py`:检查四组核心规则章节。
|
||||
- `tests/test_harness_docs.py`:验证当前 Agent 规则结构。
|
||||
|
||||
## 验收结果
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| 范围限制不禁止任务必需或仓库强制产物 | 通过 |
|
||||
| 渐进执行保留安全和高风险前置检查 | 通过 |
|
||||
| 事实复用包含失效条件和重检例外 | 通过 |
|
||||
| 最小验收包含完整项目闭环 | 通过 |
|
||||
| 相邻问题不会自动混入 | 通过 |
|
||||
| Harness 检查四组章节 | 通过 |
|
||||
| Wiki、测试和严格检查通过 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:17/17 通过。
|
||||
- 执行命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 结果:13/13 映射一致。
|
||||
- 执行命令:`python -m compileall -q dev_scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:`git diff --check`
|
||||
- 结果:通过。
|
||||
- **未验证部分**:不同新项目中的实际效率提升需要通过后续任务数据验证。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `d3df733` docs: 增加 Agent 效率与范围控制 (#4)
|
||||
@@ -0,0 +1,70 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Task-5-Simplify-Agents
|
||||
wiki_url: http://ilaer.eicp.net:8418/opc/dev_harness/wiki/Task-5-Simplify-Agents.-
|
||||
wiki_revision: 2096d9eee938c7680c1188dd6a5fbe490d1fd69c
|
||||
synchronized_at: 2026-08-08T03:26:17Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 5 精简 AGENTS 中重复的解释性内容
|
||||
|
||||
- 类型:重构
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:[opc/dev_harness#5](http://ilaer.eicp.net:8418/opc/dev_harness/issues/5)
|
||||
- Wiki 页面:Task-5-Simplify-Agents
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
AGENTS 中部分工单层级、风险示例和核心文档说明已经由 Wiki 完整维护。本任务把 AGENTS 精简为强制规则入口,降低重复维护,同时保证 Agent 只读入口规则时不会遗漏安全和交付要求。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- 工单层级保留单元任务唯一实施、父工单索引和同步要求,详细定义链接开发工作流与业务术语。
|
||||
- 归档步骤压缩但保留待验收、Wiki 优先、镜像检查、独立提交、证据回写和验收关闭。
|
||||
- 风险示例表改为强制结论,详细示例链接常见修改指南。
|
||||
- 核心文档清单改为更新触发条件,详细清单链接新项目初始化指南。
|
||||
- dev_scripts 不与业务脚本混放的项目红线保留。
|
||||
- Harness 检查关键强制规则文本,防止后续精简误删。
|
||||
- 六个现有 Wiki 页面已经承接详细内容,本任务未修改稳定 Wiki 正文。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `AGENTS.md`:精简重复解释并增加现有镜像入口。
|
||||
- `dev_scripts/check_harness.py`:检查关键强制规则仍然存在。
|
||||
|
||||
## 验收结果
|
||||
|
||||
用户于 2026-08-08 明确验收通过。
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| 所有安全和交付强制规则保留 | 通过 |
|
||||
| 详细层级、风险和文档清单不再重复 | 通过 |
|
||||
| 被精简内容均有现有文档入口 | 通过 |
|
||||
| 单元任务仍是唯一实施单位 | 通过 |
|
||||
| 高风险修改仍需停止和确认 | 通过 |
|
||||
| 用户验收前不得关闭工单 | 通过 |
|
||||
| Harness 和测试通过 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- AGENTS 非空规则行:115 降至 102。
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:17/17 通过。
|
||||
- 执行命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 结果:14/14 映射一致。
|
||||
- 执行命令:`python -m compileall -q dev_scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:`git diff --check`
|
||||
- 结果:通过。
|
||||
- **未验证部分**:无。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `c9f1bc8` refactor: 精简 AGENTS 重复说明 (#5)
|
||||
@@ -0,0 +1,78 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
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_revision: 321e7016b2fcdf39f5bc6453310b233d00e81f07
|
||||
synchronized_at: 2026-08-08T03:26:20Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 6 优化 Claude Code 规则入口
|
||||
|
||||
- 类型:重构
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/6
|
||||
- Wiki 页面:Task-6-优化ClaudeCode规则入口
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
仓库原有 `CLAUDE.md` 已声明 `AGENTS.md` 是共同规则来源,但仍手工复制了阅读顺序、安全、工单、Wiki、Git 和验收等多条共同规则。两处同时维护容易产生内容漂移。
|
||||
|
||||
本任务把 `CLAUDE.md` 优化为 Claude Code 的轻量入口:使用官方支持的 `@AGENTS.md` 语法直接导入共同规则,仅在本文件记录 Claude Code 专用差异。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- 在根目录 `CLAUDE.md` 中使用独立的 `@AGENTS.md` 导入行。
|
||||
- 删除原先重复的共同流程清单,仅保留三条入口说明。
|
||||
- 明确 `AGENTS.md` 是共同规则事实来源,共同规则只在其中维护。
|
||||
- 当前没有 Claude Code 特有的项目规则;以后只有平台或工具差异才写入 `CLAUDE.md`。
|
||||
- 将 `CLAUDE.md` 加入 Harness 必需文件。
|
||||
- 新增入口检查,要求精确的独立导入行和事实来源说明。
|
||||
- 新增自动化测试,覆盖正常入口和缺失导入两种情况。
|
||||
- 稳定流程语义未变化,因此没有修改稳定 Wiki 主题页。
|
||||
|
||||
实施结果与建单方案一致。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `CLAUDE.md`:改为导入式 Claude Code 入口,删除重复共同规则。
|
||||
- `dev_scripts/check_harness.py`:增加必需文件和 Claude Code 入口检查。
|
||||
- `tests/test_harness_docs.py`:增加入口正向测试和缺失导入失败测试。
|
||||
- `wiki-docs.json`:登记本任务 Wiki 归档镜像。
|
||||
- `docs/task/6-优化ClaudeCode规则入口.md`:本页的自动导出镜像。
|
||||
|
||||
## 验收结果
|
||||
|
||||
用户于 2026-08-08 明确验收通过。
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| 根目录文件名为 `CLAUDE.md` | 通过 |
|
||||
| 使用 `@AGENTS.md` 导入共同规则 | 通过 |
|
||||
| 不再复制大段共同流程 | 通过,由 24 行精简为 9 行 |
|
||||
| 共同规则只维护在 `AGENTS.md` | 通过 |
|
||||
| Harness 检测缺失入口或导入 | 通过 |
|
||||
| 测试、严格检查和 Wiki 镜像检查 | 通过 |
|
||||
| 实现和归档提交分离 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:19/19 通过。
|
||||
- 执行命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 结果:归档前 15/15 映射一致;归档后将重新检查 16/16。
|
||||
- 执行命令:`python -m compileall -q dev_scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:`git diff --check`
|
||||
- 结果:通过。
|
||||
- **未验证部分**:未启动 Claude Code 交互会话执行 `/memory`;导入语法依据 Claude Code 官方文档,并由仓库检查保证格式。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `2adb30a` `refactor: 优化 Claude Code 规则入口 (#6)`
|
||||
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
|
||||
@@ -0,0 +1,81 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
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_revision: cfd37f7beab92133e1528104df9553e3e7835aff
|
||||
synchronized_at: 2026-08-08T03:26:21Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
# 7 Claude Code 模型路由
|
||||
|
||||
- 类型:开发规则优化
|
||||
- 所属 Epic:无
|
||||
- 所属 MVP / 版本:无
|
||||
- 状态:已完成
|
||||
- 日期:2026-08-08
|
||||
- Gitea 工单:http://ilaer.eicp.net:8418/opc/dev_harness/issues/7
|
||||
- Wiki 页面:Task-7-ClaudeCode模型路由
|
||||
- Wiki revision:见本地镜像头
|
||||
|
||||
## 背景与目标
|
||||
|
||||
Claude Code 已通过 `CLAUDE.md` 导入共同开发规则,但没有说明 Opus、Sonnet 和 Haiku 应如何按任务复杂度分工。若每个任务固定依次调用三个模型,会增加重复上下文、Token 和等待时间;如果只用提示语要求 Haiku 只读,又不能真正限制其工具权限。
|
||||
|
||||
本任务在 Claude Code 专用入口中增加按需模型路由、结构化交接和 Haiku 只读边界。
|
||||
|
||||
## 最终方案
|
||||
|
||||
- 目标、范围和修改位置明确的任务默认由 Sonnet 分析、建单和实施。
|
||||
- 模糊需求、复杂根因、跨模块架构或高风险任务由 Opus/`opusplan` 制定方案。
|
||||
- Opus 方案必须先由用户确认,再交给 Sonnet 创建工单和实施。
|
||||
- Haiku 仅用于范围明确的文档、代码入口、日志事实和调用关系检索。
|
||||
- Haiku 不承担最终根因、技术方案、风险等级和验收结论。
|
||||
- 当前模型足够时不升级,不固定依次调用三个模型。
|
||||
- Agent 只交接结构化事实、假设、范围、风险、证据位置和未知项,减少大段重复上下文。
|
||||
- Haiku 只读必须由工具权限实现;本任务未创建子 Agent 配置,因此未配置只读权限时不得调用 Haiku 处理项目内容。
|
||||
- Harness 检查三个新增章节及关键边界,防止后续误删。
|
||||
- 未写死具体模型版本,继续使用模型别名。
|
||||
|
||||
实施结果与已确认方案一致。
|
||||
|
||||
## 修改文件
|
||||
|
||||
- `CLAUDE.md`:增加模型路由、Agent 交接和 Haiku 只读约束。
|
||||
- `dev_scripts/check_harness.py`:增加 Claude Code 路由规则的结构检查。
|
||||
- `wiki-docs.json`:登记本任务 Wiki 归档镜像。
|
||||
- `docs/task/7-ClaudeCode模型路由.md`:本页的自动导出镜像。
|
||||
|
||||
## 验收结果
|
||||
|
||||
用户于 2026-08-08 明确验收通过。
|
||||
|
||||
| 验收标准 | 结果 |
|
||||
|---|---|
|
||||
| 保留 `@AGENTS.md` 导入和共同规则来源说明 | 通过 |
|
||||
| 包含模型路由、Agent 交接和 Haiku 只读约束 | 通过 |
|
||||
| 不要求每个任务依次调用三个模型 | 通过 |
|
||||
| Opus 方案经用户确认后由 Sonnet 实施 | 通过 |
|
||||
| Haiku 不做最终决策 | 通过 |
|
||||
| Haiku 只读要求工具权限实施 | 通过 |
|
||||
| 不写死具体模型版本 | 通过 |
|
||||
| Harness、测试和镜像检查 | 通过 |
|
||||
| 实现和归档提交分离 | 通过 |
|
||||
|
||||
## 测试
|
||||
|
||||
- 执行命令:`python -m unittest discover -s tests -v`
|
||||
- 结果:19/19 通过。
|
||||
- 执行命令:`python dev_scripts/check_harness.py --strict`
|
||||
- 结果:通过。
|
||||
- 执行命令:`python dev_scripts/sync_wiki_docs.py --check`
|
||||
- 结果:归档前 16/16 映射一致;归档后重新检查 17/17。
|
||||
- 执行命令:`python -m compileall -q dev_scripts tests`
|
||||
- 结果:通过。
|
||||
- 执行命令:`git diff --check`
|
||||
- 结果:通过。
|
||||
- **未验证部分**:未创建或运行 Haiku 只读子 Agent,未执行多模型 Token/耗时基准;这些均不在本任务范围内。
|
||||
|
||||
## 相关提交
|
||||
|
||||
- `3bfe752` `docs: 增加 Claude Code 模型路由 (#7)`
|
||||
- 归档提交哈希在提交后回写 Gitea 工单,避免归档自引用。
|
||||
@@ -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 工单,避免归档自引用。
|
||||
@@ -1,130 +0,0 @@
|
||||
"""检查 DevHarness 必需文件和任务归档的基本结构。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from wiki_docs import WikiDocsError, load_config, parse_mirror
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REQUIRED_FILES = (
|
||||
"AGENTS.md",
|
||||
"README.md",
|
||||
"docs/00-project-profile.md",
|
||||
"docs/01-workflow.md",
|
||||
"docs/templates/task-archive.md",
|
||||
"wiki-docs.json",
|
||||
"scripts/wiki_docs.py",
|
||||
"scripts/sync_wiki_docs.py",
|
||||
".gitea/issue_template/epic.md",
|
||||
".gitea/issue_template/mvp.md",
|
||||
".gitea/issue_template/task.md",
|
||||
)
|
||||
ARCHIVE_HEADINGS = (
|
||||
"## 背景与目标",
|
||||
"## 最终方案",
|
||||
"## 修改文件",
|
||||
"## 验收结果",
|
||||
"## 测试",
|
||||
"## 相关提交",
|
||||
)
|
||||
|
||||
|
||||
def check_required_files(errors: list[str]) -> None:
|
||||
for relative_path in REQUIRED_FILES:
|
||||
if not (ROOT / relative_path).is_file():
|
||||
errors.append(f"缺少必需文件:{relative_path}")
|
||||
|
||||
|
||||
def check_project_profile(errors: list[str], warnings: list[str], strict: bool) -> None:
|
||||
profile = ROOT / "docs" / "00-project-profile.md"
|
||||
if not profile.is_file():
|
||||
return
|
||||
if "<填写" in profile.read_text(encoding="utf-8"):
|
||||
message = "项目档案仍有未填写内容"
|
||||
(errors if strict else warnings).append(message)
|
||||
|
||||
|
||||
def check_archives(errors: list[str]) -> None:
|
||||
task_dir = ROOT / "docs" / "task"
|
||||
for path in task_dir.glob("*.md"):
|
||||
if not re.match(r"^\d+-.+\.md$", path.name):
|
||||
errors.append(f"归档文件名不符合 <编号>-<标题>.md:{path.name}")
|
||||
content = path.read_text(encoding="utf-8")
|
||||
for heading in ARCHIVE_HEADINGS:
|
||||
if heading not in content:
|
||||
errors.append(f"{path.name} 缺少章节:{heading}")
|
||||
if "**未验证部分**:" not in content:
|
||||
errors.append(f"{path.name} 没有记录未验证部分")
|
||||
|
||||
|
||||
def check_wiki_mirrors(errors: list[str]) -> None:
|
||||
"""检查每份本地文档都有显式映射和可追踪的镜像头。"""
|
||||
|
||||
try:
|
||||
config = load_config()
|
||||
except WikiDocsError as exc:
|
||||
errors.append(str(exc))
|
||||
return
|
||||
|
||||
mapped_paths = {mapping.path for mapping in config.mappings}
|
||||
actual_paths = {
|
||||
path.relative_to(ROOT).as_posix() for path in (ROOT / "docs").rglob("*.md")
|
||||
}
|
||||
for path in sorted(actual_paths - mapped_paths):
|
||||
errors.append(f"docs 中存在未登记的 Wiki 镜像:{path}")
|
||||
|
||||
for mapping in config.mappings:
|
||||
path = ROOT / mapping.path
|
||||
if not path.is_file():
|
||||
errors.append(f"缺少 Wiki 镜像:{mapping.path}")
|
||||
continue
|
||||
try:
|
||||
metadata, _ = parse_mirror(path.read_text(encoding="utf-8"))
|
||||
except (OSError, UnicodeDecodeError, WikiDocsError) as exc:
|
||||
errors.append(f"Wiki 镜像无效 {mapping.path}:{exc}")
|
||||
continue
|
||||
if metadata.get("generated") != "true (请先修改 Gitea Wiki,禁止直接编辑本文件)":
|
||||
errors.append(f"{mapping.path} 没有只读镜像标记")
|
||||
if metadata.get("wiki_page") != mapping.page:
|
||||
errors.append(f"{mapping.path} 的 wiki_page 与映射不一致")
|
||||
revision = metadata.get("wiki_revision", "")
|
||||
if re.fullmatch(r"[0-9a-f]{40,64}", revision) is None:
|
||||
errors.append(f"{mapping.path} 的 wiki_revision 无效")
|
||||
if not metadata.get("synchronized_at"):
|
||||
errors.append(f"{mapping.path} 缺少 synchronized_at")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="检查 DevHarness 项目结构")
|
||||
parser.add_argument(
|
||||
"--strict",
|
||||
action="store_true",
|
||||
help="项目档案有占位内容时返回失败",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
errors: list[str] = []
|
||||
warnings: list[str] = []
|
||||
check_required_files(errors)
|
||||
check_project_profile(errors, warnings, args.strict)
|
||||
check_wiki_mirrors(errors)
|
||||
check_archives(errors)
|
||||
|
||||
for warning in warnings:
|
||||
print(f"警告:{warning}")
|
||||
for error in errors:
|
||||
print(f"错误:{error}")
|
||||
|
||||
if errors:
|
||||
print(f"检查失败:{len(errors)} 个问题")
|
||||
return 1
|
||||
print("DevHarness 检查通过")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,210 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / "dev_scripts"))
|
||||
|
||||
from check_harness import ( # noqa: E402
|
||||
CORE_DOCUMENT_REQUIREMENTS,
|
||||
CORE_PAGE_PATHS,
|
||||
REQUIRED_FILES,
|
||||
check_claude_code_entry,
|
||||
check_core_documents,
|
||||
check_agent_efficiency_rules,
|
||||
check_task_template,
|
||||
core_mapping_errors,
|
||||
missing_sections,
|
||||
)
|
||||
from wiki_docs import load_config # noqa: E402
|
||||
|
||||
|
||||
class CoreDocumentTests(unittest.TestCase):
|
||||
def test_current_core_documents_have_required_sections(self) -> None:
|
||||
errors: list[str] = []
|
||||
check_core_documents(errors)
|
||||
self.assertEqual(errors, [])
|
||||
|
||||
def test_missing_sections_reports_each_heading(self) -> None:
|
||||
missing = missing_sections("# 页面\n## 已有\n", ("## 已有", "## 缺少"))
|
||||
self.assertEqual(missing, ["## 缺少"])
|
||||
|
||||
def test_every_core_document_is_required(self) -> None:
|
||||
for path in CORE_DOCUMENT_REQUIREMENTS:
|
||||
self.assertIn(path, REQUIRED_FILES)
|
||||
|
||||
def test_every_core_page_has_exact_mapping(self) -> None:
|
||||
config = load_config()
|
||||
mappings = {mapping.page: mapping.path for mapping in config.mappings}
|
||||
for page, path in CORE_PAGE_PATHS.items():
|
||||
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:
|
||||
errors = core_mapping_errors({"Home": "docs/wrong.md"})
|
||||
self.assertTrue(any("Home -> docs/README.md" in error for error in errors))
|
||||
self.assertTrue(
|
||||
any("Architecture-and-Code-Map" in error for error in errors)
|
||||
)
|
||||
|
||||
|
||||
class TaskTemplateTests(unittest.TestCase):
|
||||
def test_task_template_requires_document_impact(self) -> None:
|
||||
errors: list[str] = []
|
||||
check_task_template(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):
|
||||
def test_required_agent_rules_are_present(self) -> None:
|
||||
errors: list[str] = []
|
||||
check_agent_efficiency_rules(errors)
|
||||
self.assertEqual(errors, [])
|
||||
|
||||
def test_claude_code_entry_imports_shared_rules(self) -> None:
|
||||
errors: list[str] = []
|
||||
check_claude_code_entry(errors)
|
||||
self.assertEqual(errors, [])
|
||||
|
||||
def test_claude_code_entry_requires_exact_import_line(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
(root / "CLAUDE.md").write_text(
|
||||
"共同规则事实来源\n只记录 Claude Code 特有\n"
|
||||
"共同规则只修改 `AGENTS.md`\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
errors: list[str] = []
|
||||
check_claude_code_entry(errors, root)
|
||||
self.assertIn("CLAUDE.md 缺少独立的 @AGENTS.md 导入", errors)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+158
-2
@@ -10,9 +10,18 @@ from unittest.mock import Mock, patch
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / "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
|
||||
Config,
|
||||
Mapping,
|
||||
@@ -158,6 +167,153 @@ class ArchiveTests(unittest.TestCase):
|
||||
self.assertIn("Task-12-login", 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__":
|
||||
unittest.main()
|
||||
|
||||
+36
-4
@@ -17,12 +17,44 @@
|
||||
"path": "docs/01-workflow.md"
|
||||
},
|
||||
{
|
||||
"page": "Task-Archive-Template",
|
||||
"path": "docs/templates/task-archive.md"
|
||||
"page": "Architecture-and-Code-Map",
|
||||
"path": "docs/02-architecture-and-code-map.md"
|
||||
},
|
||||
{
|
||||
"page": "Task-1-Wiki-文档主源",
|
||||
"path": "docs/task/1-Wiki-文档主源.md"
|
||||
"page": "Business-Rules-and-Glossary",
|
||||
"path": "docs/03-business-rules-and-glossary.md"
|
||||
},
|
||||
{
|
||||
"page": "Local-Development-and-Verification",
|
||||
"path": "docs/04-local-development-and-verification.md"
|
||||
},
|
||||
{
|
||||
"page": "Common-Changes",
|
||||
"path": "docs/05-common-changes.md"
|
||||
},
|
||||
{
|
||||
"page": "Troubleshooting",
|
||||
"path": "docs/06-troubleshooting.md"
|
||||
},
|
||||
{
|
||||
"page": "New-Project-Documentation-Setup",
|
||||
"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",
|
||||
"path": "docs/templates/task-archive.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user