GOV8 建立连续型 Issue 治理基线

这个提交包含在:
2026-05-13 16:57:58 +08:00
父节点 56fa38010f
当前提交 6b445a13e1
共修改 6 个文件,包含 495 行新增和 1 行删除
+105
查看文件
@@ -1,7 +1,11 @@
# 开发交付与变更管理规约
**文档状态**:当前开发交付事实源。
**分类**:开发治理。
**适用范围**:hyb-oa 所有非微小代码、文档、测试、脚本和部署准备变更。
**关联 Issue**:`GOV8`。
**最近审计**:2026-05-13。
**不得误读**:本文定义开发和变更流程,不替代具体业务 PRD、模块规约或测试规约。
**路线口径**:开发必须围绕最新 Issue CSV 执行;hyb-oa 是唯一业务主系统,企业微信只做基础设施,飞书路线已废弃。
本文回答“一个变更怎么开始、怎么审查、什么时候提交、怎么交付”。测试细节以 [测试规约与回归门禁](./测试规约与回归门禁.md) 为准。
@@ -32,6 +36,48 @@
如果回归失败,不能把 `Regression_Status` 标为 `DONE`。如果发现范围外缺口,记录到 Notes 或新 Issue。
### 2.1 连续型 Issue 策略
后续默认使用“少量长期连续合同 + 多行任务 + 阶段收口”,不再为每个小反馈、小链接修正或单点讨论新建 CSV。
| 治理流 | 覆盖范围 | 进入条件 |
| --- | --- | --- |
| `GOV8` | 文档、流程、审计、Issue 管理 | 材料散、权威不清、流程模板和审计问题 |
| `R7E` | 真实扩大试运行 | 用户确认参与人、窗口、回滚和每日收口后 |
| `ORG8` | 组织账号、角色、权限、企业微信绑定 | 组织主数据或权限边界问题 |
| `WF8` | 审批、通知、催办、转审 | 审批通知能力增强,但不涉及复杂 BPM |
| `BIZ8` | OCR、票据、财务、费用、项目轻量增强 | 业务主链路增强,但不涉及 ERP 或重预算 |
| `QAOPS8` | 测试、发布、运维、上线准备 | 回归、门禁、备份、SLO、发布问题 |
连续型 Issue 规则:
- 同类型、同目标、同风险域的问题进入同一个连续 CSV。
- 只有跨业务域、跨风险等级、跨里程碑,或当前治理流阶段性收口后,才新建下一版 CSV。
- 一个连续 CSV 内用领域前缀表达子类,例如 `GOV8-DOC-*`、`ORG8-PERM-*`、`WF8-NOTIFY-*`。
- 旧 Issue CSV 保留为历史审计证据,不删除、不批量回写、不移动到归档目录。
- 如果新治理流替代旧合同,只在新 CSV 的 `Notes` 或文档索引中说明 `supersedes`。
- 当前可执行合同只在 `docs/文档索引.md` 和 `docs/文档事实源状态矩阵.md` 中暴露,避免主入口被历史 Issue 淹没。
### 2.2 需求冻结和变更请求
非微小需求必须先进入需求事实源和当前同类型连续 CSV。需求冻结后,新增想法默认进入后续池;只有同时满足以下条件,才允许并入当前轮:
- 不扩大当前治理流范围。
- 不改变已批准验收口径。
- 不引入新的权限、状态机、数据迁移或生产风险。
- 不增加未覆盖测试面。
- 不导致当前 `Test_Method` 失效。
变更请求至少写清:
| 字段 | 说明 |
| --- | --- |
| 变更原因 | 为什么现在提出 |
| 影响范围 | 影响哪些角色、流程、接口、页面、数据或文档 |
| 处理方式 | 替代原需求、追加当前行、进入同治理流后续行或进入下一阶段 |
| 测试影响 | 原测试是否仍有效,是否新增权限/视觉/公网/真机验证 |
| 回滚路径 | 如何撤销或延后 |
## 3. 开发边界
- 每次只做当前 Issue 范围内的事,不顺手重构无关模块。
@@ -40,6 +86,65 @@
- 不在当前 MVP 首批范围内扩展预算、ERP、AI、飞书、企业微信原生审批、复杂 BPM 或重型项目管理。
- 未经确认不得重置数据库、编辑迁移历史、修改生产配置、暴露真实密钥或处理真实敏感数据。
## 3.1 方案和计划模板
后续非微小变更在实施前必须至少给出以下轻量模板内容。模板可以写在回复、Issue CSV `Notes` 或对应规约中,但必须可审计。
### 需求整理模板
| 字段 | 要求 |
| --- | --- |
| 背景 | 真实反馈、试运行问题、业务制度或技术风险 |
| 目标角色 | 员工、审批人、财务、管理员、老板/负责人等 |
| 主流程 | 从发起到验收的业务路径 |
| 必须做 | 当前轮必须完成的行为 |
| 暂不做 | 明确冻结或后续池能力 |
| 验收口径 | 用户或自动化如何判断完成 |
### 设计方案模板
| 字段 | 要求 |
| --- | --- |
| 数据/API | 新增或变更的数据、接口、字段和兼容性 |
| 权限 | 服务端授权、角色边界、敏感字段和审计 |
| 状态流 | 状态转换、非法跳转、并发和重复提交 |
| 页面 | PC、移动、企业微信入口和视觉规则 |
| 异常 | 缺配置、失败、重试、SKIP 和用户提示 |
| 回滚 | 代码、配置、数据、迁移和发布回滚路径 |
| 测试影响 | 需要新增或复跑的验证 |
### 开发计划模板
| 字段 | 要求 |
| --- | --- |
| 治理流 | GOV8/R7E/ORG8/WF8/BIZ8/QAOPS8 |
| Issue 行 | 对应 CSV 行 ID |
| 文件范围 | `docs/`、`server/`、`client/`、`scripts/qa/` 等 |
| 依赖 | 前置 Issue 行和外部条件 |
| 交接物 | 代码、文档、脚本、API 契约、测试证据 |
### 测试方案模板
| 字段 | 要求 |
| --- | --- |
| 主流程 | 至少覆盖一个业务流程级验证 |
| 异常流程 | 权限不足、缺配置、失败、重复提交、撤回/驳回等 |
| 权限 | 普通员工、审批人、财务、管理员边界 |
| 视觉 | PC、移动、企业微信 UA 和关键视口 |
| 公网/真机 | `/ready`、public bundle、live readiness、真实 OCR、真机反馈 |
| SKIP 条件 | 只允许真实外部条件缺失时 SKIP,且必须记录补测条件 |
### 测试计划模板
| 字段 | 要求 |
| --- | --- |
| 执行时机 | 开发前、后端后、前端后、review 前、回填前、commit 前 |
| 命令 | 可复现命令或人工步骤 |
| 环境 | 本地、公网匿名、带凭据、企业微信真机 |
| 证据路径 | artifacts、output、报告、Issue CSV Notes |
| 负责人 | backend/frontend/qa/ops 或人工验收角色 |
| 阻断条件 | 哪些失败必须停止推进 |
## 4. Review 规则
Review 不只看代码格式,优先检查行为风险:
+55
查看文件
@@ -1,13 +1,68 @@
# 文档事实源状态矩阵
**文档状态**:当前文档治理事实源。
**分类**:文档台账。
**适用时间**:DCL7 之后。
**关联 Issue**:`GOV8`。
**最近审计**:2026-05-13。
**不得误读**:本文登记文档权威性和状态,不替代具体 PRD、模块规约、测试规约或 Issue CSV。
**治理口径**:中文优先,物理精简。历史资料不建 `docs/archive/`,已确认不用的文档从当前树移除,通过 git 历史恢复。
## 冲突优先级
最新 Issue CSV > 当前 PRD/模块规约 > 产品和设计规则 > 当前操作手册 > 技术参考 > 历史证据 > git 历史。
## 台账状态值
| Status | 含义 | 是否可直接指导开发 |
| --- | --- | --- |
| `CURRENT` | 当前事实源或当前执行合同 | 可以 |
| `DRAFT` | 草案或准备材料,未完成启动确认 | 不可以 |
| `EVIDENCE` | 试运行、测试、审计或验收证据 | 不可以 |
| `HISTORICAL` | 历史快照或旧合同 | 不可以 |
| `SUPERSEDED` | 已被新文档或新合同替代 | 不可以 |
| `REMOVED` | 已从当前树物理移除,只能从 git 历史恢复 | 不可以 |
## 当前活跃治理流
| Stream | Contract | Status | 用途 |
| --- | --- | --- | --- |
| `GOV8` | `issues/2026-05-13_16-31-09-gov8-system-governance.csv` | `CURRENT` | 连续型 Issue 治理、文档台账、流程模板和审计脚本 |
| `R7E` | 待新建连续合同 | `DRAFT` | 真实扩大试运行人工确认和执行 |
| `ORG8` | 待新建连续合同 | `DRAFT` | 组织账号和权限主数据治理 |
| `WF8` | 待新建连续合同 | `DRAFT` | 审批与通知增强 |
| `BIZ8` | 待新建连续合同 | `DRAFT` | 报销/OCR/财务/项目轻量增强 |
| `QAOPS8` | 待新建连续合同 | `DRAFT` | 测试、发布、运维和上线准备 |
旧 Issue CSV 保留为历史审计证据:不删除、不批量回写、不移动到 `docs/archive/` 或其他归档目录。新连续合同如替代旧合同,只在新合同 `Notes` 或文档索引中说明 supersedes。
## 文档台账
| Doc_ID | Path | Category | Authority | Status | Owner | Related_Issues | Evidence | Supersedes | Last_Audited | Audit_Method | Risk | Notes |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `IDX` | `docs/文档索引.md` | 入口索引 | 最高文档入口 | `CURRENT` | product/dev | `GOV8` | `rg` | none | 2026-05-13 | `node scripts/qa/audit-docs.mjs --check-registry` | medium | 判断当前该读什么 |
| `REG` | `docs/文档事实源状态矩阵.md` | 文档台账 | 文档分类和状态事实源 | `CURRENT` | product/dev | `GOV8` | `audit-docs` | none | 2026-05-13 | `audit-docs --check-registry` | medium | 判断文档权威性 |
| `PRD-MVP` | `docs/海音达OA-MVP需求规格说明书.md` | 需求事实源 | PRD 主事实源 | `CURRENT` | product | `REQ8,P2T,GOV8` | Issue CSV | `docs/requirements-specification.md` | 2026-05-13 | `rg` | high | 定义做什么、不做什么和验收口径 |
| `PRODUCT-SCOPE` | `docs/产品口径.md` | 需求事实源 | 产品边界事实源 | `CURRENT` | product | `REQ8,P2T` | `rg` | none | 2026-05-13 | `rg` | high | 记录已拍板产品边界 |
| `DESIGN-UI` | `docs/产品设计规则.md` | 设计事实源 | PC/移动/企业微信设计事实源 | `CURRENT` | design/frontend | `MIA7,MIF7,GOV8` | Playwright/视觉审查 | none | 2026-05-13 | `rg` | high | 页面改动必须读取 |
| `DELIVERY` | `docs/开发交付与变更管理规约.md` | 开发治理 | 开发交付事实源 | `CURRENT` | dev/qa | `GOV8` | `rg` | none | 2026-05-13 | `rg` | high | Issue、review、commit 和交付规则 |
| `QA-GATE` | `docs/测试规约与回归门禁.md` | 测试验收 | 测试和回归门禁事实源 | `CURRENT` | qa | `QAF8,GOV8` | 回归脚本/Playwright | none | 2026-05-13 | `rg` | high | 测试计划和 DONE 门禁 |
| `AGENT-PRACTICE` | `docs/Agent开发交付实践.md` | Agent 治理 | Agent 协作事实源 | `CURRENT` | dev | `GOV8` | Skill 校验 | none | 2026-05-13 | `rg` | medium | Agent 协作开发实践 |
| `AGENTS` | `AGENTS.md` | 执行硬约束 | 项目硬规则 | `CURRENT` | lead | `GOV8` | 人工核对 | none | 2026-05-13 | `rg` | high | 不可违反约束 |
| `SKILL-HYB` | `.agents/skills/hyb-oa-delivery/SKILL.md` | Skill | 项目交付 Skill | `CURRENT` | dev | `GOV8` | quick_validate | none | 2026-05-13 | `quick_validate.py` | medium | 每轮交付操作入口 |
| `REQ-WF` | `docs/需求-统一审批中心规约.md` | 需求事实源 | 审批模块规约 | `CURRENT` | product/backend | `AP6,WF8` | workflow 回归 | none | 2026-05-13 | `rg` | high | 审批、催办、通知和状态流 |
| `REQ-OCR` | `docs/需求-报销发票OCR规约.md` | 需求事实源 | OCR 模块规约 | `CURRENT` | product/backend | `RI6,OCR8,BIZ8` | OCR 回归 | none | 2026-05-13 | `rg` | high | OCR 和发票边界 |
| `RULE-REIMB` | `docs/报销发票附件规则.md` | 需求事实源 | 报销发票附件规则 | `CURRENT` | product/finance | `RI6,BIZ8` | 报销回归 | none | 2026-05-13 | `rg` | high | 报销、发票、附件细则 |
| `REQ-WECOM` | `docs/需求-企业微信基础设施规约.md` | 需求事实源 | 企业微信边界规约 | `CURRENT` | product/backend | `R7E,ORG8,WF8` | live smoke/真机反馈 | none | 2026-05-13 | `rg` | high | 企业微信只做入口、身份和通知 |
| `RUNBOOK-TRIAL` | `docs/试运行与自动化验证手册.md` | 操作手册 | 试运行验证手册 | `CURRENT` | qa/ops | `R7E,QAOPS8` | live readiness | none | 2026-05-13 | `rg` | medium | 本地、公网、企业微信和真实 OCR 验证 |
| `MANUAL-ADMIN` | `docs/管理员手册.md` | 操作手册 | 管理员手册 | `CURRENT` | ops/admin | `ORG8,R7E` | 人工验收 | none | 2026-05-13 | `rg` | medium | 管理员上线和配置 |
| `MANUAL-EMPLOYEE` | `docs/员工快速上手.md` | 操作手册 | 员工手册 | `CURRENT` | product | `R7E` | 人工验收 | none | 2026-05-13 | `rg` | low | 员工侧使用说明 |
| `R7-DRAFT` | `docs/trialrun/R7扩大试运行草案.md` | 草案 | R7 准备材料 | `DRAFT` | product/qa | `R7E` | R7EP 报告 | none | 2026-05-13 | `rg` | medium | 不代表真实 R7 已启动 |
| `OPS-RUNBOOK` | `docs/trialrun/OPS7运维交接Runbook.md` | 运维草案 | OPS 准备材料 | `DRAFT` | ops | `OPS8,QAOPS8` | 只读检查 | none | 2026-05-13 | `rg` | medium | 不代表恢复演练已执行 |
| `TRIAL-REPORT` | `docs/trialrun/人工试运行报告.md` | 证据材料 | 试运行证据入口 | `EVIDENCE` | qa | `R7EP,OPS8,QAF8` | artifacts/qa-flow | none | 2026-05-13 | `rg` | medium | 只证明发生过,不直接派工 |
| `HISTORY-MATRIX` | `docs/历史功能状态矩阵.md` | 历史材料 | 历史功能索引 | `HISTORICAL` | product | `DCL7` | git 历史 | none | 2026-05-13 | `rg` | low | 只追溯历史 |
| `OLD-IMPL-PLAN` | `docs/implementation_plan.md` | 已移除历史 | 早期实施计划 | `REMOVED` | product | `DCL7` | git history | none | 2026-05-13 | manual | low | 从 git 历史恢复 |
## 当前事实源
| 路径 | 分类 | 当前用途 |
+33
查看文件
@@ -1,7 +1,11 @@
# hyb-oa 文档索引
**文档状态**:当前唯一文档入口。
**分类**:入口索引。
**适用时间**:DCL7 之后。
**关联 Issue**:`GOV8`。
**最近审计**:2026-05-13。
**不得误读**:本文只指示当前事实源和读取顺序;历史 Issue CSV 只能用于追溯,不直接生成新开发任务。
**治理口径**:中文优先,物理精简。已确认不用的历史文档不放 `docs/archive/`,直接从当前工作树移除;需要时从 git 历史恢复。
## 读取规则
@@ -10,6 +14,8 @@
- 判断历史证据:读轻量历史索引,必要时用 `git show <commit>:<old-path>` 恢复旧文档。
- 判断冲突:最新 Issue CSV > 当前 PRD/模块规约 > 设计和产品规则 > 当前操作手册 > 技术参考 > 历史证据。
- 英文文件名只在技术生态或脚本强引用时保留,例如 `docs/mcp-tools.md`。
- 判断当前可执行任务:只读当前活跃治理流和对应连续型 Issue CSV;旧 Issue CSV 默认是历史审计证据。
- 新需求或试运行反馈:优先进入当前同类型连续治理流;只有跨业务域、跨风险等级或阶段收口后,才新建下一版 CSV。
## 最近事实源链
@@ -21,6 +27,33 @@ R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> M
- MIA7 已完成移动信息架构、视觉和流程审查;MIF7-1..7 与 MIF7T 已完成本地整改、公网部署、公网匿名复检和带凭据 live smoke/OCR 复检。
- R7/OPS7/DOC7 是准备材料,不代表已上线或已启动真实 R7。
## 当前活跃治理流
后续不再为每次聊天、小反馈或单点修正单独创建 Issue CSV。同类型、同目标、同风险域的任务优先进入同一个连续型 Issue CSV,直到该治理流完成明确阶段。
| 治理流 | 当前合同 | 当前状态 | 范围 | 不做 |
| --- | --- | --- | --- | --- |
| `GOV8` | `issues/2026-05-13_16-31-09-gov8-system-governance.csv` | 当前执行 | 文档分类、台账、流程模板、审计脚本、需求冻结、变更控制 | 不改业务代码、不部署 |
| `R7E` | 待 GOV8 收口后新建连续合同 | 规划 | 人工确认、真实试运行、每日问题收口、验收结论 | 不新增 P2 能力 |
| `ORG8` | 待 R7E 或用户确认后新建连续合同 | 规划 | 组织、账号、直属主管、停用、角色、企业微信绑定、权限边界 | 不做审批流程增强 |
| `WF8` | 待 ORG8 或用户确认后新建连续合同 | 规划 | 转审、通知、催办、邮件通道决策、三渠道验收 | 不做复杂 BPM 或审批设计器 |
| `BIZ8` | 待 R7E/P2 排序后新建连续合同 | 规划 | OCR、票据、财务、费用提示、项目关联 | 不做 ERP 实时集成或重预算 |
| `QAOPS8` | 贯穿执行,必要时新建连续合同 | 规划 | 回归稳定、测试覆盖、上线门禁、备份恢复、SLO | 不改业务需求 |
旧 Issue CSV 不删除、不批量回写、不移动到归档目录。若新治理流替代旧合同,只在新 CSV 的 `Notes` 或本索引说明 supersedes,旧文件保留历史审计语义。
## 按开发阶段阅读
| 阶段 | 必读入口 | 目的 |
| --- | --- | --- |
| 需求阶段 | 最新同类型连续 Issue CSV、[海音达OA-MVP需求规格说明书](./海音达OA-MVP需求规格说明书.md)、对应 `需求-*.md`、[产品口径](./产品口径.md) | 判断做什么、不做什么、验收什么 |
| 设计阶段 | [产品设计规则](./产品设计规则.md)、[架构概览](./架构概览.md)、[集成边界](./集成边界.md)、`docs/ops/*.md`、必要 ADR | 判断页面、权限、状态流、集成和非功能边界 |
| 开发阶段 | 当前连续 Issue CSV、[开发交付与变更管理规约](./开发交付与变更管理规约.md)、`AGENTS.md` | 判断文件范围、依赖、方案批准和交接物 |
| 测试阶段 | [测试规约与回归门禁](./测试规约与回归门禁.md)、[试运行与自动化验证手册](./试运行与自动化验证手册.md)、当前 Issue 的 `Test_Method` | 判断怎么测、何时可回填 DONE |
| 发布阶段 | [发布试运行准备清单](./trialrun/发布试运行准备清单.md)、[公网 Live Smoke 准备清单](./trialrun/公网LiveSmoke准备清单.md)、[OPS7 运维交接 Runbook](./trialrun/OPS7运维交接Runbook.md) | 判断公网、企业微信、真实 OCR 和回滚条件 |
| 审计阶段 | [文档事实源状态矩阵](./文档事实源状态矩阵.md)、[人工试运行报告](./trialrun/人工试运行报告.md)、当前连续 Issue CSV、git 历史 | 判断当前事实、历史证据和冲突处理 |
| 历史追溯 | [历史功能状态矩阵](./历史功能状态矩阵.md)、旧 Issue CSV、git 历史 | 只追溯,不直接派工 |
## 当前事实源
| 文档 | 用途 |
@@ -0,0 +1,21 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
GOV8-0,连续型治理合同建档,"建立 GOV8 连续型系统治理合同,锁定本轮只做文档、流程、Issue 管理和审计脚本治理,不改 server/client 业务代码。","1) 本 CSV 校验通过;2) 范围限定 docs/issues/scripts/qa;3) 不删除旧 Issue CSV;4) 不部署;5) 后续同类治理任务优先进入本 CSV。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_16-31-09-gov8-system-governance.csv;人工核对 Files 范围不含 server/client 业务代码。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_16-31-09-gov8-system-governance.csv,[],回滚路径:删除本 CSV 与本轮 docs/scripts/qa 变更;不影响运行环境。
GOV8-1,旧 Issue 现状盘点,"盘点当前 Issue CSV 过多且不可轻易删除的问题,明确旧 Issue 作为历史审计证据保留,不批量回写、不挪 archive。","1) 文档写明旧 Issue 不删除;2) 当前活跃合同和历史合同分层;3) 旧合同只通过索引/状态矩阵降级;4) 不修改旧 CSV。","流程级验证:rg -n '旧 Issue|历史合同|不删除|不批量回写|当前活跃治理流' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。",rg,DONE,DONE,DONE,docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md,"[""GOV8-0""]",不回写历史快照;只增加治理口径。
GOV8-2,文档台账字段设计,"把文档事实源状态矩阵升级为轻量文档台账,固定 Doc_ID、Path、Category、Authority、Status、Owner、Related_Issues、Evidence、Supersedes、Last_Audited、Audit_Method、Risk、Notes 字段。","1) 状态矩阵包含文档台账字段说明;2) 状态值包含 CURRENT/DRAFT/EVIDENCE/HISTORICAL/SUPERSEDED/REMOVED;3) 核心文档至少登记一轮;4) 审计脚本能检查字段存在。","流程级验证:node scripts/qa/audit-docs.mjs --check-registry;rg -n 'Doc_ID|CURRENT|DRAFT|EVIDENCE|HISTORICAL|SUPERSEDED|REMOVED' docs/文档事实源状态矩阵.md。",node|rg,DONE,DONE,DONE,docs/文档事实源状态矩阵.md|scripts/qa/audit-docs.mjs,"[""GOV8-0""]",台账先覆盖核心事实源、操作手册、草案/证据和技术参考;后续可在 GOV8 继续补全。
GOV8-3,核心文档分类登记,"在文档台账中登记核心当前事实源、操作手册、草案证据、技术参考和已移除历史材料。","1) 当前事实源、操作手册、草案/证据、技术参考均有分类;2) 每行有 Authority 和 Status;3) 当前事实源可指导开发;4) 草案/历史不能直接派工。","流程级验证:node scripts/qa/audit-docs.mjs --check-registry;人工核对状态矩阵中核心文档分类。",node|manual,DONE,DONE,DONE,docs/文档事实源状态矩阵.md|scripts/qa/audit-docs.mjs,"[""GOV8-2""]",不要求一次登记所有历史 Issue;先固定核心文档台账。
GOV8-4,文档索引按开发阶段重写,"把文档索引从文档清单升级为按开发阶段阅读入口,覆盖需求、设计、开发、测试、发布、审计、历史追溯。","1) 索引有按开发阶段阅读规则;2) 当前活跃治理流可见;3) 历史合同入口被降级;4) 草案和历史证据不得直接开发。","流程级验证:rg -n '按开发阶段阅读|需求阶段|设计阶段|开发阶段|测试阶段|发布阶段|审计阶段|当前活跃治理流|不得直接开发' docs/文档索引.md。",rg,DONE,DONE,DONE,docs/文档索引.md,"[""GOV8-1"",""GOV8-3""]",保留 DCL7 中文优先和物理精简策略。
GOV8-5,核心文档统一头部规则,"固定核心文档顶部元数据规则,明确文档状态、分类、适用范围、上级事实源、关联 Issue、最近审计和不得误读。","1) 开发交付规约写明统一头部规则;2) 文档索引/状态矩阵已有当前头部;3) 后续新增核心文档必须套用;4) 不批量强改所有历史文档。","流程级验证:rg -n '文档状态|分类|适用范围|上级事实源|关联 Issue|最近审计|不得误读' docs/开发交付与变更管理规约.md docs/文档索引.md docs/文档事实源状态矩阵.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md|docs/文档索引.md|docs/文档事实源状态矩阵.md,"[""GOV8-4""]",只要求当前事实源和后续新增文档遵守;历史证据不大规模重写。
GOV8-6,需求冻结规则,"补强需求冻结规则:非微小需求必须先进入事实源和当前连续 CSV,冻结后新增想法默认进入后续池。","1) 需求冻结规则写入开发交付规约;2) 当前轮变更准入条件明确;3) 不再为小反馈单独开 CSV;4) 后续池和冻结项分流清楚。","流程级验证:rg -n '需求冻结|后续池|当前轮变更|小反馈|连续 CSV' docs/开发交付与变更管理规约.md issues/README.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md|issues/README.md,"[""GOV8-5""]",开发中临时变更必须先做影响评估。
GOV8-7,变更请求规则,"补强变更请求规则:开发中新增范围必须说明原因、影响、测试变化和是否替代原需求。","1) 变更请求字段明确;2) 不满足准入条件时进入下一阶段或同治理流后续行;3) 测试影响必须同步;4) 旧 Issue 不回写。","流程级验证:rg -n '变更请求|变更原因|影响范围|测试影响|替代原需求|下一阶段' docs/开发交付与变更管理规约.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md,"[""GOV8-6""]",只做流程规则,不改业务逻辑。
GOV8-8,设计方案模板,"在开发交付规约中加入设计方案模板,覆盖数据/API、权限、状态流、页面、异常、回滚和测试影响。","1) 模板字段完整;2) 涉及权限/状态机/迁移时必须写回滚;3) 可映射到 Issue CSV;4) 不引入外部平台。","流程级验证:rg -n '设计方案模板|数据/API|权限|状态流|回滚|测试影响' docs/开发交付与变更管理规约.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md,"[""GOV8-7""]",复用现有 Issue CSV,不新增外部工具。
GOV8-9,开发计划模板,"在开发交付规约中加入开发计划模板,明确治理流、Issue 行、文件范围、依赖、验证和交接物。","1) 模板能指导 backend/frontend/qa 分工;2) 文件范围和依赖清晰;3) 交接物明确;4) 与连续型 CSV 规则一致。","流程级验证:rg -n '开发计划模板|治理流|Issue 行|文件范围|依赖|交接物' docs/开发交付与变更管理规约.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md,"[""GOV8-8""]",后续实现 worker 仍按 AGENTS 作用域约束。
GOV8-10,测试方案模板,"在开发交付规约中加入测试方案模板,覆盖主流程、异常、权限、视觉、企业微信、公网和 SKIP 条件。","1) 测试方案字段完整;2) 明确流程级 Test_Method;3) 区分本地/公网匿名/带凭据;4) SKIP 不是通过。","流程级验证:rg -n '测试方案模板|主流程|异常流程|权限|视觉|企业微信|公网|SKIP' docs/开发交付与变更管理规约.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md,"[""GOV8-9""]",测试细节仍以测试规约为准。
GOV8-11,测试计划模板,"在开发交付规约中加入测试计划模板,明确执行时机、命令、环境、证据路径、负责人和阻断条件。","1) 测试计划字段完整;2) 可形成执行清单;3) 证据路径明确;4) 阻断条件清晰。","流程级验证:rg -n '测试计划模板|执行时机|命令|环境|证据路径|负责人|阻断条件' docs/开发交付与变更管理规约.md。",rg,DONE,DONE,DONE,docs/开发交付与变更管理规约.md,"[""GOV8-10""]",不替代 docs/测试规约与回归门禁.md。
GOV8-12,文档审计脚本,"新增只读文档审计脚本,检查文档台账字段、核心路径、状态值、链接引用、敏感词和旧口径风险。","1) 脚本只读;2) --check-registry 可校验核心台账;3) --help 可用;4) 不打印真实 secret;5) 默认输出摘要。","流程级验证:node --check scripts/qa/audit-docs.mjs;node scripts/qa/audit-docs.mjs --help;node scripts/qa/audit-docs.mjs --check-registry。",node,DONE,DONE,DONE,scripts/qa/audit-docs.mjs,"[""GOV8-2""]",脚本用于治理门禁;后续可在 QAOPS8 中扩展。
GOV8-13,旧口径和敏感词审计,"用文档审计脚本和 rg 扫描旧口径、TODO、未部署、尚未完成、密钥和敏感词风险。","1) 风险输出可解释;2) 不把历史证据误判为当前缺口;3) 不泄露密钥;4) 发现阻断风险时记录到 GOV8 后续行。","流程级验证:node scripts/qa/audit-docs.mjs;rg -n 'TODO|未部署|尚未完成|secret|token|密码|密钥' docs issues scripts/qa。",node|rg,DONE,DONE,DONE,docs|issues|scripts/qa,"[""GOV8-12""]",rg 命中可能包含规则说明,需人工解释。
GOV8-14,链接和路径审计,"用文档审计脚本检查 Markdown 链接指向的本地 .md/.csv 路径是否存在。","1) 相对链接可解析;2) 绝对仓库链接可解释;3) 外部链接不误报;4) 断链进入后续修复行。","流程级验证:node scripts/qa/audit-docs.mjs --check-links。",node,DONE,DONE,DONE,scripts/qa/audit-docs.mjs|docs,"[""GOV8-12""]",脚本先覆盖 docs 下 Markdown 文档链接。
GOV8-15,当前执行合同索引规则,"固定当前活跃治理流入口,只在文档索引和状态矩阵列当前活跃连续合同,历史合同通过 README 和 git 历史追溯。","1) 当前活跃治理流表存在;2) GOV8 为当前活跃治理流;3) 未来 R7E/ORG8/WF8/BIZ8/QAOPS8 有规划入口;4) 旧 Issue 不在主入口铺开。","流程级验证:rg -n '当前活跃治理流|GOV8|R7E|ORG8|WF8|BIZ8|QAOPS8|历史合同' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。",rg,DONE,DONE,DONE,docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md,"[""GOV8-4""]",减少 Issue 文件膨胀后的入口噪声。
GOV8-16,历史 Issue 降级规则,"固定旧 Issue CSV 的处理规则:不删除、不回写、不归档目录,只通过新合同 Notes 或索引说明 supersedes。","1) 规则写入索引、状态矩阵或 README;2) 明确旧 Issue 是审计历史;3) supersedes 只写在新合同或索引;4) 不移动旧文件。","流程级验证:rg -n 'supersedes|不删除|不回写|历史审计|旧 Issue' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。",rg,DONE,DONE,DONE,docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md,"[""GOV8-15""]",保持 git 历史和审计语义。
GOV8-17,治理试运行,"用 GOV8 本身试运行连续型 Issue 流程,验证一个治理流承载多行任务、状态回填和阶段收口是否可行。","1) GOV8 CSV 承载 18 行以上任务;2) 文档/脚本变更归入同一合同;3) 校验命令可执行;4) 不额外开小 CSV。","流程级验证:读取 GOV8 CSV 行数;validate_issues_csv.py 本 CSV;人工确认本轮无额外治理 CSV。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_16-31-09-gov8-system-governance.csv,"[""GOV8-0""]",本轮即为治理试运行。
GOV8-18,GOV8 回归与状态回填,"执行 GOV8 所有文档、CSV 和脚本校验,根据实测结果回填状态。","1) CSV 校验通过;2) audit-docs 关键模式通过;3) rg 关键规则命中;4) git diff --check 通过;5) 状态按证据回填。","流程级验证:validate_issues_csv.py 本 CSV;node --check scripts/qa/audit-docs.mjs;node scripts/qa/audit-docs.mjs --check-registry;node scripts/qa/audit-docs.mjs --check-links;git diff --check。",python3|node|git,DONE,DONE,DONE,issues/2026-05-13_16-31-09-gov8-system-governance.csv|docs|scripts/qa,"[""GOV8-13"",""GOV8-14"",""GOV8-17""]",回归失败不得标 DONE。
GOV8-19,GOV8 收口报告,"输出 GOV8 变更摘要、验证结果、残留风险和后续连续治理流建议。","1) 最终回复说明改了什么;2) 说明验证命令和结果;3) 说明未部署;4) 指出下一步 R7E/ORG8/QAOPS8 入口;5) 如提交则引用 GOV8。","流程级验证:最终交付说明包含变更摘要、验证结果、部署状态和后续建议。",manual,DONE,DONE,DONE,N/A,"[""GOV8-18""]",本轮面向用户的收口报告;不要求部署。
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
2 GOV8-0 连续型治理合同建档 建立 GOV8 连续型系统治理合同,锁定本轮只做文档、流程、Issue 管理和审计脚本治理,不改 server/client 业务代码。 1) 本 CSV 校验通过;2) 范围限定 docs/issues/scripts/qa;3) 不删除旧 Issue CSV;4) 不部署;5) 后续同类治理任务优先进入本 CSV。 流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_16-31-09-gov8-system-governance.csv;人工核对 Files 范围不含 server/client 业务代码。 python3|manual DONE DONE DONE issues/2026-05-13_16-31-09-gov8-system-governance.csv [] 回滚路径:删除本 CSV 与本轮 docs/scripts/qa 变更;不影响运行环境。
3 GOV8-1 旧 Issue 现状盘点 盘点当前 Issue CSV 过多且不可轻易删除的问题,明确旧 Issue 作为历史审计证据保留,不批量回写、不挪 archive。 1) 文档写明旧 Issue 不删除;2) 当前活跃合同和历史合同分层;3) 旧合同只通过索引/状态矩阵降级;4) 不修改旧 CSV。 流程级验证:rg -n '旧 Issue|历史合同|不删除|不批量回写|当前活跃治理流' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。 rg DONE DONE DONE docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md ["GOV8-0"] 不回写历史快照;只增加治理口径。
4 GOV8-2 文档台账字段设计 把文档事实源状态矩阵升级为轻量文档台账,固定 Doc_ID、Path、Category、Authority、Status、Owner、Related_Issues、Evidence、Supersedes、Last_Audited、Audit_Method、Risk、Notes 字段。 1) 状态矩阵包含文档台账字段说明;2) 状态值包含 CURRENT/DRAFT/EVIDENCE/HISTORICAL/SUPERSEDED/REMOVED;3) 核心文档至少登记一轮;4) 审计脚本能检查字段存在。 流程级验证:node scripts/qa/audit-docs.mjs --check-registry;rg -n 'Doc_ID|CURRENT|DRAFT|EVIDENCE|HISTORICAL|SUPERSEDED|REMOVED' docs/文档事实源状态矩阵.md。 node|rg DONE DONE DONE docs/文档事实源状态矩阵.md|scripts/qa/audit-docs.mjs ["GOV8-0"] 台账先覆盖核心事实源、操作手册、草案/证据和技术参考;后续可在 GOV8 继续补全。
5 GOV8-3 核心文档分类登记 在文档台账中登记核心当前事实源、操作手册、草案证据、技术参考和已移除历史材料。 1) 当前事实源、操作手册、草案/证据、技术参考均有分类;2) 每行有 Authority 和 Status;3) 当前事实源可指导开发;4) 草案/历史不能直接派工。 流程级验证:node scripts/qa/audit-docs.mjs --check-registry;人工核对状态矩阵中核心文档分类。 node|manual DONE DONE DONE docs/文档事实源状态矩阵.md|scripts/qa/audit-docs.mjs ["GOV8-2"] 不要求一次登记所有历史 Issue;先固定核心文档台账。
6 GOV8-4 文档索引按开发阶段重写 把文档索引从文档清单升级为按开发阶段阅读入口,覆盖需求、设计、开发、测试、发布、审计、历史追溯。 1) 索引有按开发阶段阅读规则;2) 当前活跃治理流可见;3) 历史合同入口被降级;4) 草案和历史证据不得直接开发。 流程级验证:rg -n '按开发阶段阅读|需求阶段|设计阶段|开发阶段|测试阶段|发布阶段|审计阶段|当前活跃治理流|不得直接开发' docs/文档索引.md。 rg DONE DONE DONE docs/文档索引.md ["GOV8-1","GOV8-3"] 保留 DCL7 中文优先和物理精简策略。
7 GOV8-5 核心文档统一头部规则 固定核心文档顶部元数据规则,明确文档状态、分类、适用范围、上级事实源、关联 Issue、最近审计和不得误读。 1) 开发交付规约写明统一头部规则;2) 文档索引/状态矩阵已有当前头部;3) 后续新增核心文档必须套用;4) 不批量强改所有历史文档。 流程级验证:rg -n '文档状态|分类|适用范围|上级事实源|关联 Issue|最近审计|不得误读' docs/开发交付与变更管理规约.md docs/文档索引.md docs/文档事实源状态矩阵.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md|docs/文档索引.md|docs/文档事实源状态矩阵.md ["GOV8-4"] 只要求当前事实源和后续新增文档遵守;历史证据不大规模重写。
8 GOV8-6 需求冻结规则 补强需求冻结规则:非微小需求必须先进入事实源和当前连续 CSV,冻结后新增想法默认进入后续池。 1) 需求冻结规则写入开发交付规约;2) 当前轮变更准入条件明确;3) 不再为小反馈单独开 CSV;4) 后续池和冻结项分流清楚。 流程级验证:rg -n '需求冻结|后续池|当前轮变更|小反馈|连续 CSV' docs/开发交付与变更管理规约.md issues/README.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md|issues/README.md ["GOV8-5"] 开发中临时变更必须先做影响评估。
9 GOV8-7 变更请求规则 补强变更请求规则:开发中新增范围必须说明原因、影响、测试变化和是否替代原需求。 1) 变更请求字段明确;2) 不满足准入条件时进入下一阶段或同治理流后续行;3) 测试影响必须同步;4) 旧 Issue 不回写。 流程级验证:rg -n '变更请求|变更原因|影响范围|测试影响|替代原需求|下一阶段' docs/开发交付与变更管理规约.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md ["GOV8-6"] 只做流程规则,不改业务逻辑。
10 GOV8-8 设计方案模板 在开发交付规约中加入设计方案模板,覆盖数据/API、权限、状态流、页面、异常、回滚和测试影响。 1) 模板字段完整;2) 涉及权限/状态机/迁移时必须写回滚;3) 可映射到 Issue CSV;4) 不引入外部平台。 流程级验证:rg -n '设计方案模板|数据/API|权限|状态流|回滚|测试影响' docs/开发交付与变更管理规约.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md ["GOV8-7"] 复用现有 Issue CSV,不新增外部工具。
11 GOV8-9 开发计划模板 在开发交付规约中加入开发计划模板,明确治理流、Issue 行、文件范围、依赖、验证和交接物。 1) 模板能指导 backend/frontend/qa 分工;2) 文件范围和依赖清晰;3) 交接物明确;4) 与连续型 CSV 规则一致。 流程级验证:rg -n '开发计划模板|治理流|Issue 行|文件范围|依赖|交接物' docs/开发交付与变更管理规约.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md ["GOV8-8"] 后续实现 worker 仍按 AGENTS 作用域约束。
12 GOV8-10 测试方案模板 在开发交付规约中加入测试方案模板,覆盖主流程、异常、权限、视觉、企业微信、公网和 SKIP 条件。 1) 测试方案字段完整;2) 明确流程级 Test_Method;3) 区分本地/公网匿名/带凭据;4) SKIP 不是通过。 流程级验证:rg -n '测试方案模板|主流程|异常流程|权限|视觉|企业微信|公网|SKIP' docs/开发交付与变更管理规约.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md ["GOV8-9"] 测试细节仍以测试规约为准。
13 GOV8-11 测试计划模板 在开发交付规约中加入测试计划模板,明确执行时机、命令、环境、证据路径、负责人和阻断条件。 1) 测试计划字段完整;2) 可形成执行清单;3) 证据路径明确;4) 阻断条件清晰。 流程级验证:rg -n '测试计划模板|执行时机|命令|环境|证据路径|负责人|阻断条件' docs/开发交付与变更管理规约.md。 rg DONE DONE DONE docs/开发交付与变更管理规约.md ["GOV8-10"] 不替代 docs/测试规约与回归门禁.md。
14 GOV8-12 文档审计脚本 新增只读文档审计脚本,检查文档台账字段、核心路径、状态值、链接引用、敏感词和旧口径风险。 1) 脚本只读;2) --check-registry 可校验核心台账;3) --help 可用;4) 不打印真实 secret;5) 默认输出摘要。 流程级验证:node --check scripts/qa/audit-docs.mjs;node scripts/qa/audit-docs.mjs --help;node scripts/qa/audit-docs.mjs --check-registry。 node DONE DONE DONE scripts/qa/audit-docs.mjs ["GOV8-2"] 脚本用于治理门禁;后续可在 QAOPS8 中扩展。
15 GOV8-13 旧口径和敏感词审计 用文档审计脚本和 rg 扫描旧口径、TODO、未部署、尚未完成、密钥和敏感词风险。 1) 风险输出可解释;2) 不把历史证据误判为当前缺口;3) 不泄露密钥;4) 发现阻断风险时记录到 GOV8 后续行。 流程级验证:node scripts/qa/audit-docs.mjs;rg -n 'TODO|未部署|尚未完成|secret|token|密码|密钥' docs issues scripts/qa。 node|rg DONE DONE DONE docs|issues|scripts/qa ["GOV8-12"] rg 命中可能包含规则说明,需人工解释。
16 GOV8-14 链接和路径审计 用文档审计脚本检查 Markdown 链接指向的本地 .md/.csv 路径是否存在。 1) 相对链接可解析;2) 绝对仓库链接可解释;3) 外部链接不误报;4) 断链进入后续修复行。 流程级验证:node scripts/qa/audit-docs.mjs --check-links。 node DONE DONE DONE scripts/qa/audit-docs.mjs|docs ["GOV8-12"] 脚本先覆盖 docs 下 Markdown 文档链接。
17 GOV8-15 当前执行合同索引规则 固定当前活跃治理流入口,只在文档索引和状态矩阵列当前活跃连续合同,历史合同通过 README 和 git 历史追溯。 1) 当前活跃治理流表存在;2) GOV8 为当前活跃治理流;3) 未来 R7E/ORG8/WF8/BIZ8/QAOPS8 有规划入口;4) 旧 Issue 不在主入口铺开。 流程级验证:rg -n '当前活跃治理流|GOV8|R7E|ORG8|WF8|BIZ8|QAOPS8|历史合同' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。 rg DONE DONE DONE docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md ["GOV8-4"] 减少 Issue 文件膨胀后的入口噪声。
18 GOV8-16 历史 Issue 降级规则 固定旧 Issue CSV 的处理规则:不删除、不回写、不归档目录,只通过新合同 Notes 或索引说明 supersedes。 1) 规则写入索引、状态矩阵或 README;2) 明确旧 Issue 是审计历史;3) supersedes 只写在新合同或索引;4) 不移动旧文件。 流程级验证:rg -n 'supersedes|不删除|不回写|历史审计|旧 Issue' docs/文档索引.md docs/文档事实源状态矩阵.md issues/README.md。 rg DONE DONE DONE docs/文档索引.md|docs/文档事实源状态矩阵.md|issues/README.md ["GOV8-15"] 保持 git 历史和审计语义。
19 GOV8-17 治理试运行 用 GOV8 本身试运行连续型 Issue 流程,验证一个治理流承载多行任务、状态回填和阶段收口是否可行。 1) GOV8 CSV 承载 18 行以上任务;2) 文档/脚本变更归入同一合同;3) 校验命令可执行;4) 不额外开小 CSV。 流程级验证:读取 GOV8 CSV 行数;validate_issues_csv.py 本 CSV;人工确认本轮无额外治理 CSV。 python3|manual DONE DONE DONE issues/2026-05-13_16-31-09-gov8-system-governance.csv ["GOV8-0"] 本轮即为治理试运行。
20 GOV8-18 GOV8 回归与状态回填 执行 GOV8 所有文档、CSV 和脚本校验,根据实测结果回填状态。 1) CSV 校验通过;2) audit-docs 关键模式通过;3) rg 关键规则命中;4) git diff --check 通过;5) 状态按证据回填。 流程级验证:validate_issues_csv.py 本 CSV;node --check scripts/qa/audit-docs.mjs;node scripts/qa/audit-docs.mjs --check-registry;node scripts/qa/audit-docs.mjs --check-links;git diff --check。 python3|node|git DONE DONE DONE issues/2026-05-13_16-31-09-gov8-system-governance.csv|docs|scripts/qa ["GOV8-13","GOV8-14","GOV8-17"] 回归失败不得标 DONE。
21 GOV8-19 GOV8 收口报告 输出 GOV8 变更摘要、验证结果、残留风险和后续连续治理流建议。 1) 最终回复说明改了什么;2) 说明验证命令和结果;3) 说明未部署;4) 指出下一步 R7E/ORG8/QAOPS8 入口;5) 如提交则引用 GOV8。 流程级验证:最终交付说明包含变更摘要、验证结果、部署状态和后续建议。 manual DONE DONE DONE N/A ["GOV8-18"] 本轮面向用户的收口报告;不要求部署。
+22 -1
查看文件
@@ -2,6 +2,27 @@
本项目使用 Issue CSV 作为需求驱动与执行合同。
## 连续型 Issue 原则
GOV8 后默认采用“少量长期连续合同 + 多行任务 + 阶段收口”,避免每次聊天、小反馈或单点修正都创建新 CSV。
- 同类型、同目标、同风险域的问题进入同一个连续 CSV。
- 一个连续 CSV 最多承载一个治理流,不混入无关业务域。
- 只有跨业务域、跨风险等级、跨里程碑,或当前治理流阶段性收口后,才新建下一版 CSV。
- 旧 Issue CSV 不删除、不批量回写、不移动到归档目录;它们是历史审计证据。
- 当前可执行合同以 `docs/文档索引.md` 和 `docs/文档事实源状态矩阵.md` 标注的“当前活跃治理流”为准。
当前优先治理流:
| 治理流 | 建议/当前文件 | 用途 |
| --- | --- | --- |
| `GOV8` | `2026-05-13_16-31-09-gov8-system-governance.csv` | 文档、流程、Issue 管理和审计治理 |
| `R7E` | 待新建连续 CSV | 真实扩大试运行 |
| `ORG8` | 待新建连续 CSV | 组织账号和权限主数据 |
| `WF8` | 待新建连续 CSV | 审批与通知增强 |
| `BIZ8` | 待新建连续 CSV | 报销/OCR/财务/项目轻量增强 |
| `QAOPS8` | 待新建连续 CSV | 测试、发布、运维和上线准备 |
## 必填列(全部必填)
- `ID`
- `Title`
@@ -45,7 +66,7 @@
- UTF-8 编码。
## 权威读取顺序
- **当前执行合同**:优先查看时间最新且已批准的 `issues/*.csv`;当前治理收口入口为 [2026-05-05_20-01-18-r90-r91-trialrun-closeout.csv](/home/shunli/Projects/hyb-oa/issues/2026-05-05_20-01-18-r90-r91-trialrun-closeout.csv:1)。
- **当前执行合同**:优先查看 `docs/文档索引.md` 和 `docs/文档事实源状态矩阵.md` 标注的当前活跃治理流;不要只按文件时间最新判断。
- **历史蓝图链**:P5 相关只把 [2026-02-09_13-39-02-p5-blueprint-v3.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_13-39-02-p5-blueprint-v3.csv:1) 视为权威完成态;[2026-02-09_11-17-07-p5-blueprint.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_11-17-07-p5-blueprint.csv:1) 和 [2026-02-09_12-34-42-p5-blueprint-v2.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_12-34-42-p5-blueprint-v2.csv:1) 保留为历史快照,不再单独作为当前待办来源。
- **试运行链**:本地/外部试运行相关优先串读 `R70 -> R71 -> R73 -> R74 -> R75 -> R76 -> R77 -> R78 -> R79 -> R80 -> R82 -> R83-R86 -> R87 -> R88 -> R89 -> R90/R91`,不要只看单一 CSV 判断系统状态。
- **跨文档事实源**:业务能力现状优先结合 [历史功能状态矩阵.md](/home/shunli/Projects/hyb-oa/docs/历史功能状态矩阵.md:1)、[试运行覆盖矩阵.csv](/home/shunli/Projects/hyb-oa/docs/trialrun/试运行覆盖矩阵.csv:1) 和 [人工试运行报告.md](/home/shunli/Projects/hyb-oa/docs/trialrun/人工试运行报告.md:1) 阅读。
+259
查看文件
@@ -0,0 +1,259 @@
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
const repoRoot = process.cwd();
const args = new Set(process.argv.slice(2));
const registryPath = 'docs/文档事实源状态矩阵.md';
const requiredFields = [
'Doc_ID',
'Path',
'Category',
'Authority',
'Status',
'Owner',
'Related_Issues',
'Evidence',
'Supersedes',
'Last_Audited',
'Audit_Method',
'Risk',
'Notes',
];
const validStatuses = new Set([
'CURRENT',
'DRAFT',
'EVIDENCE',
'HISTORICAL',
'SUPERSEDED',
'REMOVED',
]);
const requiredCorePaths = [
'docs/文档索引.md',
'docs/文档事实源状态矩阵.md',
'docs/海音达OA-MVP需求规格说明书.md',
'docs/开发交付与变更管理规约.md',
'docs/测试规约与回归门禁.md',
'docs/产品设计规则.md',
'docs/产品口径.md',
'AGENTS.md',
'.agents/skills/hyb-oa-delivery/SKILL.md',
];
function printHelp() {
console.log(`Usage: node scripts/qa/audit-docs.mjs [options]
Options:
--check-registry Validate docs registry fields, status values, and core paths.
--check-links Scan docs markdown links to local .md/.csv targets.
--help Show this help.
Default without options runs registry, link, stale-term, and sensitive-risk checks.
This script is read-only and never prints secret values.`);
}
function readText(relativePath) {
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
}
function pathExists(relativePath) {
return fs.existsSync(path.join(repoRoot, relativePath));
}
function listFiles(dir, predicate = () => true) {
const absDir = path.join(repoRoot, dir);
if (!fs.existsSync(absDir)) return [];
const result = [];
for (const entry of fs.readdirSync(absDir, { withFileTypes: true })) {
const relative = path.join(dir, entry.name);
if (entry.isDirectory()) {
result.push(...listFiles(relative, predicate));
} else if (predicate(relative)) {
result.push(relative);
}
}
return result;
}
function extractRegistryTable() {
const text = readText(registryPath);
const marker = '## 文档台账';
const start = text.indexOf(marker);
if (start < 0) {
return { header: [], rows: [], errors: ['missing registry section: ## 文档台账'] };
}
const after = text.slice(start + marker.length);
const nextSection = after.search(/\n## /);
const section = nextSection >= 0 ? after.slice(0, nextSection) : after;
const tableLines = section
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.startsWith('|') && line.endsWith('|'));
if (tableLines.length < 2) {
return { header: [], rows: [], errors: ['registry table is missing or too short'] };
}
const cells = (line) => line.slice(1, -1).split('|').map((cell) => cell.trim());
const header = cells(tableLines[0]);
const rows = tableLines.slice(2).map((line) => cells(line));
return { header, rows, errors: [] };
}
function stripCode(value) {
return value.replace(/^`|`$/g, '').trim();
}
function checkRegistry() {
const errors = [];
const warnings = [];
if (!pathExists(registryPath)) {
return { errors: [`missing ${registryPath}`], warnings };
}
const { header, rows, errors: parseErrors } = extractRegistryTable();
errors.push(...parseErrors);
for (const field of requiredFields) {
if (!header.includes(field)) {
errors.push(`registry missing field: ${field}`);
}
}
const pathIndex = header.indexOf('Path');
const statusIndex = header.indexOf('Status');
const registeredPaths = new Set();
for (const row of rows) {
if (row.length !== header.length) {
errors.push(`registry row has ${row.length} cells, expected ${header.length}: ${row.join(' | ')}`);
continue;
}
const docPath = stripCode(row[pathIndex] ?? '');
const status = stripCode(row[statusIndex] ?? '');
registeredPaths.add(docPath);
if (!validStatuses.has(status)) {
errors.push(`invalid status ${status || '<empty>'} for ${docPath}`);
}
if (status !== 'REMOVED' && docPath !== 'none' && !pathExists(docPath)) {
errors.push(`registered path missing: ${docPath}`);
}
}
for (const corePath of requiredCorePaths) {
if (!registeredPaths.has(corePath)) {
errors.push(`core path not registered: ${corePath}`);
}
}
const docsFiles = listFiles('docs', (file) => file.endsWith('.md') || file.endsWith('.csv'));
const unregistered = docsFiles.filter((file) => !registeredPaths.has(file));
if (unregistered.length > 0) {
warnings.push(`unregistered docs files: ${unregistered.length}`);
}
return { errors, warnings };
}
function normalizeLinkTarget(sourceFile, target) {
let clean = target.trim();
if (clean.startsWith('<') && clean.endsWith('>')) clean = clean.slice(1, -1);
if (/^(https?:|mailto:|#)/i.test(clean)) return null;
clean = clean.split('#')[0].trim();
if (!clean || !/\.(md|csv)$/i.test(clean)) return null;
if (clean.startsWith('/home/shunli/Projects/hyb-oa/')) {
return path.relative(repoRoot, clean);
}
if (clean.startsWith('/')) return null;
return path.normalize(path.join(path.dirname(sourceFile), clean));
}
function checkLinks() {
const errors = [];
const warnings = [];
const markdownFiles = listFiles('docs', (file) => file.endsWith('.md'));
const linkPattern = /\[[^\]]+\]\(([^)]+)\)/g;
for (const file of markdownFiles) {
const text = readText(file);
for (const match of text.matchAll(linkPattern)) {
const normalized = normalizeLinkTarget(file, match[1]);
if (!normalized) continue;
if (!pathExists(normalized)) {
warnings.push(`broken local link in ${file}: ${match[1]}`);
}
}
}
return { errors, warnings };
}
function checkSensitiveRisk() {
const warnings = [];
const files = [
...listFiles('docs', (file) => /\.(md|csv)$/i.test(file)),
...listFiles('issues', (file) => file.endsWith('.csv') || file.endsWith('.md')),
...listFiles('scripts/qa', (file) => /\.(mjs|js|sh)$/i.test(file)),
];
const patterns = [
/BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY/,
/AKIA[0-9A-Z]{16}/,
/(secret|token|password|api[_-]?key)\s*[:=]\s*['"]?[A-Za-z0-9_./+=-]{16,}/i,
];
for (const file of files) {
const text = readText(file);
if (patterns.some((pattern) => pattern.test(text))) {
warnings.push(`possible sensitive literal risk in ${file}`);
}
}
return { errors: [], warnings };
}
function checkStaleTerms() {
const warnings = [];
const currentDocs = [
'docs/文档索引.md',
'docs/文档事实源状态矩阵.md',
'docs/海音达OA-MVP需求规格说明书.md',
'docs/开发交付与变更管理规约.md',
'docs/测试规约与回归门禁.md',
];
const staleTerms = ['TODO', '未部署', '尚未完成', '下一批', '旧口径'];
for (const file of currentDocs) {
if (!pathExists(file)) continue;
const text = readText(file);
const hits = staleTerms.filter((term) => text.includes(term));
if (hits.length > 0) {
warnings.push(`stale-term review needed in ${file}: ${hits.join(', ')}`);
}
}
return { errors: [], warnings };
}
function mergeResults(results) {
return results.reduce(
(acc, item) => ({
errors: [...acc.errors, ...item.errors],
warnings: [...acc.warnings, ...item.warnings],
}),
{ errors: [], warnings: [] },
);
}
if (args.has('--help')) {
printHelp();
process.exit(0);
}
const checks = [];
if (args.has('--check-registry')) checks.push(checkRegistry);
if (args.has('--check-links')) checks.push(checkLinks);
if (checks.length === 0) {
checks.push(checkRegistry, checkLinks, checkStaleTerms, checkSensitiveRisk);
}
const result = mergeResults(checks.map((check) => check()));
console.log(`audit-docs: errors=${result.errors.length} warnings=${result.warnings.length}`);
for (const warning of result.warnings.slice(0, 40)) {
console.log(`warning: ${warning}`);
}
if (result.warnings.length > 40) {
console.log(`warning: ${result.warnings.length - 40} more warnings omitted`);
}
for (const error of result.errors) {
console.error(`error: ${error}`);
}
process.exit(result.errors.length === 0 ? 0 : 1);