From fb8e787eceb06244fe9f84239c27e12fab858252 Mon Sep 17 00:00:00 2001 From: ila Date: Wed, 26 Aug 2026 20:40:21 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=8D=87=E7=BA=A7=20DevHarness=20?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=9F=BA=E7=BA=BF=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/issue_template/task.md | 29 ++-- AGENTS.md | 68 ++++++---- README.md | 8 +- dev_scripts/harness.py | 58 +++++--- docs/00-project-profile.md | 14 +- docs/01-workflow.md | 148 +++++++++++++-------- docs/07-new-project-documentation-setup.md | 22 ++- docs/09-product-requirements-overview.md | 18 +-- docs/README.md | 14 +- tests/test_harness_docs.py | 52 +++++--- 10 files changed, 262 insertions(+), 169 deletions(-) diff --git a/.gitea/issue_template/task.md b/.gitea/issue_template/task.md index 26de9b1..d85b925 100644 --- a/.gitea/issue_template/task.md +++ b/.gitea/issue_template/task.md @@ -59,15 +59,15 @@ - 修改类型:纯显示文案 / 小范围 UI / 新组件 / 新页面或独立用户功能 / 重大交互或导航 / 非 UI / 恢复既有行为的 Bug - 所需设计证据:无 / 标注截图 / 低保真图 / 已确认原型 / 架构、API、数据、状态或流程设计 / 原设计或复现证据 -- 可编辑设计源链接、版本或事实来源: -- 本地 HTML 审核快照路径和版本(不适用时说明原因): -- 本地浏览方式和资源完整性检查: -- 版本、revision 或确认日期: +- 可编辑设计源、线上原型链接和访问检查: +- 审核版本、revision、复制版本或确认日期及识别方式: +- 本地 HTML 导出:未要求 / 用户明确要求 / 项目规则要求 +- 本地 HTML 路径、版本和资源检查(仅显式导出时填写): - 状态:无 / 草稿 / 已确认 / 已废弃 - 确认人、确认时间和覆盖范围: - 无需 UI 原型或无需任何原型的原因: - + ## 文档影响 @@ -89,6 +89,15 @@ - [ ] 新增交付文档,受众与页面: - [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式: +## 任务记录与可选快照 + +- 单次任务事实来源:当前 Gitea 工单正文与评论 +- [ ] 默认不创建任务快照 +- [ ] 用户明确要求专项快照;用途和范围: +- [ ] 项目专用规则要求任务快照;规则入口: + + + ## 验收标准 - [ ] @@ -98,16 +107,6 @@ -## 完成证据 - - - -- 最终差异: -- 测试结果: -- 未验证部分: -- 提交哈希: -- 长期 Wiki 页面与 revision(无长期文档影响时填“无”): - ## 风险和回退 diff --git a/AGENTS.md b/AGENTS.md index 1838bba..d4a9e93 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Agent 开发规则 -本仓库采用 DevHarness 工作流:Gitea 工单是单次任务需求、过程、实现、测试和验收的事实来源,Gitea Wiki 只保存长期开发文档,Git 是代码与版本绑定资料的变更记录。`docs/` 默认保存核心 Wiki 的只读镜像,`docs/task/` 只保留历史兼容或人工明确要求的任务快照。人负责确认方案与验收,Agent 负责检查、实现、测试和留下证据。 +本仓库采用 DevHarness 工作流:Gitea 工单是单次任务需求、变化、实现、测试、提交和验收的事实来源,Gitea Wiki 是长期开发文档的事实来源,Git 是代码与版本绑定资料的变更记录。`docs/` 默认保存核心 Wiki 的只读镜像,`docs/task/` 只保存人工明确要求的专项或历史兼容快照。人负责确认方案与验收,Agent 负责检查、实现、测试和留下证据。 开始工作前先阅读任务涉及目录中的 `AGENTS.md`。目录越深的规则越具体,但不得削弱上级安全规则。 @@ -17,9 +17,9 @@ | 运行单元测试 | `python -m unittest discover -s tests -v` | | 导出核心 Wiki 镜像 | `python dev_scripts/harness.py sync` | | 检查核心 Wiki 镜像 | `python dev_scripts/harness.py sync --check` | -| 创建历史任务快照(按需) | `python dev_scripts/harness.py archive 123 "修复登录超时"` | -| 增量导出历史快照(按需) | `python dev_scripts/harness.py export` | -| 全量导出历史快照(按需) | `python dev_scripts/harness.py export --all` | +| 创建可选任务快照 | `python dev_scripts/harness.py archive 123 "修复登录超时"` | +| 增量导出已有快照 | `python dev_scripts/harness.py export` | +| 全量导出已有快照 | `python dev_scripts/harness.py export --all` | ## 1. 永久规则 @@ -56,11 +56,23 @@ 5. 建立新工单不要求其他工单已经完成;开始实施前检查工单声明的前置工单。真实依赖未满足时保持“待实施”,允许并行时必须写明原因。 6. 开始实施前检查分支和工作区,明确哪些现有改动不属于本任务。 7. 严格按工单范围实现;新发现的问题先记录,不顺手混入当前任务。 -8. 执行与风险相称的测试。开始实施时更新一次工单;只有方案、范围、根因、风险或阻塞发生重要变化时追加记录;完成后集中回写最终差异、测试、未验证项和提交证据。 -9. 只有长期事实变化时才更新核心文档:先修改 Wiki、读取确认,再运行一次 `sync` 和一次 `sync --check`。无长期文档影响时不运行 Wiki 同步,不得直接编辑镜像后反向覆盖 Wiki。 +8. 执行与风险相称的测试,把关键结果和未验证部分更新到工单。实施过程中出现计划外、当前无法解除的问题时才标记“阻塞”。 +9. 只有长期事实变化时才修改 Wiki、读取确认,再运行 `python dev_scripts/harness.py sync` 导出本地镜像;没有长期文档影响时在工单说明原因并跳过 Wiki 同步。不得直接编辑镜像后反向覆盖 Wiki。 + +工单正文保存用户确认的任务基线;根因、范围、方案、风险或阻塞发生重要变化时追加评论。完成实现后用一条评论集中记录最终差异、测试、未验证内容、提交哈希和文档影响;用户验收后再追加验收时间与结论,不重复覆盖或抄写已有证据。 Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明确授权,不得默认绕过建单。 +### Gitea 交互与工单最小读取 + +- 所有 Gitea 工单和 Wiki 的查询、创建、更新、评论、状态变更及关闭操作,优先使用项目已配置的 Gitea MCP。 +- MCP 不可用或不支持所需操作时才回退 Gitea API,并在当前工单记录回退原因;初始化阶段尚无工单时记录到初始化工单草稿,建单后补回。凭据只从环境或 MCP 安全配置读取。 +- 首次接手任务时读取工单确认基线和完成当前判断所需的评论,不因节省 Token 跳过范围、依赖、安全、验收或重要变更。 +- 同一任务、同一会话且关键前提未变化时,复用仍有效的工单事实,优先关注当前状态、最新评论和首个未完成步骤,不重复分析已经确认且仍有效的内容。 +- 会话、代码、配置、依赖、凭据、远端状态或关键前提变化,任务基线不清楚,或最新评论声明历史需求、方案、范围、风险或验收发生变化时,重新读取必要历史;无法判断影响范围时读取完整工单。 +- 连接器不支持评论分页或增量读取时允许读取完整工单,但不得把“已读取全文”误当成需要重新分析全部历史,也不得为规避完整读取而新增本地工单、缓存或第二事实来源。 +- 正确性、安全规则和已确认范围优先于 Token 优化;读取边界存在不确定时补读必要证据。 + ### 新项目 Wiki 初始化门禁 - 从本模板创建新项目时,先创建 Gitea 远端仓库并启用工单和 Wiki,再配置 `wiki-docs.json`;不得把模板自带的本地 `docs/` 当作新项目 Wiki 已初始化的证据。 @@ -73,14 +85,14 @@ Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明 - 纯界面显示文案只有在不改变业务含义、流程、权限、状态、接口、数据、法律/安全/支付/单位等高风险含义、国际化键、程序标识符、布局和可访问性,且没有任何不确定时,才免工单和原型;修改后执行最小界面检查。 - 新页面、独立用户功能、重大交互或导航变化,必须先用 Quant-UX 或其他合适工具制作可审阅原型;用户确认原型、文字需求和覆盖范围后,才能建立或放行实现工单并编写生产代码。 -- 上述完整原型形成待审核版本后,必须在用户审核前生成本地可浏览 HTML 快照,保存到 `prototypes/<工单号>/<版本>/index.html`;版本目录内资源使用相对路径。可编辑设计源仍在原设计工具,Git HTML 是版本化审核证据,Wiki 和工单只保存索引。 -- 已确认的 HTML 快照不得原位覆盖;页面结构、流程、状态、权限、异常处理或验收结果变化时,使用新版本目录重新导出并重新确认。提交审核前检查入口、主要交互和资源完整性,并删除凭据、账号、个人信息和生产数据。 +- 上述完整原型形成待审核版本后,默认直接通过 Quant-UX 或其他设计工具的线上链接审核,不要求每次导出本地 HTML。工单必须记录可访问链接、版本/revision 或确认日期、审核版本识别方式、确认人、确认时间和覆盖范围;线上链接无法访问或无法区分版本时停止审核,等待用户确认等效方案。 +- 只有用户明确要求 `导出原型 #N`、`导出全部原型`,或项目专用规则明确要求离线交付时,才导出到 `prototypes/<工单号>/<版本>/index.html`。已确认的本地快照不得原位覆盖;版本目录内资源使用相对路径,导出后检查入口、主要交互和资源完整性,但不自动提交。 - 现有界面的小范围样式或布局调整使用标注截图、低保真图或明确复用的现有规范;新组件记录状态、错误和边界。两者只要不符合纯文案豁免就必须建单。 - 后端、接口、数据处理和定时任务不强制 UI 原型,但必须先确认架构、API、数据、状态或流程设计;恢复既有确认行为的 Bug 可以复用原设计、截图、复现步骤或已有验收证据。 - 需要设计证据的工单记录链接或路径、版本/revision 或日期、状态、确认人、确认时间和覆盖范围;没有 UI 原型时记录替代技术设计或原因。 - 页面结构、主要流程、状态、权限、异常处理或验收结果变化时,必须更新原型或文字需求并重新确认后再继续正式编码。 - 草稿原型可以用于讨论;写入 Git/Wiki、多人协作或单独实施时建立设计任务。草稿和经明确授权的隔离技术验证都不得直接作为生产实现。 -- 设计工具无法生成可用 HTML 时,在工单记录限制并停止审核,等待用户确认等效的本地可浏览方案;不得只保留难以访问的线上链接后直接编码。纯显示文案、小范围 UI、非 UI 需求和恢复既有行为的 Bug 不强制生成 HTML。 +- 设计工具无法生成用户明确要求的可用 HTML 时,在工单记录限制并停止该导出或离线交付,等待用户确认等效方案;线上原型可访问且版本明确时不因此阻塞线上审核。纯显示文案、小范围 UI、非 UI 需求和恢复既有行为的 Bug 不强制建立完整线上原型或导出 HTML。 ### 自然语言快捷指令 @@ -88,16 +100,18 @@ Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明 - `只分析`:只读检查并给出方案;不建单、不修改,停在等待确认。 - `建工单`:根据已确认方案创建单元任务工单;建单后停止,不修改代码。 -- `执行工单 #N`:检查工单和依赖,实施、测试、提交、推送并集中回写证据;仅在长期文档变化时同步 Wiki;停在“待验收”。 +- `执行工单 #N`:检查工单和依赖,实施、测试、提交、推送并回写证据;仅在明确要求时创建任务快照;停在“待验收”。 - `建工单并做`:依次建单和执行,`建工单,做`、`建工单,做` 含义相同;停在“待验收”。 -- `继续工单 #N`:核对工单、Git 和 Wiki 证据,从首个未完成步骤继续,不重复仍然有效的检查。 +- `继续工单 #N`:优先核对当前状态、最新评论、Git 和必要 Wiki 证据,从首个未完成步骤继续;关键前提未变化时不重复读取和分析仍有效的内容。 - `检查工单 #N`:只读核对范围、验收、测试和证据并输出报告;不自动修复。 - `同步文档`:读取 Wiki、导出核心 `docs/` 并检查一致性,不处理任务归档;不修改 Wiki、不自动提交。 -- `导出任务归档`:历史兼容指令;用户明确要求时运行 `python dev_scripts/harness.py export`,只导出新增或 revision 已变化的 Wiki 任务快照;不删除本地文件、不自动提交。 -- `导出全部任务归档`:历史兼容指令;用户明确要求时运行 `python dev_scripts/harness.py export --all`,读取并导出全部线上任务快照;不删除本地文件、不自动提交。 -- `#N 验收通过`:仅在用户明确验收后,在工单记录验收结论,按需推送尚未推送的提交、同步父工单并关闭任务;不创建任务归档,不重复同步无变化的 Wiki。 +- `导出原型 #N`:人工触发导出指定工单已确认的原型版本,按工单和版本写入 `prototypes/`;不扩展范围、不自动提交。 +- `导出全部原型`:人工触发导出当前项目已明确范围内的全部已确认原型;不自动提交。 +- `导出任务归档`:人工触发 `python dev_scripts/harness.py export`,只导出新增或 revision 已变化的任务归档;不删除本地文件、不自动提交。 +- `导出全部任务归档`:人工触发 `python dev_scripts/harness.py export --all`,读取并导出全部线上任务归档;不删除本地文件、不自动提交。 +- `#N 验收通过`:仅在用户明确验收后,在工单追加验收结论;按需更新真实变化的长期 Wiki,推送、同步父工单并关闭任务;不创建或导出任务归档。 -方案未确认或前置依赖未满足时,实施类指令必须停在对应门禁;除 `#N 验收通过` 外,快捷指令不得关闭待验收工单。历史任务快照的创建和导出必须由用户明确提出,其他指令不得隐式执行。Gitea 工单不导出全文,`docs/task/` 只是可能不完整的历史快照。详细语义见 [开发工作流](docs/01-workflow.md)。 +方案未确认或前置依赖未满足时,实施类指令必须停在对应门禁;除 `#N 验收通过` 外,快捷指令不得关闭待验收工单。原型和任务快照的导出必须由用户明确提出或项目专用规则明确要求,其他指令不得隐式执行。Gitea 工单不导出全文,`docs/task/` 只是可能不完整的专项或历史兼容快照。详细语义见 [开发工作流](docs/01-workflow.md)。 ### 需求记录与流转 @@ -105,13 +119,13 @@ Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明 - 工单中的目标、非目标、已确认方案、验收标准和文档影响构成确认后的正式任务需求。 - 影响范围、接口、数据、风险或验收的需求变化必须记录日期、内容、原因和用户确认;会改变已确认结果时先更新工单并等待再次确认。 - 不复制完整聊天,不保存 Agent 内部推理,不写入密码、令牌、个人数据或生产数据;包含敏感信息的原话必须删除敏感部分或改写为脱敏摘要。 -- 长期有效的产品需求、业务规则和系统边界进入对应 Wiki 主题页并导出核心 `docs/`;完成结果、测试、提交和验收留在 Gitea 工单。`docs/task/` 只在用户明确要求历史快照时使用,Gitea 工单全文不导出到仓库。 +- 长期有效的产品需求、业务规则和系统边界进入对应 Wiki 主题页并导出核心 `docs/`;单次任务的完成结果和验收保留在工单正文与评论。只有用户明确要求专项快照或项目专用规则要求时才创建 Wiki 任务快照并按需导出 `docs/task/`。Gitea 工单全文不导出到仓库。 详细记录边界见 [开发工作流](docs/01-workflow.md) 与 [业务规则和术语](docs/03-business-rules-and-glossary.md)。 ### 效率与范围控制 -本节只用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、按需 Wiki 同步、Git 提交和人工验收要求。 +本节只用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、必要的长期文档同步、Git 提交和人工验收要求。 #### 严格控制范围 @@ -163,19 +177,19 @@ Gitea 不可用时,输出完整工单草稿并说明阻塞。未经用户明 - 实现提交信息引用工单号,例如:`fix: 修复登录超时 (#123)`。 - 不为流程制造空提交。 - 优先运行项目档案中记录的格式检查、静态检查、单元测试和必要的集成测试。 -- 不能验证的真机、生产、迁移或并发行为必须写入工单。 +- 不能验证的真机、生产、迁移或并发行为必须写入工单;存在明确要求的任务快照时再同步记录。 -## 7. 完成、验收和关闭 +## 7. 完成和验收 -1. 逐项完成验收、测试和实现提交,并把最终方案、差异、结果、提交及遗留问题写回工单。 +1. 逐项完成验收、测试和实现提交,在工单追加最终证据评论,记录最终方案、差异、结果、提交、遗留问题和文档影响。 2. 工单保持“待验收”,用户没有明确验收通过前不得关闭。 -3. 只有长期文档发生变化时,读取确认 Wiki,运行一次 `sync` 和一次 `sync --check`,并把页面 revision 写回工单;无长期文档影响时跳过。 -4. 用户验收通过后,在工单记录验收结论,关闭单元工单,并同步更新 MVP 和 Epic;不重复抄写已有证据或同步无变化的 Wiki。 -5. `archive`、`export` 和 `export --all` 仅作为历史兼容能力,在用户明确要求专项快照时使用,不属于标准完成流程。 +3. 有长期文档影响时,读取确认 Wiki,运行 `python dev_scripts/harness.py sync --check` 检查核心镜像,并把页面 revision 和镜像提交哈希写回工单;没有长期文档影响时不运行 Wiki 同步。 +4. 用户验收通过后,在工单追加验收时间和结论,关闭单元工单,并同步更新 MVP 和 Epic;没有真实变化的 Wiki 不重复更新或检查。 +5. 默认不创建任务归档。只有用户明确要求专项快照或项目专用规则明确要求时,才运行 `python dev_scripts/harness.py archive <编号> "<短标题>"`;`export` 和 `export --all` 同样必须显式触发。 MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才能关闭 MVP。Epic 的全部范围完成后才能关闭 Epic。 -详细完成顺序和证据边界见 [开发工作流](docs/01-workflow.md)。 +详细证据回写、可选快照和文档同步边界见 [开发工作流](docs/01-workflow.md)。 ## 8. 可维护性 @@ -198,7 +212,7 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才 - 启动、测试、部署、排错命令,模块入口、目录职责、主要调用路径,配置、API、数据结构、状态、业务规则、安全边界、日志位置发生变化时,必须更新对应 Wiki。 - 部署命令变化时,有常驻服务的项目更新自己的 `Deployment-and-Operations` 页面(由 [部署文档模板](docs/templates/deployment.md) 复制建立);没有常驻服务的项目记录为无部署文档影响,不创建空的部署页。 - 普通内部重构只有在入口、行为、配置和验证方式均未改变时,才可以记录为不影响长期文档。 -- 必需核心页面及结构以 `python dev_scripts/harness.py check --strict` 和 [新项目文档初始化](docs/07-new-project-documentation-setup.md) 为准;稳定文档、工单和历史快照的分工见 [开发工作流](docs/01-workflow.md)。 +- 必需核心页面及结构以 `python dev_scripts/harness.py check --strict` 和 [新项目文档初始化](docs/07-new-project-documentation-setup.md) 为准;稳定文档与可选历史快照的分工见 [开发工作流](docs/01-workflow.md)。 ## 9. 引导提交例外 @@ -210,9 +224,9 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才 -- 长期开发文档以 Gitea Wiki 为事实来源,`docs/` 默认保存显式映射生成的核心只读镜像;`docs/task/` 是人工按需快照,可能不完整或不是最新状态。 +- 长期开发文档以 Gitea Wiki 为事实来源,单次任务证据以 Gitea 工单为事实来源;`docs/` 默认保存显式映射生成的核心只读镜像,`docs/task/` 是人工明确要求的专项或历史兼容快照,可能不完整或不是最新状态。 - 核心 Wiki 与镜像的固定顺序是:修改 Wiki → 读取确认 → 导出核心 `docs` → 校验差异 → 提交镜像。 -- 新任务默认不创建 Wiki 任务归档;既有归档与 `docs/task/` 作为历史兼容内容保留。创建或导出任务快照必须由用户明确提出,且不得自动传播删除或重命名。 +- 默认不创建任务归档;`archive`、`导出任务归档` 或 `导出全部任务归档` 必须由用户明确提出或项目专用规则明确要求,且不得自动传播删除或重命名。 - 同步配置只允许写入 `docs/` 下的 Markdown;发现镜像有未提交修改时必须停止。 - Gitea 凭据只通过进程环境或 MCP 安全配置提供,不得写入仓库。 - `dev_scripts/` 只存放 DevHarness 自身工具;业务项目的通用脚本必须使用独立目录,不得混放。 diff --git a/README.md b/README.md index fd94a06..5ebe8ae 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ chorus 是把 cmhub(Django)中的「提示词 + 原图 → 新图」和「 - 不改动 cmhub,也不依赖 cmhub 运行;核心逻辑是**重写移植**而非代码复用。 - 技术栈:Go + Gin + GORM + go-admin(管理端)+ html/template + HTMX + Alpine(用户端),MySQL 8.0,单库。 -- 开发过程遵循 DevHarness:Gitea 工单管理任务、Gitea Wiki 管理长期文档、Git 记录代码变更、人工确认与验收。 +- 开发过程遵循 DevHarness:Gitea 工单是单次任务唯一事实来源,Gitea Wiki 管理长期文档,Git 记录代码变更,由人工确认方案与验收。 ## 当前阶段 @@ -30,6 +30,8 @@ MVP-0 的范围、非目标和验收口径见 [产品需求总览](docs/09-produ 新仓库在 Gitea 尚未建立前允许一次不关联工单的引导提交。远端和工单系统配置完成后,新功能、接口/配置契约、数据库、高风险、跨模块和重大 UI 工作必须先有单元任务工单;明确的低风险修改边界见开发工作流。 +默认不创建任务归档。任务专项快照和原型 HTML 只在用户明确要求或项目专用规则要求时创建;已有快照继续作为历史证据保留。 + ## 文档入口 | 想知道什么 | 读哪里 | @@ -53,8 +55,8 @@ AGENTS.md Agent 的通用工作规则 CLAUDE.md Claude Code 的规则入口 .gitea/issue_template/ Epic、MVP、单元任务工单模板 docs/ 核心长期文档(Wiki 初始化后转为只读镜像) -docs/task/ 历史兼容或人工明确要求的 Wiki 任务快照 -prototypes/ 按工单和版本保存的本地 HTML 审核快照 +docs/task/ 人工明确要求的专项或历史兼容 Wiki 快照 +prototypes/ 按需导出的本地 HTML 原型快照 wiki-docs.json 核心 Wiki 页面到本地镜像的显式映射 dev_scripts/harness.py check / sync 入口,兼容 archive / export tests/ Harness 工具自动化测试 diff --git a/dev_scripts/harness.py b/dev_scripts/harness.py index d8bcb86..bea9576 100644 --- a/dev_scripts/harness.py +++ b/dev_scripts/harness.py @@ -1,10 +1,10 @@ """DevHarness 单一命令行入口。 子命令: - check 检查必需文件、核心文档和已有历史任务快照结构 + check 检查必需文件、核心文档和已有任务快照结构 sync 从 Gitea Wiki 单向导出或校验核心 docs 镜像 - archive 按用户明确要求在 Gitea Wiki 创建历史任务快照 - export 按用户明确要求把 Wiki 历史任务快照导出到 docs/task + archive 显式在 Gitea Wiki 创建可选任务快照 + export 人工按需把已有 Wiki 任务快照导出到 docs/task 各子命令的实现逻辑取自原来的 check_harness.py、sync_wiki_docs.py、 new_task_archive.py 和 export_task_archives.py,行为未改变。 @@ -76,16 +76,17 @@ CORE_DOCUMENT_REQUIREMENTS = { "## 环境、配置与凭据", ), "docs/01-workflow.md": ( + "## Gitea 交互与工单最小读取", "## 新项目 Wiki 初始化门禁", "## 工单与设计证据双门禁", "### 先判断是否需要工单", "### 再判断设计证据", - "### 本地 HTML 审核快照", + "### 线上原型审核与按需导出", "### 记录和重新确认", "## 面向初级维护者的修改边界", "## 每个任务的文档影响", "## 需求记录与流转", - "## 稳定文档与历史任务快照", + "## 稳定文档与可选历史快照", "## 自然语言快捷指令", "## 效率与范围控制", "### 严格控制范围", @@ -125,6 +126,7 @@ CORE_DOCUMENT_REQUIREMENTS = { "## 初始化顺序", "#### 需求总览启用条件", "### 2. 选择建设基线", + "#### 工程基线裁剪", "#### 判断案例", "### 3. 识别子项目与交付单元", "### 7. 确定交付对象和文档", @@ -157,7 +159,7 @@ CORE_DOCUMENT_REQUIREMENTS = { "## 登记规则", "## 原型与设计资产", "### 原型门禁", - "### 本地 HTML 审核快照", + "### 线上原型与按需 HTML 快照", "### 原型确认记录", "## 状态规则", "## 更新时机", @@ -289,10 +291,10 @@ def check_task_template(errors: list[str], root: Path = ROOT) -> None: "## 设计与原型门禁", "- 修改类型:纯显示文案 / 小范围 UI / 新组件 / 新页面或独立用户功能 / 重大交互或导航 / 非 UI / 恢复既有行为的 Bug", "- 所需设计证据:无 / 标注截图 / 低保真图 / 已确认原型 / 架构、API、数据、状态或流程设计 / 原设计或复现证据", - "- 可编辑设计源链接、版本或事实来源:", - "- 本地 HTML 审核快照路径和版本(不适用时说明原因):", - "- 本地浏览方式和资源完整性检查:", - "- 版本、revision 或确认日期:", + "- 可编辑设计源、线上原型链接和访问检查:", + "- 审核版本、revision、复制版本或确认日期及识别方式:", + "- 本地 HTML 导出:未要求 / 用户明确要求 / 项目规则要求", + "- 本地 HTML 路径、版本和资源检查(仅显式导出时填写):", "- 状态:无 / 草稿 / 已确认 / 已废弃", "- 确认人、确认时间和覆盖范围:", "- 无需 UI 原型或无需任何原型的原因:", @@ -306,12 +308,11 @@ def check_task_template(errors: list[str], root: Path = ROOT) -> None: "- [ ] 更新已有交付文档,受众与页面:", "- [ ] 新增交付文档,受众与页面:", "- [ ] 需要目标岗位或客户代表验证:是 / 否;验证方式:", - "## 完成证据", - "- 最终差异:", - "- 测试结果:", - "- 未验证部分:", - "- 提交哈希:", - "- 长期 Wiki 页面与 revision(无长期文档影响时填“无”):", + "## 任务记录与可选快照", + "- 单次任务事实来源:当前 Gitea 工单正文与评论", + "- [ ] 默认不创建任务快照", + "- [ ] 用户明确要求专项快照;用途和范围:", + "- [ ] 项目专用规则要求任务快照;规则入口:", ) for section in missing_sections(content, required): errors.append(f"单元任务模板缺少:{section}") @@ -331,7 +332,14 @@ def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None: "单元任务是唯一正式实施单位", "高风险修改必须停止", "用户没有明确验收通过前不得关闭", - "只有长期事实变化时才更新核心文档", + "只有长期事实变化时才修改 Wiki", + "Gitea 工单是单次任务需求、变化、实现、测试、提交和验收的事实来源", + "默认不创建任务归档", + "### Gitea 交互与工单最小读取", + "查询、创建、更新、评论、状态变更及关闭操作", + "优先关注当前状态、最新评论和首个未完成步骤", + "连接器不支持评论分页或增量读取时允许读取完整工单", + "不得为规避完整读取而新增本地工单、缓存或第二事实来源", "### 新项目 Wiki 初始化门禁", "`Home` 不存在时必须先创建 `Home`", "不得把模板自带的本地 `docs/` 当作新项目 Wiki 已初始化的证据", @@ -339,7 +347,10 @@ def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None: "### 工单与设计证据双门禁", "新页面、独立用户功能、重大交互或导航变化", "`prototypes/<工单号>/<版本>/index.html`", - "已确认的 HTML 快照不得原位覆盖", + "默认直接通过 Quant-UX 或其他设计工具的线上链接审核", + "已确认的本地快照不得原位覆盖", + "`导出原型 #N`", + "`导出全部原型`", "代码组件名、类名、变量、国际化键、API 字段和数据库字段不是显示文案", "### 自然语言快捷指令", "`只分析`", @@ -349,6 +360,8 @@ def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None: "`继续工单 #N`", "`检查工单 #N`", "`同步文档`", + "`导出原型 #N`", + "`导出全部原型`", "`导出任务归档`", "`导出全部任务归档`", "`#N 验收通过`", @@ -356,7 +369,6 @@ def check_agent_efficiency_rules(errors: list[str], root: Path = ROOT) -> None: "不得臆造用户原话", "不复制完整聊天", "Gitea 工单全文不导出到仓库", - "新任务默认不创建 Wiki 任务归档", ) for section in missing_sections(content, required): errors.append(f"AGENTS.md 缺少:{section}") @@ -375,6 +387,8 @@ def check_repository_readme(errors: list[str], root: Path = ROOT) -> None: "`Home` 不存在时先创建并回读 `Home`", "本地 `docs/` 的存在不能证明线上 Wiki 已初始化", "python dev_scripts/harness.py sync --verify", + "Gitea 工单是单次任务唯一事实来源", + "默认不创建任务归档", ) for section in missing_sections(content, required): errors.append(f"README.md 缺少:{section}") @@ -682,7 +696,7 @@ def run_export(args: argparse.Namespace) -> int: def main() -> int: - parser = argparse.ArgumentParser(description="DevHarness 检查、同步与历史快照兼容工具") + parser = argparse.ArgumentParser(description="DevHarness 检查、同步与归档工具") sub = parser.add_subparsers(dest="command", required=True) p_check = sub.add_parser("check", help="检查 DevHarness 项目结构") @@ -705,7 +719,7 @@ def main() -> int: ) p_sync.set_defaults(func=run_sync) - p_archive = sub.add_parser("archive", help="按明确要求在 Gitea Wiki 创建历史任务快照") + p_archive = sub.add_parser("archive", help="显式在 Gitea Wiki 创建可选任务快照") p_archive.add_argument("issue_number", help="Gitea 工单号,例如 123") p_archive.add_argument("title", help="简短任务标题") p_archive.add_argument( @@ -713,7 +727,7 @@ def main() -> int: ) p_archive.set_defaults(func=run_archive) - p_export = sub.add_parser("export", help="按明确要求导出 Gitea Wiki 历史任务快照") + p_export = sub.add_parser("export", help="人工按需导出 Gitea Wiki 任务归档") p_export.add_argument( "--all", action="store_true", diff --git a/docs/00-project-profile.md b/docs/00-project-profile.md index 41cba84..702c5ee 100644 --- a/docs/00-project-profile.md +++ b/docs/00-project-profile.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Project-Profile wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Project-Profile.- -wiki_revision: cd93968f7c48ebbe0a594f6198c29726e8ac9c3e -synchronized_at: 2026-08-25T07:00:30Z +wiki_revision: 9966ce2c233336465514115adf51545dda55efb3 +synchronized_at: 2026-08-26T12:37:12Z # 项目档案 @@ -33,9 +33,9 @@ synchronized_at: 2026-08-25T07:00:30Z | 项目 | 内容 | |---|---| | DevHarness 来源仓库 | `https://git.ilapage.cn/OPC/dev_harness` | -| 当前基线提交 | `3696663781c569c57f47bb26e3b5b6369180fdaa` | -| 最后接入或升级日期 | 2026-08-20 | -| 项目适配说明 | 完整保留 Harness 规则、工单模板、Wiki 镜像与结构检查工具;`docs/00`、`02`–`06`、`09` 和 `docs/README.md` 改写为 chorus 内容,`docs/01`、`07`、`08`、`delivery/`、`templates/` 沿用上游文本 | +| 当前基线提交 | `0b6ec7675dfc2d930a30527eddac83f4302d0879` | +| 最后接入或升级日期 | 2026-08-26 | +| 项目适配说明 | 增量采用 Harness 规则、工单模板、Wiki 镜像与结构检查工具;`docs/00`、`02`–`06`、`09` 和 `docs/README.md` 按 Chorus 改写,`docs/01`、`07`、`08`、`delivery/`、`templates/` 沿用上游通用规则;保留 Chorus 项目红线和单人开发低风险直接提交边界 | ## 子项目与交付单元 @@ -137,8 +137,8 @@ synchronized_at: 2026-08-25T07:00:30Z | `admin-ui/` | 固定 go-admin-ui 导入代码与定制页 | 运行时依赖 `D:\github\goadmin` | | `migrations/` | 全部生产表结构与配置种子 SQL | 测试数据、AutoMigrate、不可逆一次性修数 | | `docs/` | 核心长期文档的 Wiki 只读镜像 | 人工直接维护的最终事实 | -| `docs/task/` | 历史兼容:仅按用户明确要求导出的 Wiki 任务快照 | 新任务的标准完成证据和默认自动导出 | -| `prototypes/` | 按工单/版本保存 HTML 审核快照 | 凭据、个人信息、生产数据 | +| `docs/task/` | 仅保存用户明确要求的专项或历史兼容 Wiki 任务快照 | 单次任务的默认证据和自动导出 | +| `prototypes/` | 按明确要求导出的工单/版本 HTML 原型快照;已有快照保留为历史证据 | 凭据、个人信息、生产数据 | | `scripts/` | Chorus 本地开发与运行辅助脚本 | DevHarness 工具、凭据和生产数据 | | `dev_scripts/` | DevHarness 工具 | 产品业务脚本 | | `tests/` | Harness 测试;Go 测试与代码同目录 | 生产数据 | diff --git a/docs/01-workflow.md b/docs/01-workflow.md index b905b3f..28ae986 100644 --- a/docs/01-workflow.md +++ b/docs/01-workflow.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Development-Workflow wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Development-Workflow.- -wiki_revision: 2226a80884a2363522cf856a0edafe42f74df8a3 -synchronized_at: 2026-08-24T07:59:22Z +wiki_revision: 33350ca4800cbe9124f1438a31077ff0191e23a5 +synchronized_at: 2026-08-26T12:37:20Z # 开发工作流 @@ -11,10 +11,20 @@ synchronized_at: 2026-08-24T07:59:22Z ## 事实来源边界 - Gitea 工单记录任务状态、讨论、阻塞、方案变化、验证和验收。 -- Gitea Wiki 只保存长期有效的架构说明、开发规范和操作手册;单次任务结果留在 Gitea 工单。 +- Gitea Wiki 保存长期架构、契约、业务规则、开发规范、操作手册和稳定需求;默认不重复保存单次任务归档。 - Git 保存源码、与特定代码版本强绑定的文档,以及 Wiki 的本地镜像。 - 本地 `docs/` 仅供浏览和审查,不是长期文档编辑入口。 +## Gitea 交互与工单最小读取 + +- 所有 Gitea 工单和 Wiki 的查询、创建、更新、评论、状态变更及关闭操作,优先使用项目已配置的 Gitea MCP。 +- MCP 不可用或不支持所需操作时才回退 Gitea API,并在当前工单记录回退原因;初始化阶段尚无工单时记录到初始化工单草稿,建单后补回。凭据只从环境或 MCP 安全配置读取。 +- 首次接手任务时读取工单确认基线和完成当前判断所需的评论,不因节省 Token 跳过范围、依赖、安全、验收或重要变更。 +- 同一任务、同一会话且关键前提未变化时,复用仍有效的工单事实,优先关注当前状态、最新评论和首个未完成步骤,不重复分析已经确认且仍有效的内容。 +- 会话、代码、配置、依赖、凭据、远端状态或关键前提变化,任务基线不清楚,或最新评论声明历史需求、方案、范围、风险或验收发生变化时,重新读取必要历史;无法判断影响范围时读取完整工单。 +- 连接器不支持评论分页或增量读取时允许读取完整工单,但不得把“已读取全文”误当成需要重新分析全部历史,也不得为规避完整读取而新增本地工单、缓存或第二事实来源。 +- 正确性、安全规则和已确认范围优先于 Token 优化;读取边界存在不确定时补读必要证据。 + ## 新项目 Wiki 初始化门禁 从 DevHarness 创建新项目时,本地 `docs/` 即使完整存在,也只能证明模板镜像存在,不能证明新项目的线上 Wiki 已初始化。开始任何产品代码前必须完成以下闭环: @@ -33,29 +43,16 @@ Gitea 暂时不可用时可以准备工单和 Wiki 草稿,但不得把本地 ### 先判断是否需要工单 -以下改动必须建立单元任务工单: - -- 新功能、数据库迁移、API 或运行时配置契约变化; -- 权限、安全、凭据、并发、数据删除、发布或其他高风险操作; -- 跨模块行为变化、重构、重大 UI、交互或导航变化; -- 无法确定影响范围、风险或是否改变既有行为的修改。 - -以下修改同时满足“范围明确、容易回退、不涉及上述必须建单项”时可以直接提交: - -- 错别字、注释、文档措辞、格式化、导入排序、单文件内部变量改名; -- 不改变产品行为的类型标注、文档字符串、测试或已确认死代码清理; -- 单文件低风险缺陷,且只是恢复已有明确行为,不改变接口、数据库、状态、权限、安全、并发、流程、布局或可访问性; -- 纯界面显示文案,并满足本页的全部文案豁免条件。 - -直接提交仍要保留无关工作区改动、执行受影响的最小验证并写清提交说明。有任何不确定就建单。 - -纯界面显示文案豁免还必须同时满足: +只有纯界面显示文案同时满足以下全部条件时,才可以免工单、免原型: - 只修改用户看到的组件显示名称、按钮文字、标题、提示语或其他文案; - 不改变业务含义、操作流程、权限、状态、接口、数据和验收结果; - 不涉及法律条款、安全提示、支付、金额、单位或其他高风险含义; - 不修改国际化键、代码组件名、类名、变量、API 字段、数据库字段或其他程序标识符; -- 不造成明显布局、截断、换行、可访问性或支持平台问题。 +- 不造成明显布局、截断、换行、可访问性或支持平台问题; +- 有任何不确定时不使用豁免。 + +豁免修改只执行与受影响界面相称的最小检查,确认文字正确且没有明显布局或可访问性问题,然后停止。只要任一条件不满足,或涉及用户行为、样式布局、交互和导航,就建立单元任务工单。 ### 再判断设计证据 @@ -70,25 +67,33 @@ Gitea 暂时不可用时可以准备工单和 Wiki 草稿,但不得把本地 采用最低成本、足以让用户确认的证据,不为了形式制作高保真原型。草稿原型可以用于需求讨论;草稿需要写入 Git/Wiki、多人协作或单独实施时,应建立设计任务。草稿原型和临时技术验证都不能直接作为生产实现。 -### 本地 HTML 审核快照 +### 线上原型审核与按需导出 -新页面、独立用户功能、重大交互或导航变化使用 Quant-UX 或等效工具形成待审核版本后,必须在用户审核前生成本地可浏览 HTML 快照: +新页面、独立用户功能、重大交互或导航变化使用 Quant-UX 或等效工具形成待审核版本后,默认直接通过线上原型审核,不要求每次导出本地 HTML: -- 可编辑设计源仍保存在 Quant-UX 或原设计工具;Git 中的 HTML 只是与需求和代码版本绑定的审核证据,Wiki 和工单只保存索引与确认记录。 -- 快照放入 `prototypes/<工单号>/<版本>/index.html`;图片、样式、脚本和字体使用该版本目录内的相对路径。需要网络资源才能显示时,不得标记为可离线浏览。 -- 用户通过 `index.html` 审核;浏览器限制直接打开时,在工单记录最小本地静态服务命令和访问地址,不新增项目专用服务脚本。 -- 提交或请求审核前检查入口可打开、主要页面和交互可访问、图片和字体不缺失,并删除令牌、账号、个人信息和生产数据。 -- 页面结构、主要流程、状态、权限、异常处理或验收结果发生变化时,在新版本目录重新导出并重新确认;不得覆盖已经确认的版本。 -- 纯显示文案、小范围现有 UI 调整、非 UI 需求和恢复既有行为的 Bug 不强制生成 HTML;仍使用双门禁表规定的最低证据。 -- 设计工具无法生成可用 HTML 时必须在工单说明限制并停止审核,由用户确认等效的本地可浏览原型方案;不得只保留难以访问的线上链接后直接编码。 +- 可编辑设计源保存在 Quant-UX 或原设计工具;工单和 Wiki 只保存链接、版本与确认记录,不复制为第二份可编辑事实来源。 +- 线上链接必须能被确认人访问,并能通过版本、revision、复制版本或确认日期识别本次审核对象;无法访问或无法区分版本时停止审核,等待用户确认等效方案。 +- 提交审核前检查主要页面、流程、状态和交互可访问,并删除令牌、真实账号、个人信息和生产数据。 +- 页面结构、主要流程、状态、权限、异常处理或验收结果变化时,更新线上原型并重新确认;不得用旧确认覆盖新版本。 +- 纯显示文案、小范围现有 UI 调整、非 UI 需求和恢复既有行为的 Bug 仍只使用双门禁表规定的最低证据,不强制建立完整线上原型。 + +只有用户明确发出 `导出原型 #N`、`导出全部原型`,或项目专用规则明确要求离线交付时,才导出本地 HTML: + +- 指定工单的快照放入 `prototypes/<工单号>/<版本>/index.html`;全部导出时也按工单和版本分目录,先在工单明确导出范围。 +- 图片、样式、脚本和字体使用版本目录内的相对路径;需要网络资源才能显示时不得标记为可离线浏览。 +- 已确认的本地快照不得原位覆盖;新版本使用新目录,已有快照继续作为历史审核证据。 +- 导出后检查入口、主要交互和资源完整性;浏览器限制直接打开时,在工单记录最小本地静态服务命令和访问地址,不新增项目专用服务脚本。 +- 导出指令只生成或更新请求范围内的快照并报告结果,不自动提交;用户未明确要求时不得顺带导出其他原型。 +- 设计工具无法生成用户要求的可用 HTML 时,在工单记录限制并停止该导出或离线交付,等待用户确认等效方案;线上原型仍可访问且版本明确时,不因此阻塞线上审核。 ### 记录和重新确认 需要设计证据的工单必须记录: -- 原型或设计的链接、Git 路径或对应事实来源; -- 版本、revision 或确认日期; +- 原型或设计的线上链接、对应事实来源,以及链接可访问性; +- 版本、revision、复制版本或确认日期,以及审核版本的识别方式; - 状态:无、草稿、已确认或已废弃; +- 只有显式导出时才记录本地 HTML 路径、版本和资源检查结果; - 确认人和确认时间; - 本次确认覆盖的页面、组件、流程和边界; - 不需要 UI 原型时采用的技术设计,或无需任何原型的原因。 @@ -137,40 +142,61 @@ Gitea 暂时不可用时可以准备工单和 Wiki 草稿,但不得把本地 Agent 检查分支和工作区,只修改工单范围内的文件。发现新问题时先记录到工单;如果不影响当前验收,则另建工单,不扩大当前任务。 -工单以两次集中更新为默认节奏: +重要进度及时写回工单: -1. 开始实施时将状态改为“进行中”,记录已确认方案、依赖和范围;只有根因、范围、方案、阻塞或风险发生重要变化时追加更新。 -2. 实现与测试完成后集中写入最终差异、测试结果、未验证内容、提交哈希和长期 Wiki 页面 revision,并改为“待验收”。 +- 已确认的根因; +- 方案或范围变化; +- 测试结果; +- 阻塞和未验证内容; +- Git 提交哈希; +- 相关 Wiki 页面及 revision。 -长期核心文档仅在启动、部署、架构、接口、数据结构、业务规则、安全边界等长期事实变化时更新。需要更新时遵循: +工单正文保存用户确认的任务基线;根因、范围、方案、风险或阻塞发生重要变化时追加评论。完成实现后用一条评论集中记录最终差异、测试、未验证内容、提交哈希和长期文档影响,保留可追溯时间线,不在 Wiki 重抄同一份任务结果。 + +只有长期事实发生变化时才执行核心文档闭环: ```text -修改 Wiki → 在线回读 revision → sync 导出 docs → sync --check → 提交镜像 +修改 Wiki → 读取确认 → 导出核心 docs → 校验差异 → 提交镜像 ``` -无长期文档影响的任务不运行 Wiki 同步。不得先编辑本地镜像再反向覆盖 Wiki。 +没有长期文档影响时,在工单写明原因并跳过 Wiki 更新和核心镜像同步;默认任务流程不创建任务归档。长期文档仍不得先编辑本地镜像再反向覆盖 Wiki。 ### 4. 待验收 实现和测试完成后,Agent 提交实现代码并将工单更新为“待验收”。用户验收前工单保持开启。 -### 5. 验收和关闭 +### 5. 待验收和关闭 -用户明确验收通过后,在工单记录验收结论,关闭单元工单,并勾选所属 MVP 和 Epic 的任务索引。验收时不重复抄写已经记录的测试和提交证据,也不再次同步没有变化的 Wiki 页面。 +实现、必要测试和提交完成后,在工单追加一条最终证据评论并保持“待验收”。评论至少记录最终差异、测试结果、未验证内容、提交哈希,以及长期 Wiki 页面和 revision,或“无长期文档影响”及原因。 -历史兼容命令 `archive`、`export` 和 `export --all` 仅在用户明确要求保留专项快照时使用,不属于标准任务完成流程。既有 Wiki 任务归档和 `docs/task/` 快照继续保留,不自动删除、改名或补齐。 +用户明确验收通过后: + +1. 在工单追加验收时间和结论,不重复抄写已有测试与提交证据; +2. 关闭单元工单并勾选所属 MVP/Epic 子任务; +3. 只有验收结论改变长期需求状态或其他 Wiki 事实时,才更新 Wiki 并执行同步闭环;没有变化时不重复检查 Wiki; +4. 默认不创建或导出任务归档。 + +任务归档只保留为显式兼容能力。只有用户明确要求专项快照,或项目专用规则明确要求时才运行: + +```powershell +python dev_scripts/harness.py archive 123 "修复登录超时" +python dev_scripts/harness.py export # 增量导出已有归档 +python dev_scripts/harness.py export --all # 全量导出已有归档 +``` + +可选归档不得成为第二个日常维护入口;创建时以工单中的最终证据为来源,并记录工单链接。既有 Wiki 归档和 `docs/task/` 快照不自动删除、重命名或补齐。 ## 文档同步规则 - 核心页面映射保存在 `wiki-docs.json`;普通同步只处理这些核心长期文档。 -- 历史任务归档不逐页登记映射;用户明确要求导出时,由兼容工具根据 `Task-<编号>-<标题>` 动态发现,已有镜像优先按镜像头匹配原页面。 +- 可选任务归档不逐页登记映射;显式执行归档导出时,工具根据 `Task-<编号>-<标题>` 动态发现,已有镜像优先按镜像头匹配原页面。 - 所有同步和导出只实现 Wiki → `docs/`,不提供反向同步。 - 镜像头必须记录页面名、页面地址、revision 和同步时间。 - 已跟踪镜像存在未提交改动时,同步必须停止;确认改动来源后再处理。 -- 只有长期文档发生变化时才运行核心同步;一次 `sync` 后运行一次 `sync --check`,不因归档或验收重复执行。`--check` 不要求历史任务归档全部存在于本地。 +- 核心同步的 `--check` 只检查核心镜像,不要求线上任务归档全部存在于本地。 - 已经导出的任务镜像仍必须具有来源页面、revision 和同步时间,并通过 Harness 格式检查。 - 页面删除和重命名不会自动传播,必须先更新工单并人工确认映射变化。 -- Wiki 更新成功而核心镜像导出失败时,在工单记录部分完成状态,不得把任务标为待验收。 +- Wiki 更新成功而导出失败时,在工单记录部分完成状态,不得把任务标为完成。 - 与具体代码版本强绑定的接口或迁移资料可直接随代码维护,但必须在 Wiki 提供入口或适用版本说明。 ## 面向初级维护者的修改边界 @@ -224,20 +250,20 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新 | 关键原始需求、确认后的单次任务需求 | Gitea 单元任务工单 | 无 | | 讨论、决定和需求变化 | Gitea 工单正文或评论 | 无 | | 长期有效的产品需求、业务规则和系统边界 | 对应 Gitea Wiki 主题页 | `docs/` | -| 完成后的实现、验证、提交和遗留问题 | Gitea 单元任务工单 | 无 | +| 完成后的实现、验证、遗留问题和验收 | Gitea 单元任务工单正文与评论 | 无;用户明确要求时可创建专项 Wiki 快照 | 任务产生长期结论时,先更新对应 Wiki 主题页,再导出本地镜像。Gitea 工单全文不导出到仓库,避免形成第二份任务过程记录。 -## 稳定文档与历史任务快照 +## 稳定文档与可选历史快照 - Home、项目档案、代码地图、业务规则、开发验证、常见修改和故障排查描述项目现在怎样工作。 -- Gitea 工单解释某次为什么修改、实际改了什么以及如何验证,是单次任务证据的事实来源。 -- 既有 Wiki 任务归档与 `docs/task/` 仅是历史或人工专项快照,不要求为新任务创建;新人先读稳定主题页,追查历史时优先读工单。 -- 任务产生的长期结论必须合并到对应主题页,不能只留在工单。 +- 工单正文和评论解释某次为什么修改、实际改了什么、如何验证以及怎样验收。 +- 新人先读稳定主题页,只有追查历史原因时才读工单;可选 Wiki 快照和本地任务快照只是专项或历史兼容资料,不是默认事实来源。 +- 任务产生的长期结论必须合并到对应主题页,不能只留在工单或可选快照。 ## 效率与范围控制 -本节用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、按需 Wiki 同步、Git 提交和人工验收要求。 +本节用于减少无关工作和重复检查,不得削弱安全规则、已确认方案、工单范围、必要测试、必要的长期文档同步、Git 提交和人工验收要求。 ### 严格控制范围 @@ -264,7 +290,7 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新 ### 明确停止条件 - 完成用户确认的验收标准和仓库规定的必要闭环后立即停止,不主动继续优化。 -- “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、按需 Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。 +- “最小验收条件”包括当前工单要求的实现、必要测试、文档影响处理、Wiki 镜像检查、提交和证据回写,不等同于功能第一次运行成功。 - 未影响当前验收的相邻问题只提示或建单,不顺手处理。 ## 自然语言快捷指令 @@ -275,23 +301,26 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新 |---|---|---| | `只分析` | 只读检查需求、代码、日志和文档,区分事实与假设并给出方案 | 输出方案并等待确认;不建单、不修改 | | `建工单` | 根据已经确认的方案创建单元任务工单 | 工单创建并记录完成;不修改代码 | -| `执行工单 #N` | 读取工单和前置依赖,实施、测试、提交;仅在长期文档变化时更新 Wiki 并同步镜像;集中回写完成证据 | 工单保持“待验收” | +| `执行工单 #N` | 读取工单和前置依赖,实施、测试、提交并回写证据;仅有长期文档影响时更新 Wiki 和镜像 | 工单保持“待验收” | | `建工单并做` | 依次执行“建工单”和“执行工单”;`建工单,做`、`建工单,做` 含义相同 | 工单保持“待验收” | | `继续工单 #N` | 核对工单、Git 和 Wiki 证据,从首个未完成步骤继续,不重复仍然有效的检查 | 到达该工单当前流程的停止条件 | | `检查工单 #N` | 只读对照范围、验收标准、测试和证据,报告通过项、缺失项及未验证部分 | 输出检查报告;不自动修复 | | `同步文档` | 读取 Wiki,导出核心长期文档镜像并检查一致性,不处理任务归档 | 显示结果和差异;不修改 Wiki、不自动提交 | -| `导出任务归档` | 兼容指令;仅按用户明确要求增量导出历史 Wiki 任务归档 | 显示导出或跳过结果;不删除本地文件、不自动提交 | -| `导出全部任务归档` | 兼容指令;仅按用户明确要求全量导出历史 Wiki 任务归档 | 显示导出结果;不删除本地文件、不自动提交 | -| `#N 验收通过` | 在工单记录验收结论,按需推送尚未推送的提交,勾选父工单并关闭任务;不创建归档,不重复同步无变化的 Wiki | 工单“已完成”并关闭 | +| `导出原型 #N` | 人工触发导出指定工单已确认的原型版本;按工单和版本写入 `prototypes/` | 显示路径和检查结果;不扩展范围、不自动提交 | +| `导出全部原型` | 人工触发导出当前项目明确范围内的全部已确认原型 | 显示导出范围和结果;不自动提交 | +| `导出任务归档` | 人工触发增量导出,只写入新增或 revision 已变化的任务归档 | 显示导出或跳过结果;不删除本地文件、不自动提交 | +| `导出全部任务归档` | 人工触发全量读取并导出线上全部任务归档 | 显示导出结果;不删除本地文件、不自动提交 | +| `#N 验收通过` | 在工单追加验收结论,按需更新真实变化的长期 Wiki,推送、同步父工单并关闭任务;不创建或导出任务归档 | 工单“已完成”并关闭 | 补充边界: - 方案未确认时,`建工单`、`建工单并做` 和 `执行工单 #N` 不得绕过确认;Agent 应停在方案确认。 - 前置依赖未满足且不允许并行时,实施类指令停在“待实施”。 - `#N 验收通过` 必须来自用户明确表达;其他快捷指令不得关闭待验收工单。 -- `同步文档` 或历史任务归档导出发现目标镜像有未提交改动时停止,不覆盖现有修改。 -- `导出任务归档` 和 `导出全部任务归档` 是历史兼容能力,必须由用户明确提出,其他快捷指令不隐式创建或导出任务归档。 -- Gitea 工单保留讨论、完成证据和验收,不把工单全文导出到本地;`docs/task/` 只保存人工按需导出的历史 Wiki 任务快照。 +- `同步文档` 或任务归档导出发现目标镜像有未提交改动时停止,不覆盖现有修改。 +- `导出原型 #N` 和 `导出全部原型` 必须由用户明确提出或项目专用规则明确要求;其他指令不隐式导出原型。 +- `导出任务归档` 和 `导出全部任务归档` 必须由用户明确提出,其他快捷指令不隐式执行。 +- Gitea 工单是单次任务唯一事实来源,不导出全文;`docs/task/` 只保存人工明确要求的专项或历史兼容快照。 ## 什么时候重新确认方案 @@ -314,5 +343,6 @@ Agent 检查分支和工作区,只修改工单范围内的文件。发现新 | 实施进度和阻塞 | 是 | 否 | 否 | | 长期有效的最终方案 | 链接 | 是 | 镜像 | | 测试结果与未验证内容 | 是 | 否 | 否 | -| 提交哈希与验收结论 | 是 | 否 | 否 | +| 提交哈希和验收结论 | 是 | 否 | 否 | +| 用户明确要求的任务专项快照 | 提供来源 | 可选 | 可选导出 | | 与具体代码版本绑定的说明 | 可链接 | 提供入口 | 是 | diff --git a/docs/07-new-project-documentation-setup.md b/docs/07-new-project-documentation-setup.md index 94c7c89..7abe807 100644 --- a/docs/07-new-project-documentation-setup.md +++ b/docs/07-new-project-documentation-setup.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: New-Project-Documentation-Setup wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/New-Project-Documentation-Setup.- -wiki_revision: 14eca6fde6902c48941550c49a570a5cb7e157b5 -synchronized_at: 2026-08-20T03:29:35Z +wiki_revision: 404f507af12c9bd21272cd6446f9608a3a06a241 +synchronized_at: 2026-08-26T12:38:03Z # 新项目文档初始化 @@ -48,6 +48,20 @@ synchronized_at: 2026-08-20T03:29:35Z 采用开源基线时,在 Project-Profile 的“技术栈与运行环境”记录上游项目名称、仓库地址、基线版本或提交、许可证、保留能力、定制范围和上游升级策略。尚未确认的候选和取舍先写入首个技术方案工单,不得把假设写成项目事实。 +#### 工程基线裁剪 + +所有项目采用最小工程基线,不按项目规模免除事实和验收要求: + +- 用完整 Git commit 和核验日期固定“当前事实”的代码基线; +- 分开记录“当前已经实现什么”和“目标规范要求什么”,不得用目标描述宣称现有能力; +- 写明证据路径、可确认行为、未覆盖范围和证据不能证明什么; +- 明确目标、非目标、安全边界和可判定的验收标准; +- 跨子项目接口或契约指定唯一事实来源和各端验证命令。 + +当前事实以指定 commit 的代码、可执行测试和运行证据为依据;目标行为以人工批准的契约、ADR 和业务规则为依据。两者冲突时登记为带编号的差距或缺陷,不允许现有错误实现覆盖目标规范,也不允许目标设计冒充当前实现。 + +出现跨团队或跨仓库协作、外部交付、接口或状态机复杂、权限安全、迁移并发、明显文档漂移等情况时,采用增强工程基线:按需增加 GAP-ID 差距表、带状态的 ADR、接口与数据契约、需求追踪测试矩阵,以及 PR、RC、Definition of Done 分层门禁。SRS、SAD、安全、运维和测试文档按风险与读者选择,不强制小型单人项目建立完整文档集。 + #### 判断案例 以下案例用于说明判断方式,不代表必须选择某种技术或具体开源项目。 @@ -108,7 +122,7 @@ synchronized_at: 2026-08-20T03:29:35Z ### 5. 修改镜像配置 -把 `wiki-docs.json` 中的地址、owner 和 repository 改成新项目;只保留核心主题映射,任务归档不逐页登记。 +把 `wiki-docs.json` 中的地址、owner 和 repository 改成新项目;只保留核心主题映射。可选任务快照不逐页登记,默认任务流程不创建。 确认当前目录确实是新项目副本、且 DevHarness 历史归档快照不需要保留后,可以移除对应 `docs/task/` 文件。不要在原 DevHarness 仓库或已有业务项目中执行这项清理。 @@ -187,7 +201,7 @@ python dev_scripts/harness.py sync --verify python -m unittest discover -s tests -v ``` -只有线上 Wiki 确认后才导出核心 `docs/`。任务归档默认不导出;用户明确要求时再运行 `python dev_scripts/harness.py export` 或加 `--all`。旧项目的任务归档快照不能带入新项目历史。 +只有线上 Wiki 确认后才导出核心 `docs/`。默认不创建或导出任务归档;用户明确要求专项快照时才运行 `archive`、`export` 或 `export --all`。旧项目的任务归档快照不能带入新项目历史。 `harness.py sync --check` 会在线读取全部显式映射页面;任一页面不存在、无法读取或 revision 与镜像不一致时,初始化不通过。只有上述命令全部成功后才允许开始产品代码。 diff --git a/docs/09-product-requirements-overview.md b/docs/09-product-requirements-overview.md index bec226f..73dfc43 100644 --- a/docs/09-product-requirements-overview.md +++ b/docs/09-product-requirements-overview.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Product-Requirements-Overview wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Product-Requirements-Overview.- -wiki_revision: 2d5b8e5eccadc0b08212ef1df2c6582ee77b1a68 -synchronized_at: 2026-08-26T06:56:47Z +wiki_revision: 6c7e3b2aee8c0f675013cf60020243cadb566e77 +synchronized_at: 2026-08-26T12:38:17Z # 产品需求总览 @@ -208,22 +208,24 @@ MVP-2 的 API Key 存哈希、身份仍属于 `users`。提交、查询、幂等 新增页面、独立用户功能、重大交互或导航变化的顺序固定为:确认文字需求 → 制作可审阅原型 → 用户确认原型和覆盖范围 → 建立或放行实现工单 → 编写生产代码。原型发生影响页面结构、主要流程、状态、权限、异常处理或验收结果的变化时,必须重新确认。 -### 本地 HTML 审核快照 +### 线上原型与按需 HTML 快照 -需要完整原型门禁的新页面、独立用户功能、重大交互或导航变化,在用户审核前把 Quant-UX 或等效设计源的待审核版本生成到 `prototypes/<工单号>/<版本>/index.html`。版本目录内的资源使用相对路径,快照应在本地可浏览;如果必须启动静态服务,在工单记录最小启动命令。可编辑设计源仍以原设计工具为准,Git HTML 是不可覆盖的版本化审核证据,Wiki 和工单负责索引。 +需要完整原型门禁的新页面、独立用户功能、重大交互或导航变化,默认直接通过 Quant-UX 或等效设计工具的线上版本审核。可编辑设计源仍以原设计工具为准,工单记录可访问链接、版本/revision、复制版本或确认日期、审核版本识别方式、确认人、确认时间和覆盖范围。 -已确认快照不得原位覆盖。页面结构、流程、状态、权限、异常处理或验收结果变化时创建新版本目录、重新导出并重新确认。审核前检查页面、交互和资源完整性,并删除凭据、账号、个人信息和生产数据。纯显示文案、小范围 UI、非 UI 需求和恢复既有行为的 Bug 不强制生成 HTML。 +线上链接无法访问或无法区分审核版本时停止审核,等待用户确认等效方案;不能为了节省时间把不稳定链接直接当作已确认原型。页面结构、流程、状态、权限、异常处理或验收结果变化时更新线上版本并重新确认。 -设计工具无法生成可用 HTML 时,工单记录限制并停止审核,等待用户确认等效的本地可浏览方案;不能把难以访问的线上链接直接当作已确认原型。 +只有用户明确要求 `导出原型 #N`、`导出全部原型`,或项目专用规则要求离线交付时,才把确认版本导出到 `prototypes/<工单号>/<版本>/index.html`。资源使用相对路径,导出后检查入口、主要交互和资源完整性;已确认快照不得原位覆盖,新版本使用新目录。导出不自动提交,也不顺带扩大到未请求的原型。 + +设计工具无法生成用户明确要求的可用 HTML 时,工单记录限制并停止该导出或离线交付,等待用户确认等效方案;只要线上原型仍可访问且版本明确,不因此阻塞线上审核。已有本地快照继续作为历史审核证据,不反向替代可编辑设计源。 ### 原型确认记录 -原型或替代设计证据至少记录链接/路径、版本/revision或确认日期、状态、确认人、确认时间和覆盖范围。外部原型需要保留可追溯版本;重要已确认版本按需保存快照。没有 UI 原型时,记录采用的技术设计或无需原型的原因。 +原型或替代设计证据至少记录线上链接、访问检查、版本/revision、复制版本或确认日期、审核版本识别方式、状态、确认人、确认时间和覆盖范围。只有显式导出时才记录本地路径、版本和资源检查结果。没有 UI 原型时,记录采用的技术设计或无需原型的原因。 - 与代码版本绑定的图片、HTML 交互稿和设计源文件放入 Git 的 `design/` 或 `prototypes/`,不要手工放入 Wiki 镜像目录 `docs/`。 - #17 管理端运营原型:`prototypes/17/v1/index.html`,v1,2026-08-21,状态“已确认”;由用户于 2026-08-21 验收通过,覆盖四类标准 CRUD、路由池编排、Provider 健康/主动探测、生成记录详情,以及加载、空、错误、无权限和边界状态。 - #18 用户端增强原型:`prototypes/18/v1/index.html`,v1,2026-08-21,状态“已确认”;由用户于 2026-08-21 验收通过,覆盖文生图、图片编辑、role_rule 覆盖、每图 role/note/order、键盘排序与历史增量加载/失败恢复/到底状态。 -- 外部 Figma 等原型记录可访问链接、版本或确认日期、负责人和适用需求;重要的已确认版本保留可追溯快照。 +- 外部 Quant-UX、Figma 等原型记录可访问链接、审核版本识别方式、负责人和适用需求;只有用户或项目专用规则明确要求时才保存本地快照。 - 原型必须标记“草稿、已确认、已废弃”之一。草稿不能作为正式实现依据;已废弃原型保留状态和替代入口,不让 Agent 误用。 - 原型只表达界面和交互意图,不能代替文字业务规则、安全边界、异常处理和验收标准。 - 没有原型时写“无”和原因,不创建空图片、空目录或占位原型。 diff --git a/docs/README.md b/docs/README.md index 5d6e5e6..2af456e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,13 +2,13 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Home wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Home -wiki_revision: bf4f622133bfa31a595a5c57a62d6bcb0ed4189c -synchronized_at: 2026-08-24T07:59:09Z +wiki_revision: 07c26be93a044570206347fefe1f9a491c6a426a +synchronized_at: 2026-08-26T12:37:06Z # chorus 文档中心 -chorus 是从 cmhub 设计中抽取并用 Go 重写的独立生图生文服务:用户提交提示词(可带原图)得到图片或文本,运营在管理端配置上游并查看生成记录。Gitea 工单记录任务过程,Wiki 是长期文档事实来源,Git 记录代码与镜像。 +chorus 是从 cmhub 设计中抽取并用 Go 重写的独立生图生文服务:用户提交提示词(可带原图)得到图片或文本,运营在管理端配置上游并查看生成记录。Gitea 工单是单次任务需求、变化、实现、测试、提交和验收的唯一事实来源,Wiki 是长期文档事实来源,Git 记录代码与镜像。 当前处于 **MVP-0:安全、可观测地跑通单上游闭环**。文档基线由工单 [#1](https://git.ilapage.cn/OPC/chorus/issues/1) 更新;这不表示产品功能已经开工。 @@ -55,12 +55,12 @@ retryable、SSRF、密钥、迁移、租约/CAS、身份权限、点数写入、 | 信息 | 事实来源 | |---|---| -| 单元任务状态、讨论、阻塞和验收 | Gitea 工单 | +| 单次任务需求、变化、实现、测试、提交和验收 | Gitea 工单 | | 长期需求导航 | Product-Requirements-Overview | | 架构、规则、开发、排错和部署等长期文档 | Gitea Wiki | | 生产数据库结构和配置种子 | `migrations/` 可逆 SQL | | 源码和固定版本资料 | chorus Git;外部来源提交记录在 Project-Profile | -| 已确认界面与交互 | `prototypes/<工单号>/<版本>/index.html` | +| 已确认界面与交互 | 可访问且版本明确的线上设计源;本地 `prototypes/` 仅保存明确要求导出的快照 | | 离线核心文档 | Git 中的 `docs/` Wiki 只读镜像 | `D:\github\goadmin` 是已审查来源,不是运行时事实来源。线上 Wiki 已初始化;长期文档必须先改 Wiki、回读 revision,再同步镜像。 @@ -73,7 +73,7 @@ retryable、SSRF、密钥、迁移、租约/CAS、身份权限、点数写入、 - [代码仓库](https://git.ilapage.cn/OPC/chorus) - [新项目文档初始化](New-Project-Documentation-Setup.-) - [交付文档指南](Delivery-Documentation-Guide.-) -- [历史任务快照模板(兼容)](Task-Archive-Template.-) +- [可选任务快照模板(兼容)](Task-Archive-Template.-) ## 同步原则 @@ -81,7 +81,7 @@ retryable、SSRF、密钥、迁移、租约/CAS、身份权限、点数写入、 修改 Wiki → 在线回读 revision → 导出 docs → 校验差异 → 提交镜像 ``` -- `wiki-docs.json` 显式映射核心和项目专用页面;仅在长期文档变化时同步,普通同步不处理历史任务快照。 +- `wiki-docs.json` 显式映射核心和项目专用页面;仅在长期文档变化时同步。默认不创建任务归档,专项快照和导出必须由用户或项目专用规则明确要求。 - 带 `generated: true` 的文件不得手工编辑;有未提交镜像修改时同步停止。 - 页面删除、重命名和事实源变化必须先更新工单并确认。 - 凭据、个人数据、真实 prompt、生成文件和生产数据不得进入文档、工单或原型。 diff --git a/tests/test_harness_docs.py b/tests/test_harness_docs.py index 067d9ae..2b5b6ad 100644 --- a/tests/test_harness_docs.py +++ b/tests/test_harness_docs.py @@ -72,7 +72,7 @@ class CoreDocumentTests(unittest.TestCase): self.assertIn("## 当前需求索引", required) self.assertIn("## 原型与设计资产", required) self.assertIn("### 原型门禁", required) - self.assertIn("### 本地 HTML 审核快照", required) + self.assertIn("### 线上原型与按需 HTML 快照", required) self.assertIn("### 原型确认记录", required) self.assertIn("## 更新时机", required) @@ -81,7 +81,7 @@ class CoreDocumentTests(unittest.TestCase): self.assertIn("## 工单与设计证据双门禁", required) self.assertIn("### 先判断是否需要工单", required) self.assertIn("### 再判断设计证据", required) - self.assertIn("### 本地 HTML 审核快照", required) + self.assertIn("### 线上原型审核与按需导出", required) self.assertIn("### 记录和重新确认", required) def test_workflow_requires_online_wiki_initialization_gate(self) -> None: @@ -92,6 +92,22 @@ class CoreDocumentTests(unittest.TestCase): self.assertIn("## 新项目 Wiki 初始化门禁", workflow) self.assertIn("#### 在线创建与回读门禁", setup) + def test_workflow_requires_issue_only_task_record(self) -> None: + workflow = CORE_DOCUMENT_REQUIREMENTS["docs/01-workflow.md"] + setup = CORE_DOCUMENT_REQUIREMENTS[ + "docs/07-new-project-documentation-setup.md" + ] + self.assertIn("## 稳定文档与可选历史快照", workflow) + self.assertIn("#### 工程基线裁剪", setup) + + def test_workflow_requires_gitea_mcp_and_minimal_issue_reading(self) -> None: + workflow = CORE_DOCUMENT_REQUIREMENTS["docs/01-workflow.md"] + self.assertIn("## Gitea 交互与工单最小读取", workflow) + + errors: list[str] = [] + check_agent_efficiency_rules(errors) + self.assertEqual(errors, []) + def test_existing_project_adoption_requires_upgrade_process(self) -> None: required = CORE_DOCUMENT_REQUIREMENTS[ "docs/08-existing-project-adoption.md" @@ -177,18 +193,6 @@ class TaskTemplateTests(unittest.TestCase): errors, ) - def test_task_template_requires_completion_evidence(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_design_and_prototype_gate(self) -> None: with tempfile.TemporaryDirectory() as directory: root = Path(directory) @@ -199,15 +203,29 @@ class TaskTemplateTests(unittest.TestCase): check_task_template(errors, root) self.assertIn("单元任务模板缺少:## 设计与原型门禁", errors) self.assertIn( - "单元任务模板缺少:- 可编辑设计源链接、版本或事实来源:", + "单元任务模板缺少:- 可编辑设计源、线上原型链接和访问检查:", errors, ) self.assertIn( - "单元任务模板缺少:- 本地 HTML 审核快照路径和版本(不适用时说明原因):", + "单元任务模板缺少:- 本地 HTML 导出:未要求 / 用户明确要求 / 项目规则要求", errors, ) self.assertIn( - "单元任务模板缺少:- 本地浏览方式和资源完整性检查:", + "单元任务模板缺少:- 本地 HTML 路径、版本和资源检查(仅显式导出时填写):", + errors, + ) + + def test_task_template_requires_optional_snapshot_policy(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, )