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