WPROC2 增加开发流程自动化门禁

这个提交包含在:
2026-05-19 12:26:53 +08:00
父节点 bb5e204d95
当前提交 45caee97ba
共修改 12 个文件,包含 694 行新增和 36 行删除
+2 -2
查看文件
@@ -17,7 +17,7 @@ Read only what is relevant:
- For approval workflow, roles, self-approval, notification, deeplink, reminder, or escalation work, read `docs/需求-统一审批中心规约.md`. - For approval workflow, roles, self-approval, notification, deeplink, reminder, or escalation work, read `docs/需求-统一审批中心规约.md`.
- For HR lifecycle, employee onboarding/offboarding, Enterprise WeChat directory sync, account disablement, or Enterprise WeChat API work, read `docs/需求-企业微信基础设施规约.md`, `docs/企微API能力目录.md`, `docs/管理员手册.md`, and the latest HCLT/HRWD/WAPI/WRRA Issue CSV evidence first. - For HR lifecycle, employee onboarding/offboarding, Enterprise WeChat directory sync, account disablement, or Enterprise WeChat API work, read `docs/需求-企业微信基础设施规约.md`, `docs/企微API能力目录.md`, `docs/管理员手册.md`, and the latest HCLT/HRWD/WAPI/WRRA Issue CSV evidence first.
- For any Enterprise WeChat capability, Secret, callback, approval, check-in, HR assistant, or contact-directory task, read `docs/企微API能力目录.md` before planning or coding. WAPI fixes the current Secret matrix: contacts use `WECOM_CONTACT_SECRET`; workbench/OAuth/messages/HR assistant/roster/check-in/approval use `WECOM_AGENT_SECRET`; `WECOM_CHECKIN_SECRET` is only an explicit check-in override; `WECOM_HR_ASSISTANT_SECRET` is historical compatibility and not a default. Do not write runtime code that tries multiple Secrets to guess the correct one. - For any Enterprise WeChat capability, Secret, callback, approval, check-in, HR assistant, or contact-directory task, read `docs/企微API能力目录.md` before planning or coding. WAPI fixes the current Secret matrix: contacts use `WECOM_CONTACT_SECRET`; workbench/OAuth/messages/HR assistant/roster/check-in/approval use `WECOM_AGENT_SECRET`; `WECOM_CHECKIN_SECRET` is only an explicit check-in override; `WECOM_HR_ASSISTANT_SECRET` is historical compatibility and not a default. Do not write runtime code that tries multiple Secrets to guess the correct one.
- For Enterprise WeChat-first HR/attendance runtime migration, read `docs/企微优先开发路线图.md` before planning or coding. WDRG makes the roadmap authoritative for stage order; WAPI adds the runtime-first stage before deep mirror work; WRRA states that WOUA `PASS_WITH_FINDINGS` does not clear deep mirror work; WOUA-FIX has now soft-archived the 7 OA active test accounts missing in WeCom, fixed the `T0000` seed reactivation behavior, transferred the `SMOKE201` test-manager side effects, and rerun WOUA with `oaActiveMissingInWecom=0`. WCPC has rerun the capability POC with an existing active test account and reached `GO_TO_HR_MASTER_SYNC`; WHMS/WHMSLIVE has implemented, deployed, and publicly verified `wecom_hr_master_sync_v1`, with the production flag restored to `force_off` and production real-employee batch apply not approved. WMSG1 proves real app-message delivery and Deeplink return only; WAPC1 fixes the approval configuration preparation checklist before mirror work; WAPC2 adds the leave/missed-punch approval template and low-risk `sp_no` read-only POC runner. WPROC1 fixes the engineering route: WAPC2 must be followed by WAPC2F automatic POC fixtures, WAPC2 rerun, WCBK1 callback POC, WACP3 compensation-pull POC, and WADM1 mirror data model design before `wecom_attendance_approval_mirror_v1`. Do not start `wecom_attendance_approval_mirror_v1`, `oa_hr_emergency_mode_v1`, `wecom_recovery_writeback_v1`, or `wecom_ruleops_v1` without the next stage's own Issue CSV. - For Enterprise WeChat-first HR/attendance runtime migration, read `docs/企微优先开发路线图.md` before planning or coding. WDRG makes the roadmap authoritative for stage order; WAPI adds the runtime-first stage before deep mirror work; WRRA states that WOUA `PASS_WITH_FINDINGS` does not clear deep mirror work; WOUA-FIX has now soft-archived the 7 OA active test accounts missing in WeCom, fixed the `T0000` seed reactivation behavior, transferred the `SMOKE201` test-manager side effects, and rerun WOUA with `oaActiveMissingInWecom=0`. WCPC has rerun the capability POC with an existing active test account and reached `GO_TO_HR_MASTER_SYNC`; WHMS/WHMSLIVE has implemented, deployed, and publicly verified `wecom_hr_master_sync_v1`, with the production flag restored to `force_off` and production real-employee batch apply not approved. WMSG1 proves real app-message delivery and Deeplink return only; WAPC1 fixes the approval configuration preparation checklist before mirror work; WAPC2 adds the leave/missed-punch approval template and low-risk `sp_no` read-only POC runner. WPROC1 fixes the engineering route: WAPC2 must be followed by WAPC2F automatic POC fixtures, WAPC2 rerun, WCBK1 callback POC, WACP3 compensation-pull POC, and WADM1 mirror data model design before `wecom_attendance_approval_mirror_v1`. WPROC2 adds the executable `process gate`: before WAPC2F or other high-risk WeCom work, run `node scripts/qa/check-process-contract.mjs --baseline` and the issue-specific profile check to enforce DoR/DoD, fixed Secret source, non-self approval, live write switches, missing-config classification, and redaction boundaries. Do not start `wecom_attendance_approval_mirror_v1`, `oa_hr_emergency_mode_v1`, `wecom_recovery_writeback_v1`, or `wecom_ruleops_v1` without the next stage's own Issue CSV.
- For reimbursement, invoice, OCR, duplicate invoice, or attachment work, read `docs/报销发票附件规则.md` and `references/reimbursement.md`. - For reimbursement, invoice, OCR, duplicate invoice, or attachment work, read `docs/报销发票附件规则.md` and `references/reimbursement.md`.
- For local/WeCom/public trial-run, OCR runtime, Caddy, or DB drift work, read `docs/试运行与自动化验证手册.md` and `references/trialrun.md`. - For local/WeCom/public trial-run, OCR runtime, Caddy, or DB drift work, read `docs/试运行与自动化验证手册.md` and `references/trialrun.md`.
- For how this skill should evolve, read `docs/Agent开发交付实践.md`. - For how this skill should evolve, read `docs/Agent开发交付实践.md`.
@@ -110,7 +110,7 @@ Final responses should include:
- WMSG1 has verified real Enterprise WeChat personal-app delivery and Deeplink return: report `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T234431Z/summary.json` has `checks.message.status=OK`, `errcode=0`, and `recipientCount=1`; the user confirmed receiving "OA 运行就绪检查" and opening the OA notifications page from the message. This only clears message/deeplink runtime evidence; approval template ID, approval `sp_no`, callback config, and deep mirror work remain separate later gates. - WMSG1 has verified real Enterprise WeChat personal-app delivery and Deeplink return: report `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T234431Z/summary.json` has `checks.message.status=OK`, `errcode=0`, and `recipientCount=1`; the user confirmed receiving "OA 运行就绪检查" and opening the OA notifications page from the message. This only clears message/deeplink runtime evidence; approval template ID, approval `sp_no`, callback config, and deep mirror work remain separate later gates.
- WAPC1 has fixed the WeCom approval configuration preparation gate: first templates are leave, missed punch, outing, and overtime; each needs template ID, scope, fields, approver rules, visible scope, and self-built app permission; low-risk test `sp_no` must not contain procurement, contract, reimbursement, invoice, bank receipt, sensitive attachment, or real sensitive business material; callback URL/Token/EncodingAESKey are deployment-only values and must not be written to repo docs or Issue CSV. Do not implement real approval callback handling, deep mirror, emergency mode, recovery writeback, or RuleOps until a later approved Issue covers the POC or implementation. - WAPC1 has fixed the WeCom approval configuration preparation gate: first templates are leave, missed punch, outing, and overtime; each needs template ID, scope, fields, approver rules, visible scope, and self-built app permission; low-risk test `sp_no` must not contain procurement, contract, reimbursement, invoice, bank receipt, sensitive attachment, or real sensitive business material; callback URL/Token/EncodingAESKey are deployment-only values and must not be written to repo docs or Issue CSV. Do not implement real approval callback handling, deep mirror, emergency mode, recovery writeback, or RuleOps until a later approved Issue covers the POC or implementation.
- WAPC2 has added the WeCom approval template/detail read-only POC runner for leave and missed punch. Use `npm run check:wecom-approval-poc`; pass template IDs with `--template=leave:<id>` / `--template=missed_punch:<id>` and low-risk test approval numbers with `--sp-no=leave:<sp_no>` / `--sp-no=missed_punch:<sp_no>`. The runner must use only `WECOM_AGENT_SECRET`, redact full template IDs and `sp_no`, and never output form values, attachments, comments, full userid, token, Secret, or raw payload. - WAPC2 has added the WeCom approval template/detail read-only POC runner for leave and missed punch. Use `npm run check:wecom-approval-poc`; pass template IDs with `--template=leave:<id>` / `--template=missed_punch:<id>` and low-risk test approval numbers with `--sp-no=leave:<sp_no>` / `--sp-no=missed_punch:<sp_no>`. The runner must use only `WECOM_AGENT_SECRET`, redact full template IDs and `sp_no`, and never output form values, attachments, comments, full userid, token, Secret, or raw payload.
- WPROC1 fixes the WeCom approval engineering process. Future WeCom work must satisfy route gate, capability gate, and implementation gate; use automatic runners before asking the user to do manual work. Manual work is limited to write approval, secrets/callback config, WeCom backend settings that cannot be API-driven, real-device confirmation, and risk decisions. High-risk stages require POC before implementation: callback signature/decryption/idempotency, compensation pull, mirror data model, then mirror implementation. - WPROC1 fixes the WeCom approval engineering process. Future WeCom work must satisfy route gate, capability gate, and implementation gate; use automatic runners before asking the user to do manual work. WPROC2 makes this executable through `node scripts/qa/check-process-contract.mjs --baseline` plus issue-specific profiles such as `--profile wecom-approval-fixture`; run it before WAPC2F and later high-risk WeCom contracts. Manual work is limited to write approval, secrets/callback config, WeCom backend settings that cannot be API-driven, real-device confirmation, and risk decisions. High-risk stages require POC before implementation: callback signature/decryption/idempotency, compensation pull, mirror data model, then mirror implementation.
- Approval-chain correctness can be proven by PC or automation, while Enterprise WeChat validates entry, binding,免登录, notification, deeplink, and mobile layout. - Approval-chain correctness can be proven by PC or automation, while Enterprise WeChat validates entry, binding,免登录, notification, deeplink, and mobile layout.
- If real-device mobile validation is paused after automation passes, record the gate as `PAUSED`; do not close RS6/UI6/R6 mobile blockers until representative real-device confirmation is recorded. - If real-device mobile validation is paused after automation passes, record the gate as `PAUSED`; do not close RS6/UI6/R6 mobile blockers until representative real-device confirmation is recorded.
- Role-specific pages should use one shared OA/mobile framework and tailor summaries, entries, actions, and sensitive fields by role. Do not create unrelated UI systems for employee, approver, finance, admin, or CEO views. - Role-specific pages should use one shared OA/mobile framework and tailor summaries, entries, actions, and sensitive fields by role. Do not create unrelated UI systems for employee, approver, finance, admin, or CEO views.
+3 -2
查看文件
@@ -2,8 +2,8 @@
**文档状态**:当前企微 API 调研与本项目使用事实源。 **文档状态**:当前企微 API 调研与本项目使用事实源。
**分类**:集成事实源 / API 能力目录。 **分类**:集成事实源 / API 能力目录。
**适用时间**:WAPI / WAPC1 / WAPC2 / WPROC1 之后。 **适用时间**:WAPI / WAPC1 / WAPC2 / WPROC1 / WPROC2 之后。
**关联 Issue**:`WAPI,WAPC1,WAPC2,WPROC1`。 **关联 Issue**:`WAPI,WAPC1,WAPC2,WPROC1,WPROC2`。
**最近核对**:2026-05-19。 **最近核对**:2026-05-19。
**不得误读**:本文只记录本项目会用到的企业微信官方 API 摘要、链接和项目决策,不复制官方文档全文,不保存 Secret、access token、完整 userid、手机号、邮箱或企微原始 payload。官方文档和企业微信后台权限配置始终是最终依据。 **不得误读**:本文只记录本项目会用到的企业微信官方 API 摘要、链接和项目决策,不复制官方文档全文,不保存 Secret、access token、完整 userid、手机号、邮箱或企微原始 payload。官方文档和企业微信后台权限配置始终是最终依据。
@@ -14,6 +14,7 @@
- 产品 UI 支持不等于开放 API 支持。入职、转正、离职、工资条确认、考勤确认等人事助手产品能力,只有在官方 API 明确支持并通过 POC 后才能进入自动化实现。 - 产品 UI 支持不等于开放 API 支持。入职、转正、离职、工资条确认、考勤确认等人事助手产品能力,只有在官方 API 明确支持并通过 POC 后才能进入自动化实现。
- 生产写接口、真实员工批量同步、企微规则写入、应急模式开启和恢复回写都必须另建合同并获得明确批准。 - 生产写接口、真实员工批量同步、企微规则写入、应急模式开启和恢复回写都必须另建合同并获得明确批准。
- WPROC1 后默认自动化优先:能用 runner 自动生成、自动检查、自动复跑的,不要求人工手动操作;人工只处理写入批准、Secret/Token/EncodingAESKey 配置、企微后台无法 API 化配置、真机确认和风险拍板。 - WPROC1 后默认自动化优先:能用 runner 自动生成、自动检查、自动复跑的,不要求人工手动操作;人工只处理写入批准、Secret/Token/EncodingAESKey 配置、企微后台无法 API 化配置、真机确认和风险拍板。
- WPROC2 后,企微高风险合同必须先通过 `node scripts/qa/check-process-contract.mjs --baseline` 和对应 profile 的 process gate;WAPC2F 使用 `wecom-approval-fixture` profile。
- 审批类 POC 默认禁止自审;WAPC2F 默认测试链为申请人 `SMOKE002`、审批人 `SMOKE101`,两者必须 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid。若 `SMOKE101` 不可用,不自动换人,返回配置缺口并问答确认。 - 审批类 POC 默认禁止自审;WAPC2F 默认测试链为申请人 `SMOKE002`、审批人 `SMOKE101`,两者必须 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid。若 `SMOKE101` 不可用,不自动换人,返回配置缺口并问答确认。
## 2. Secret 矩阵 ## 2. Secret 矩阵
+5 -4
查看文件
@@ -2,10 +2,10 @@
**文档状态**:当前开发路线图事实源。 **文档状态**:当前开发路线图事实源。
**分类**:开发治理 / 路线图。 **分类**:开发治理 / 路线图。
**适用时间**:WDRG / WCP1 / WHMSLIVE / WOUA / WAPI / WRRA / WOUA-FIX / WRV1 / WRA1 / WMSG1 / WAPC1 / WAPC2 / WPROC1 之后。 **适用时间**:WDRG / WCP1 / WHMSLIVE / WOUA / WAPI / WRRA / WOUA-FIX / WRV1 / WRA1 / WMSG1 / WAPC1 / WAPC2 / WPROC1 / WPROC2 之后。
**关联 Issue**:`WDRG,WCP1,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1`。 **关联 Issue**:`WDRG,WCP1,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1,WPROC2`。
**最近审计**:2026-05-19。 **最近审计**:2026-05-19。
**不得误读**:本文只控制后续开发节奏、阶段顺序和门禁。WHMSLIVE 后只代表企微 HR 主数据镜像已部署并受控验证;WAPI 后进一步固定企微 API/Secret 口径并转为运行优先;WRRA 后明确 `PASS_WITH_FINDINGS` 只代表只读对账成功且存在差异,不代表企微考勤/审批镜像、OA 应急接管、恢复回写或 RuleOps 已完成运行时实现。WMSG1 只证明企业微信应用消息可达和 Deeplink 可回到 OA;WAPC1 只固化审批配置准备清单;WAPC2 只新增请假/补卡模板详情和低风险 `sp_no` 审批详情只读 POC,不代表真实回调或镜像能力已完成。WPROC1 后,WAPC2 不直接放行深度镜像,必须先完成自动样件、回调、补偿拉取和镜像数据模型设计门禁。 **不得误读**:本文只控制后续开发节奏、阶段顺序和门禁。WHMSLIVE 后只代表企微 HR 主数据镜像已部署并受控验证;WAPI 后进一步固定企微 API/Secret 口径并转为运行优先;WRRA 后明确 `PASS_WITH_FINDINGS` 只代表只读对账成功且存在差异,不代表企微考勤/审批镜像、OA 应急接管、恢复回写或 RuleOps 已完成运行时实现。WMSG1 只证明企业微信应用消息可达和 Deeplink 可回到 OA;WAPC1 只固化审批配置准备清单;WAPC2 只新增请假/补卡模板详情和低风险 `sp_no` 审批详情只读 POC,不代表真实回调或镜像能力已完成。WPROC1 后,WAPC2 不直接放行深度镜像,必须先完成自动样件、回调、补偿拉取和镜像数据模型设计门禁。WPROC2 只新增可执行 process gate,不实现 WAPC2F 业务能力。
## 1. 路线图原则 ## 1. 路线图原则
@@ -36,6 +36,7 @@
| `WAPC1` | 配置准备清单已固化 | WMSG1 后的下一步改为审批配置准备清单:首批关注请假、补卡、外出、加班模板;准备模板 ID、低风险测试 `sp_no`、真实回调 URL/Token/EncodingAESKey 和后续 POC 准入项。本阶段不接真实回调、不调用写接口、不进入深度镜像。 | | `WAPC1` | 配置准备清单已固化 | WMSG1 后的下一步改为审批配置准备清单:首批关注请假、补卡、外出、加班模板;准备模板 ID、低风险测试 `sp_no`、真实回调 URL/Token/EncodingAESKey 和后续 POC 准入项。本阶段不接真实回调、不调用写接口、不进入深度镜像。 |
| `WAPC2` | 已部署并公网只读复跑 | 新增 QA-only `npm run check:wecom-approval-poc`,范围先锁定请假和补卡;固定 `WECOM_AGENT_SECRET` 调用 `POST /cgi-bin/oa/gettemplatedetail` 与 `POST /cgi-bin/oa/getapprovaldetail`,报告只输出脱敏模板 ID/`sp_no` 前缀、字段/节点计数和错误分类。公网报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`:Secret 可用,但缺请假/补卡模板 ID 和两条低风险 `sp_no`,未伪造成 PASS。 | | `WAPC2` | 已部署并公网只读复跑 | 新增 QA-only `npm run check:wecom-approval-poc`,范围先锁定请假和补卡;固定 `WECOM_AGENT_SECRET` 调用 `POST /cgi-bin/oa/gettemplatedetail` 与 `POST /cgi-bin/oa/getapprovaldetail`,报告只输出脱敏模板 ID/`sp_no` 前缀、字段/节点计数和错误分类。公网报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`:Secret 可用,但缺请假/补卡模板 ID 和两条低风险 `sp_no`,未伪造成 PASS。 |
| `WPROC1` | 路线与流程门禁已修正 | 固化三层门禁、Definition of Ready、Definition of Done、自动化优先和非自审规则。后续路线调整为 `WAPC2 -> WAPC2F 自动生成 POC 样件 -> WAPC2 自动复跑 -> WCBK1 回调只读 POC -> WACP3 补偿拉取 POC -> WADM1 镜像数据模型设计 -> wecom_attendance_approval_mirror_v1`。WAPC2F 默认测试链为 `SMOKE002 -> SMOKE101`,若 `SMOKE101` 不可用,不自动换人,先问答确认。 | | `WPROC1` | 路线与流程门禁已修正 | 固化三层门禁、Definition of Ready、Definition of Done、自动化优先和非自审规则。后续路线调整为 `WAPC2 -> WAPC2F 自动生成 POC 样件 -> WAPC2 自动复跑 -> WCBK1 回调只读 POC -> WACP3 补偿拉取 POC -> WADM1 镜像数据模型设计 -> wecom_attendance_approval_mirror_v1`。WAPC2F 默认测试链为 `SMOKE002 -> SMOKE101`,若 `SMOKE101` 不可用,不自动换人,先问答确认。 |
| `WPROC2` | 流程自动化门禁已新增 | 新增 `scripts/qa/check-process-contract.mjs`,把 WPROC1 的三层门禁、DoR/DoD、自动化优先、非自审、Secret 固定、live 写入开关、缺配置分类和脱敏边界升级为可执行 process gate;WAPC2F 实施前必须先通过 baseline gate 和 `wecom-approval-fixture` profile。 |
## 3. 阶段路线 ## 3. 阶段路线
@@ -45,7 +46,7 @@
| 2 | `wecom_hr_master_sync_v1` | 企微/人事助手员工、部门、主管、职位、联系方式和在职状态镜像到 OA。 | POC 证明人事助手/通讯录读取和回调能力可用,或明确缺口处理方式。 | WHMSLIVE 后已完成本地门禁、部署和受控公网验证;OA 可自动创建/更新员工档案、账号、角色、企微绑定和审计;最终 `force_off`,真实员工批量 apply 仍需单独批准;缺配置时记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 | | 2 | `wecom_hr_master_sync_v1` | 企微/人事助手员工、部门、主管、职位、联系方式和在职状态镜像到 OA。 | POC 证明人事助手/通讯录读取和回调能力可用,或明确缺口处理方式。 | WHMSLIVE 后已完成本地门禁、部署和受控公网验证;OA 可自动创建/更新员工档案、账号、角色、企微绑定和审计;最终 `force_off`,真实员工批量 apply 仍需单独批准;缺配置时记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 |
| 3 | `runtime_first_wecom_enablement` | 先把已可用企微能力用于系统运行:入口、免登/绑定、脱敏消息、deeplink、通讯录 userid 清单、人事助手读取、打卡读取和只读对账。 | WAPI API 目录和 Secret 矩阵完成;WOUA 按新读取策略复跑。 | WOUA-FIX 后 OA active 缺企微已清零;WRV1/WRA1 通过 `check:wecom-runtime-ready` 给出运行优先结论;WMSG1 已证明真实消息和 Deeplink 可用。`PASS_WITH_CONFIG_GAPS` 只允许继续入口、免登、消息和只读读取主链路,不放行深度镜像;审批模板、测试 `sp_no`、真实回调仍阻断 `wecom_attendance_approval_mirror_v1`。 | | 3 | `runtime_first_wecom_enablement` | 先把已可用企微能力用于系统运行:入口、免登/绑定、脱敏消息、deeplink、通讯录 userid 清单、人事助手读取、打卡读取和只读对账。 | WAPI API 目录和 Secret 矩阵完成;WOUA 按新读取策略复跑。 | WOUA-FIX 后 OA active 缺企微已清零;WRV1/WRA1 通过 `check:wecom-runtime-ready` 给出运行优先结论;WMSG1 已证明真实消息和 Deeplink 可用。`PASS_WITH_CONFIG_GAPS` 只允许继续入口、免登、消息和只读读取主链路,不放行深度镜像;审批模板、测试 `sp_no`、真实回调仍阻断 `wecom_attendance_approval_mirror_v1`。 |
| 4 | `WAPC1 / WAPC2` | 审批配置准备和请假/补卡模板详情、低风险审批详情只读 POC。 | 运行优先门禁完成;WMSG1 消息和 Deeplink 已确认。 | WAPC2 runner 已部署,缺模板 ID 或 `sp_no` 时真实记录 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,不放行深度镜像。 | | 4 | `WAPC1 / WAPC2` | 审批配置准备和请假/补卡模板详情、低风险审批详情只读 POC。 | 运行优先门禁完成;WMSG1 消息和 Deeplink 已确认。 | WAPC2 runner 已部署,缺模板 ID 或 `sp_no` 时真实记录 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,不放行深度镜像。 |
| 5 | `WAPC2F 自动生成 POC 样件` | 尽量用 QA-only runner 自动创建 OA-POC 请假/补卡测试模板和低风险测试审批单。 | WAPC2 已证明 Secret 可用但缺模板或 `sp_no`;用户批准低风险企微测试样件写入。 | 默认 dry-run;live 写入必须显式开关;申请人 `SMOKE002`、审批人 `SMOKE101` 通过 active、绑定、可见和非自审预检;缺权限或不支持时记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 | | 5 | `WAPC2F 自动生成 POC 样件` | 尽量用 QA-only runner 自动创建 OA-POC 请假/补卡测试模板和低风险测试审批单。 | WAPC2 已证明 Secret 可用但缺模板或 `sp_no`;WPROC2 baseline gate 和 WAPC2F profile gate 通过;用户批准低风险企微测试样件写入。 | 默认 dry-run;live 写入必须显式开关;申请人 `SMOKE002`、审批人 `SMOKE101` 通过 active、绑定、可见和非自审预检;缺权限或不支持时记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 |
| 6 | `WAPC2 自动复跑` | 使用 WAPC2F 生成的脱敏模板 ID 和 `sp_no` 自动复跑只读 POC。 | WAPC2F 生成全部或部分样件。 | 请假/补卡模板详情与审批详情可读为 `PASS_APPROVAL_POC`;部分缺项为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`。 | | 6 | `WAPC2 自动复跑` | 使用 WAPC2F 生成的脱敏模板 ID 和 `sp_no` 自动复跑只读 POC。 | WAPC2F 生成全部或部分样件。 | 请假/补卡模板详情与审批详情可读为 `PASS_APPROVAL_POC`;部分缺项为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`。 |
| 7 | `WCBK1 回调只读 POC` | 证明真实回调 URL 验证、验签、解密、幂等键和重复投递处理。 | 回调 URL、Token、EncodingAESKey 由部署环境配置;不得写入仓库或聊天。 | 真实回调可达、可验签/解密、重复投递幂等、失败重试语义明确;缺配置记录 `NEEDS_CONFIG`。 | | 7 | `WCBK1 回调只读 POC` | 证明真实回调 URL 验证、验签、解密、幂等键和重复投递处理。 | 回调 URL、Token、EncodingAESKey 由部署环境配置;不得写入仓库或聊天。 | 真实回调可达、可验签/解密、重复投递幂等、失败重试语义明确;缺配置记录 `NEEDS_CONFIG`。 |
| 8 | `WACP3 补偿拉取 POC` | 证明按时间窗口批量获取审批单号并可拉取审批详情,作为回调丢失补偿。 | WAPC2 或 WAPC2F 至少能提供低风险样例;官方 API 和权限明确。 | 能按窗口拿到审批单号并拉详情;不能伪造成 PASS,权限或可信 IP 问题记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 | | 8 | `WACP3 补偿拉取 POC` | 证明按时间窗口批量获取审批单号并可拉取审批详情,作为回调丢失补偿。 | WAPC2 或 WAPC2F 至少能提供低风险样例;官方 API 和权限明确。 | 能按窗口拿到审批单号并拉详情;不能伪造成 PASS,权限或可信 IP 问题记录 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`。 |
+8 -1
查看文件
@@ -3,7 +3,7 @@
**文档状态**:当前开发交付事实源。 **文档状态**:当前开发交付事实源。
**分类**:开发治理。 **分类**:开发治理。
**适用范围**:hyb-oa 所有非微小代码、文档、测试、脚本和部署准备变更。 **适用范围**:hyb-oa 所有非微小代码、文档、测试、脚本和部署准备变更。
**关联 Issue**:`GOV8,WDRG,WPROC1`。 **关联 Issue**:`GOV8,WDRG,WPROC1,WPROC2`。
**最近审计**:2026-05-19。 **最近审计**:2026-05-19。
**不得误读**:本文定义开发和变更流程,不替代具体业务 PRD、模块规约或测试规约。 **不得误读**:本文定义开发和变更流程,不替代具体业务 PRD、模块规约或测试规约。
**路线口径**:开发必须围绕最新 Issue CSV 执行;WDRG 后企微优先 HR/考勤改造必须先读 [企微优先开发路线图](./企微优先开发路线图.md),再按单功能 Issue CSV 实施。采购、合同、报销、财务、AP、代账和高敏附件继续 OA 主办,ERP 未来不接入 OA。 **路线口径**:开发必须围绕最新 Issue CSV 执行;WDRG 后企微优先 HR/考勤改造必须先读 [企微优先开发路线图](./企微优先开发路线图.md),再按单功能 Issue CSV 实施。采购、合同、报销、财务、AP、代账和高敏附件继续 OA 主办,ERP 未来不接入 OA。
@@ -133,6 +133,13 @@ Definition of Done:
- 人工只处理写入批准、Secret/Token/EncodingAESKey 配置、企微后台无法 API 化的配置、真机确认和风险拍板。 - 人工只处理写入批准、Secret/Token/EncodingAESKey 配置、企微后台无法 API 化的配置、真机确认和风险拍板。
- 缺配置必须输出 `NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不得伪造成 PASS。 - 缺配置必须输出 `NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不得伪造成 PASS。
WPROC2 后,三层门禁先由可执行 process gate 承接:
- 基线检查:`node scripts/qa/check-process-contract.mjs --baseline`。
- 单合同检查:`node scripts/qa/check-process-contract.mjs --issue <csv> --profile <profile> --json`。
- 首批 profile 为 `general`、`docs-only`、`wecom` 和 `wecom-approval-fixture`。
- WAPC2F 和后续高风险企微合同在实现前必须先通过 baseline gate 和对应 profile gate;`scripts/check-minimal.sh` 已接入 baseline gate。
高风险能力进入实现前必须先有 POC: 高风险能力进入实现前必须先有 POC:
- 真实回调先证明 URL 验证、验签、解密、幂等和重复投递。 - 真实回调先证明 URL 验证、验签、解密、幂等和重复投递。
+12 -10
查看文件
@@ -79,6 +79,7 @@
| `WAPC1` | `issues/2026-05-19_08-44-58-wecom-approval-config-prep-v1.csv` | `EVIDENCE` | 企微审批配置准备清单已完成:WMSG1 后不直接进入深度镜像;首批模板为请假、补卡、外出、加班;模板 ID、低风险 `sp_no`、真实回调配置项、验签/解密/幂等/重试和补偿拉取准入已固化;本轮不改业务代码、不部署、不接真实回调、不调用企微写接口 | | `WAPC1` | `issues/2026-05-19_08-44-58-wecom-approval-config-prep-v1.csv` | `EVIDENCE` | 企微审批配置准备清单已完成:WMSG1 后不直接进入深度镜像;首批模板为请假、补卡、外出、加班;模板 ID、低风险 `sp_no`、真实回调配置项、验签/解密/幂等/重试和补偿拉取准入已固化;本轮不改业务代码、不部署、不接真实回调、不调用企微写接口 |
| `WAPC2` | `issues/2026-05-19_09-34-16-wecom-approval-template-spno-poc-v1.csv` | `CURRENT` | 企微审批模板与低风险 `sp_no` 只读 POC 已部署并公网复跑:新增 `check:wecom-approval-poc` QA-only runner 和只读集成服务,范围请假/补卡,固定 `WECOM_AGENT_SECRET` 调用 `gettemplatedetail`/`getapprovaldetail`;远端报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,缺模板或 `sp_no` 不放行深度镜像 | | `WAPC2` | `issues/2026-05-19_09-34-16-wecom-approval-template-spno-poc-v1.csv` | `CURRENT` | 企微审批模板与低风险 `sp_no` 只读 POC 已部署并公网复跑:新增 `check:wecom-approval-poc` QA-only runner 和只读集成服务,范围请假/补卡,固定 `WECOM_AGENT_SECRET` 调用 `gettemplatedetail`/`getapprovaldetail`;远端报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,缺模板或 `sp_no` 不放行深度镜像 |
| `WPROC1` | `issues/2026-05-19_10-43-50-wecom-process-route-engineering-v1.csv` | `CURRENT` | 企微路线与开发流程工程化修正:docs-only/contract-only 固化三层门禁、Definition of Ready、Definition of Done、自动化优先、非自审和高风险 POC 前置;修正 WAPC2F 默认链为 `SMOKE002 -> SMOKE101`,WAPC2 后不得直接进入深度镜像 | | `WPROC1` | `issues/2026-05-19_10-43-50-wecom-process-route-engineering-v1.csv` | `CURRENT` | 企微路线与开发流程工程化修正:docs-only/contract-only 固化三层门禁、Definition of Ready、Definition of Done、自动化优先、非自审和高风险 POC 前置;修正 WAPC2F 默认链为 `SMOKE002 -> SMOKE101`,WAPC2 后不得直接进入深度镜像 |
| `WPROC2` | `issues/2026-05-19_11-15-10-process-gate-automation-v1.csv` | `CURRENT` | 开发流程自动化门禁:新增 `scripts/qa/check-process-contract.mjs` process gate、WAPC2F profile 和最小门禁接入;WAPC2F 实施前必须先通过 baseline gate,不部署、不写 OA/企微数据 |
旧 Issue CSV 保留为历史审计证据:不删除、不批量回写、不移动到 `docs/archive/` 或其他归档目录。新连续合同如替代旧合同,只在新合同 `Notes` 或文档索引中说明 supersedes。 旧 Issue CSV 保留为历史审计证据:不删除、不批量回写、不移动到 `docs/archive/` 或其他归档目录。新连续合同如替代旧合同,只在新合同 `Notes` 或文档索引中说明 supersedes。
@@ -86,15 +87,15 @@
| Doc_ID | Path | Category | Authority | Status | Owner | Related_Issues | Evidence | Supersedes | Last_Audited | Audit_Method | Risk | Notes | | Doc_ID | Path | Category | Authority | Status | Owner | Related_Issues | Evidence | Supersedes | Last_Audited | Audit_Method | Risk | Notes |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `IDX` | `docs/文档索引.md` | 入口索引 | 最高文档入口 | `CURRENT` | product/dev | `GOV8,QAOPS9,P2D,P2-ORG,P2-FIN-DECISION,P2-FIN-V1,P2-OCR-SAMPLE,P2Q,P2AUTO,P2AF,P2-FIN-LIVE-DECISION,P2-FIN-LIVE,PRELAUNCH,CASHIER-VOUCHER-V1,LAUNCH-DEPLOY-FINANCE,FIN-PROD-ENABLE,ACCOUNTING-HANDOFF-V1,SYSTEM-COMPLETE-GATE,LAUNCH-OPS-V1,REQ-COMPLETE-AUDIT,ATTV1,LAUNCH-AUTO-OPS-V1,AUTO-REMAINING-CLOSEOUT,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1` | `rg` | none | 2026-05-19 | `node scripts/qa/audit-docs.mjs --check-registry` | medium | 判断当前该读什么 | | `IDX` | `docs/文档索引.md` | 入口索引 | 最高文档入口 | `CURRENT` | product/dev | `GOV8,QAOPS9,P2D,P2-ORG,P2-FIN-DECISION,P2-FIN-V1,P2-OCR-SAMPLE,P2Q,P2AUTO,P2AF,P2-FIN-LIVE-DECISION,P2-FIN-LIVE,PRELAUNCH,CASHIER-VOUCHER-V1,LAUNCH-DEPLOY-FINANCE,FIN-PROD-ENABLE,ACCOUNTING-HANDOFF-V1,SYSTEM-COMPLETE-GATE,LAUNCH-OPS-V1,REQ-COMPLETE-AUDIT,ATTV1,LAUNCH-AUTO-OPS-V1,AUTO-REMAINING-CLOSEOUT,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1,WPROC2` | `rg` | none | 2026-05-19 | `node scripts/qa/audit-docs.mjs --check-registry` | medium | 判断当前该读什么 |
| `REG` | `docs/文档事实源状态矩阵.md` | 文档台账 | 文档分类和状态事实源 | `CURRENT` | product/dev | `GOV8,QAOPS9,P2D,P2-ORG,P2-FIN-DECISION,P2-FIN-V1,P2-OCR-SAMPLE,P2Q,P2AUTO,P2AF,P2-FIN-LIVE-DECISION,P2-FIN-LIVE,PRELAUNCH,CASHIER-VOUCHER-V1,LAUNCH-DEPLOY-FINANCE,FIN-PROD-ENABLE,ACCOUNTING-HANDOFF-V1,SYSTEM-COMPLETE-GATE,LAUNCH-OPS-V1,REQ-COMPLETE-AUDIT,ATTV1,LAUNCH-AUTO-OPS-V1,AUTO-REMAINING-CLOSEOUT,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1` | `audit-docs` | none | 2026-05-19 | `audit-docs --check-registry` | medium | 判断文档权威性 | | `REG` | `docs/文档事实源状态矩阵.md` | 文档台账 | 文档分类和状态事实源 | `CURRENT` | product/dev | `GOV8,QAOPS9,P2D,P2-ORG,P2-FIN-DECISION,P2-FIN-V1,P2-OCR-SAMPLE,P2Q,P2AUTO,P2AF,P2-FIN-LIVE-DECISION,P2-FIN-LIVE,PRELAUNCH,CASHIER-VOUCHER-V1,LAUNCH-DEPLOY-FINANCE,FIN-PROD-ENABLE,ACCOUNTING-HANDOFF-V1,SYSTEM-COMPLETE-GATE,LAUNCH-OPS-V1,REQ-COMPLETE-AUDIT,ATTV1,LAUNCH-AUTO-OPS-V1,AUTO-REMAINING-CLOSEOUT,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1,WPROC2` | `audit-docs` | none | 2026-05-19 | `audit-docs --check-registry` | medium | 判断文档权威性 |
| `PRD-MVP` | `docs/海音达OA-MVP需求规格说明书.md` | 需求事实源 | PRD 主事实源 | `CURRENT` | product | `REQ8,P2T,GOV8,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WAPC1` | Issue CSV | `docs/requirements-specification.md` | 2026-05-19 | `rg` | high | WAPC1 后定义 HR 主数据镜像读取口径、运行优先、WOUA 差异收口、消息实发和审批配置准备边界;ERP 未来不接入 OA | | `PRD-MVP` | `docs/海音达OA-MVP需求规格说明书.md` | 需求事实源 | PRD 主事实源 | `CURRENT` | product | `REQ8,P2T,GOV8,HR-WECOM-DIRECTORY-V1,WFOC,DBWFOC,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WAPC1` | Issue CSV | `docs/requirements-specification.md` | 2026-05-19 | `rg` | high | WAPC1 后定义 HR 主数据镜像读取口径、运行优先、WOUA 差异收口、消息实发和审批配置准备边界;ERP 未来不接入 OA |
| `PRODUCT-SCOPE` | `docs/产品口径.md` | 需求事实源 | 产品边界事实源 | `CURRENT` | product | `REQ8,P2T,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WAPC1` | `rg` | none | 2026-05-19 | `rg` | high | 记录已拍板产品边界、企微/OA 设计门禁、开发路线图、WCPC 准入结论、WHMS 部署验证、WAPI 运行优先、WRRA 差异收口和 WAPC1 审批配置准备口径 | | `PRODUCT-SCOPE` | `docs/产品口径.md` | 需求事实源 | 产品边界事实源 | `CURRENT` | product | `REQ8,P2T,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WAPC1` | `rg` | none | 2026-05-19 | `rg` | high | 记录已拍板产品边界、企微/OA 设计门禁、开发路线图、WCPC 准入结论、WHMS 部署验证、WAPI 运行优先、WRRA 差异收口和 WAPC1 审批配置准备口径 |
| `DESIGN-UI` | `docs/产品设计规则.md` | 设计事实源 | PC/移动/企业微信设计事实源 | `CURRENT` | design/frontend | `MIA7,MIF7,GOV8,DG8,DG9,WFDG` | Playwright/视觉审查/DG8/DG9/WFDG | none | 2026-05-18 | `rg` | high | 页面改动必须读取;DG8 后飞书为主 UI/布局参考;DG9 后按页面分层和样板选型;WFDG 后区分 OA 主办、企微镜像和 OA 应急接管 | | `DESIGN-UI` | `docs/产品设计规则.md` | 设计事实源 | PC/移动/企业微信设计事实源 | `CURRENT` | design/frontend | `MIA7,MIF7,GOV8,DG8,DG9,WFDG` | Playwright/视觉审查/DG8/DG9/WFDG | none | 2026-05-18 | `rg` | high | 页面改动必须读取;DG8 后飞书为主 UI/布局参考;DG9 后按页面分层和样板选型;WFDG 后区分 OA 主办、企微镜像和 OA 应急接管 |
| `ROADMAP-WECOM` | `docs/企微优先开发路线图.md` | 开发治理 | 企微优先开发路线图事实源 | `CURRENT` | product/dev | `WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1` | Issue CSV | none | 2026-05-19 | `rg` | high | WPROC1 后记录企微 HR/考勤路线阶段顺序、API/Secret 口径、运行优先、消息实发、审批配置、只读 POC、WAPC2F 自动样件、WCBK1 回调、WACP3 补偿拉取、WADM1 模型设计和禁止跳阶段 | | `ROADMAP-WECOM` | `docs/企微优先开发路线图.md` | 开发治理 | 企微优先开发路线图事实源 | `CURRENT` | product/dev | `WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WOUAFIX,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1,WPROC2` | Issue CSV | none | 2026-05-19 | `rg` | high | WPROC2 后记录企微 HR/考勤路线阶段顺序、API/Secret 口径、运行优先、消息实发、审批配置、只读 POC、process gate、WAPC2F 自动样件、WCBK1 回调、WACP3 补偿拉取、WADM1 模型设计和禁止跳阶段 |
| `WECOM-API-CATALOG` | `docs/企微API能力目录.md` | 集成事实源 | 企微 API 能力目录和 Secret 矩阵事实源 | `CURRENT` | product/backend/qa | `WAPI,WRRA,WAPC1,WAPC2,WPROC1` | 官方企业微信开发者中心链接/Issue CSV | none | 2026-05-19 | `rg` | high | 企微开发先读;只保存摘要、链接和项目决策,不保存 Secret、token、完整 userid、手机号、邮箱或原始 payload;WPROC1 后深度镜像等待自动样件、回调、补偿拉取和数据模型设计 | | `WECOM-API-CATALOG` | `docs/企微API能力目录.md` | 集成事实源 | 企微 API 能力目录和 Secret 矩阵事实源 | `CURRENT` | product/backend/qa | `WAPI,WRRA,WAPC1,WAPC2,WPROC1,WPROC2` | 官方企业微信开发者中心链接/Issue CSV | none | 2026-05-19 | `rg` | high | 企微开发先读;只保存摘要、链接和项目决策,不保存 Secret、token、完整 userid、手机号、邮箱或原始 payload;WPROC2 后高风险企微合同先跑 process gate |
| `DELIVERY` | `docs/开发交付与变更管理规约.md` | 开发治理 | 开发交付事实源 | `CURRENT` | dev/qa | `GOV8,WDRG,WRRA,WAPC1,WPROC1` | `rg` | none | 2026-05-19 | `rg` | high | Issue、review、commit、交付规则;WPROC1 后采用路线门禁、能力门禁、实现门禁、DoR/DoD 和自动化优先 | | `DELIVERY` | `docs/开发交付与变更管理规约.md` | 开发治理 | 开发交付事实源 | `CURRENT` | dev/qa | `GOV8,WDRG,WRRA,WAPC1,WPROC1,WPROC2` | `rg` | none | 2026-05-19 | `rg` | high | Issue、review、commit、交付规则;WPROC2 后采用路线门禁、能力门禁、实现门禁、DoR/DoD、自动化优先和可执行 process gate |
| `QA-GATE` | `docs/测试规约与回归门禁.md` | 测试验收 | 测试和回归门禁事实源 | `CURRENT` | qa | `QAF8,GOV8,WPROC1` | 回归脚本/Playwright | none | 2026-05-19 | `rg` | high | 测试计划、DONE 门禁、企微三层门禁、自动化优先和非自审测试要求 | | `QA-GATE` | `docs/测试规约与回归门禁.md` | 测试验收 | 测试和回归门禁事实源 | `CURRENT` | qa | `QAF8,GOV8,WPROC1,WPROC2` | 回归脚本/Playwright | none | 2026-05-19 | `rg` | high | 测试计划、DONE 门禁、企微三层门禁、自动化优先、非自审测试要求和 check-process-contract |
| `AGENT-PRACTICE` | `docs/Agent开发交付实践.md` | Agent 治理 | Agent 协作事实源 | `CURRENT` | dev | `GOV8,DG8` | Skill 校验 | none | 2026-05-13 | `rg` | medium | Agent 协作开发实践和设计主参考层级 | | `AGENT-PRACTICE` | `docs/Agent开发交付实践.md` | Agent 治理 | Agent 协作事实源 | `CURRENT` | dev | `GOV8,DG8` | Skill 校验 | none | 2026-05-13 | `rg` | medium | Agent 协作开发实践和设计主参考层级 |
| `AGENTS` | `AGENTS.md` | 执行硬约束 | 项目硬规则 | `CURRENT` | lead | `GOV8` | 人工核对 | none | 2026-05-13 | `rg` | high | 不可违反约束 | | `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,DG8,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1` | quick_validate | none | 2026-05-19 | `quick_validate.py` | medium | 每轮交付操作入口;企微/OA 后续先读 API 能力目录、Secret 矩阵、路线图和 WPROC1 状态,不得跳过 WAPC2F/WCBK1/WACP3/WADM1 直接做考勤审批镜像 | | `SKILL-HYB` | `.agents/skills/hyb-oa-delivery/SKILL.md` | Skill | 项目交付 Skill | `CURRENT` | dev | `GOV8,DG8,WFDG,WDRG,WCP1,WCPC,WHMS,WHMSLIVE,WOUA,WAPI,WRRA,WRV1,WRA1,WMSG1,WAPC1,WAPC2,WPROC1` | quick_validate | none | 2026-05-19 | `quick_validate.py` | medium | 每轮交付操作入口;企微/OA 后续先读 API 能力目录、Secret 矩阵、路线图和 WPROC1 状态,不得跳过 WAPC2F/WCBK1/WACP3/WADM1 直接做考勤审批镜像 |
@@ -120,14 +121,14 @@
| `docs/文档事实源状态矩阵.md` | 当前事实源 | 文档分类和恢复规则 | | `docs/文档事实源状态矩阵.md` | 当前事实源 | 文档分类和恢复规则 |
| `docs/海音达OA-MVP需求规格说明书.md` | 当前事实源 | PRD 主事实源 | | `docs/海音达OA-MVP需求规格说明书.md` | 当前事实源 | PRD 主事实源 |
| `docs/产品设计规则.md` | 当前事实源 | PC、移动、企业微信设计规则;DG8 主 UI/布局参考层级 | | `docs/产品设计规则.md` | 当前事实源 | PC、移动、企业微信设计规则;DG8 主 UI/布局参考层级 |
| `docs/企微优先开发路线图.md` | 当前事实源 | WDRG/WCP1/WCPC/WHMS/WHMSLIVE/WOUA/WAPI/WRRA/WAPC2/WPROC1 后企微优先 HR/考勤改造阶段顺序、API/Secret 口径、运行优先、审批只读 POC、自动样件、回调、补偿拉取、模型设计和禁止跳阶段 | | `docs/企微优先开发路线图.md` | 当前事实源 | WDRG/WCP1/WCPC/WHMS/WHMSLIVE/WOUA/WAPI/WRRA/WAPC2/WPROC1/WPROC2 后企微优先 HR/考勤改造阶段顺序、API/Secret 口径、运行优先、审批只读 POC、process gate、自动样件、回调、补偿拉取、模型设计和禁止跳阶段 |
| `docs/企微API能力目录.md` | 当前事实源 | WAPI/WRRA/WAPC2/WPROC1 后企微官方 API、Secret 矩阵、权限/可信 IP/回调模板、读写边界、运行优先、审批只读 POC 和后续 POC 决策 | | `docs/企微API能力目录.md` | 当前事实源 | WAPI/WRRA/WAPC2/WPROC1/WPROC2 后企微官方 API、Secret 矩阵、权限/可信 IP/回调模板、读写边界、运行优先、审批只读 POC 和后续 POC 决策 |
| `docs/产品口径.md` | 当前事实源 | 产品边界和业务规则 | | `docs/产品口径.md` | 当前事实源 | 产品边界和业务规则 |
| `docs/需求-统一审批中心规约.md` | 当前事实源 | 审批、催办、超时、效率摘要 | | `docs/需求-统一审批中心规约.md` | 当前事实源 | 审批、催办、超时、效率摘要 |
| `docs/报销发票附件规则.md` | 当前事实源 | 报销、发票、附件细则 | | `docs/报销发票附件规则.md` | 当前事实源 | 报销、发票、附件细则 |
| `docs/需求-报销发票OCR规约.md` | 当前事实源 | OCR 和报销模块规约 | | `docs/需求-报销发票OCR规约.md` | 当前事实源 | OCR 和报销模块规约 |
| `docs/需求-企业微信基础设施规约.md` | 当前事实源 | 企业微信入口、身份、消息、deeplink | | `docs/需求-企业微信基础设施规约.md` | 当前事实源 | 企业微信入口、身份、消息、deeplink |
| `docs/需求-请假考勤修正规约.md` | 当前事实源 | 请假、补卡、考勤修正、WAPC2 只读 POC 和 WPROC1 后续门禁 | | `docs/需求-请假考勤修正规约.md` | 当前事实源 | 请假、补卡、考勤修正、WAPC2 只读 POC 和 WPROC1/WPROC2 后续门禁 |
| `docs/需求-采购费用审批规约.md` | 当前事实源 | 采购和费用审批 | | `docs/需求-采购费用审批规约.md` | 当前事实源 | 采购和费用审批 |
| `docs/需求-合同附件归档规约.md` | 当前事实源 | 合同台账和附件归档 | | `docs/需求-合同附件归档规约.md` | 当前事实源 | 合同台账和附件归档 |
| `docs/需求-项目轻管理规约.md` | 当前事实源 | 项目轻管理 | | `docs/需求-项目轻管理规约.md` | 当前事实源 | 项目轻管理 |
@@ -196,8 +197,9 @@
- `ME6-3` 代表性企业微信真机门禁已关闭。 - `ME6-3` 代表性企业微信真机门禁已关闭。
- MIF7-1..7 与 MIF7T 已完成本地整改、公网部署、公网匿名复检和带凭据 live smoke/OCR 复检。 - MIF7-1..7 与 MIF7T 已完成本地整改、公网部署、公网匿名复检和带凭据 live smoke/OCR 复检。
- R7E 真实扩大试运行阶段验收、P2 排序、R7E 收口、QAOPS8 上线硬化阶段收口、QAOPS9 上线硬化连续合同、PRELAUNCH 正式启用前公网预回归、CASHIER-VOUCHER-V1 财务闭环与银行回单附件、LAUNCH-DEPLOY-FINANCE 部署复检、FIN-PROD-ENABLE 正式常开、ACCOUNTING-HANDOFF-V1 代账交接 SOP、SYSTEM-COMPLETE-GATE 系统完成门禁、LAUNCH-OPS-V1 首周运营保障、REQ-COMPLETE-AUDIT 需求完成度复核、ATTV1 考勤统一入口、AUTO-REMAINING-CLOSEOUT 剩余自动化收口、HRWD-CONTACT-LIVE-TEST 公网企微通讯录真实写入闭环、WFOC 需求重构、DBWFOC 数据边界修正、WFDG 设计门禁、WDRG 路线图门禁、WCPC 配置复跑、WHMSLIVE、WAPI、WRRA、WOUA-FIX、WRA1、WMSG1、WAPC1、WAPC2 和 WPROC1 均已完成,当前 P0/P1 阻断为 0;P2D 已完成决策分流,P2-ORG 只读巡检已完成且无需写修复合同。LAUNCH-AUTO-OPS-V1 发现的公网 `payment_batch_v1=force_off` 漂移已由 AUTOREM 恢复为 `force_on`,正式自动巡检结论为 `GO_TO_OPERATE`;`erp_sync=force_off`,ERP 未来不接入 OA,正式支付接口、图片 OCR 和银行流水导入继续不进入当前路线。WCP1 已完成企业微信能力 QA-only 只读 POC,历史结论为 `PAUSE_FOR_CONFIG`;WCPC 使用既有在职测试号 `SMOKE002/测试员工`(脱敏 `oa_smoke***`)完成远端只读复跑,报告 `/tmp/wecom-capability-poc-wcpc-smoke002/summary.json`,结论 `GO_TO_HR_MASTER_SYNC`,`nextStageAllowed=true`,`blockingCapabilities=[]`。WHMS 已实现并部署验证 `wecom_hr_master_sync_v1`、同步批次/逐员工记录、dry-run/apply、管理员 API、People 管理入口和 QA-only runner;默认和最终均为 `force_off`,公网 `SMOKE002` 因缺手机号、邮箱和部门按 `missing_required_field` 跳过,未执行生产真实员工批量 apply。WAPI 已将企微官方 API 能力目录、Secret 矩阵和运行优先路线落为当前事实源:通讯录读取使用 `WECOM_CONTACT_SECRET` 和 `user/list_id`,成员详情只作可选富化,人事助手/花名册、打卡、消息、OAuth 和审批读取默认使用 `WECOM_AGENT_SECRET`,`WECOM_CHECKIN_SECRET` 只作专用打卡 override,`WECOM_HR_ASSISTANT_SECRET` 不参与默认读取;后续企微能力不清楚时先查官方 API 和 [企微 API 能力目录](./企微API能力目录.md),不得靠运行时多个 Secret 试错。WOUA-FIX 已按用户确认执行受控写入并复检:7 个 OA active 缺企微测试账号软归档,`T0000` seed 复活问题修正,`SMOKE201` 测试主管和待办副作用已转交,最终 WOUA 报告 `/app/artifacts/qa-flow/wecom-oa-user-consistency-20260518T161716Z/summary.json` 为 `PASS_WITH_FINDINGS`,但 OA active 5、企微 active 5、匹配 5、OA active 缺企微 0;剩余 5 个企微缺字段先接受不补,`HRWDTEST-20260517214548` 归档绑定保留审计。WRV1 原始报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T173402Z/summary.json` 曾因同步开关误阻断;WRA1 已修正并公网复跑,报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T180506Z/summary.json` 为 `PASS_WITH_CONFIG_GAPS`,入口/OAuth、Secret 矩阵、OA active 绑定、通讯录、人事助手、消息 dry-run 和打卡只读链路均通过,打卡记录 `readable_sync_disabled`。WMSG1 已证明企业微信应用消息和 Deeplink 可用;WAPC1 已固定首批审批模板(请假、补卡、外出、加班)、低风险 `sp_no`、真实回调配置项、验签/解密/幂等/重试和补偿拉取准入清单;WAPC2 已新增请假/补卡模板详情和审批详情只读 POC runner;WPROC1 已固定后续自动化优先、非自审和三层门禁。HR/考勤员工日常审批优先复用企业微信,OA 目标是按域镜像、人工接管、恢复回写和 RuleOps;采购、费用、合同、项目、报销、付款、AP、代账交接、审计和高敏附件继续 OA 主办。考勤/审批镜像、审批回调、OA 应急接管、恢复回写和 RuleOps 尚未实现;审批模板 ID、审批单号 `sp_no`、真实回调配置、补偿拉取、镜像数据模型和 HR 写接口仍需后续独立合同处理;不得跳过 WAPC2F、WCBK1、WACP3、WADM1 直接进入 `wecom_attendance_approval_mirror_v1`、`oa_hr_emergency_mode_v1`、`wecom_recovery_writeback_v1` 或 `wecom_ruleops_v1`。HRWD 已完成 OA 驱动企业微信通讯录同步,并通过 `HRWDTEST-20260517214548` 真实公网 create/update/disable 验证;测试成员按审计要求保留离职/禁用状态。 - R7E 真实扩大试运行阶段验收、P2 排序、R7E 收口、QAOPS8 上线硬化阶段收口、QAOPS9 上线硬化连续合同、PRELAUNCH 正式启用前公网预回归、CASHIER-VOUCHER-V1 财务闭环与银行回单附件、LAUNCH-DEPLOY-FINANCE 部署复检、FIN-PROD-ENABLE 正式常开、ACCOUNTING-HANDOFF-V1 代账交接 SOP、SYSTEM-COMPLETE-GATE 系统完成门禁、LAUNCH-OPS-V1 首周运营保障、REQ-COMPLETE-AUDIT 需求完成度复核、ATTV1 考勤统一入口、AUTO-REMAINING-CLOSEOUT 剩余自动化收口、HRWD-CONTACT-LIVE-TEST 公网企微通讯录真实写入闭环、WFOC 需求重构、DBWFOC 数据边界修正、WFDG 设计门禁、WDRG 路线图门禁、WCPC 配置复跑、WHMSLIVE、WAPI、WRRA、WOUA-FIX、WRA1、WMSG1、WAPC1、WAPC2、WPROC1 和 WPROC2 均已完成,当前 P0/P1 阻断为 0;P2D 已完成决策分流,P2-ORG 只读巡检已完成且无需写修复合同。LAUNCH-AUTO-OPS-V1 发现的公网 `payment_batch_v1=force_off` 漂移已由 AUTOREM 恢复为 `force_on`,正式自动巡检结论为 `GO_TO_OPERATE`;`erp_sync=force_off`,ERP 未来不接入 OA,正式支付接口、图片 OCR 和银行流水导入继续不进入当前路线。WCP1 已完成企业微信能力 QA-only 只读 POC,历史结论为 `PAUSE_FOR_CONFIG`;WCPC 使用既有在职测试号 `SMOKE002/测试员工`(脱敏 `oa_smoke***`)完成远端只读复跑,报告 `/tmp/wecom-capability-poc-wcpc-smoke002/summary.json`,结论 `GO_TO_HR_MASTER_SYNC`,`nextStageAllowed=true`,`blockingCapabilities=[]`。WHMS 已实现并部署验证 `wecom_hr_master_sync_v1`、同步批次/逐员工记录、dry-run/apply、管理员 API、People 管理入口和 QA-only runner;默认和最终均为 `force_off`,公网 `SMOKE002` 因缺手机号、邮箱和部门按 `missing_required_field` 跳过,未执行生产真实员工批量 apply。WAPI 已将企微官方 API 能力目录、Secret 矩阵和运行优先路线落为当前事实源:通讯录读取使用 `WECOM_CONTACT_SECRET` 和 `user/list_id`,成员详情只作可选富化,人事助手/花名册、打卡、消息、OAuth 和审批读取默认使用 `WECOM_AGENT_SECRET`,`WECOM_CHECKIN_SECRET` 只作专用打卡 override,`WECOM_HR_ASSISTANT_SECRET` 不参与默认读取;后续企微能力不清楚时先查官方 API 和 [企微 API 能力目录](./企微API能力目录.md),不得靠运行时多个 Secret 试错。WOUA-FIX 已按用户确认执行受控写入并复检:7 个 OA active 缺企微测试账号软归档,`T0000` seed 复活问题修正,`SMOKE201` 测试主管和待办副作用已转交,最终 WOUA 报告 `/app/artifacts/qa-flow/wecom-oa-user-consistency-20260518T161716Z/summary.json` 为 `PASS_WITH_FINDINGS`,但 OA active 5、企微 active 5、匹配 5、OA active 缺企微 0;剩余 5 个企微缺字段先接受不补,`HRWDTEST-20260517214548` 归档绑定保留审计。WRV1 原始报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T173402Z/summary.json` 曾因同步开关误阻断;WRA1 已修正并公网复跑,报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T180506Z/summary.json` 为 `PASS_WITH_CONFIG_GAPS`,入口/OAuth、Secret 矩阵、OA active 绑定、通讯录、人事助手、消息 dry-run 和打卡只读链路均通过,打卡记录 `readable_sync_disabled`。WMSG1 已证明企业微信应用消息和 Deeplink 可用;WAPC1 已固定首批审批模板(请假、补卡、外出、加班)、低风险 `sp_no`、真实回调配置项、验签/解密/幂等/重试和补偿拉取准入清单;WAPC2 已新增请假/补卡模板详情和审批详情只读 POC runner;WPROC1 已固定后续自动化优先、非自审和三层门禁,WPROC2 已将其升级为 `check-process-contract` process gate。HR/考勤员工日常审批优先复用企业微信,OA 目标是按域镜像、人工接管、恢复回写和 RuleOps;采购、费用、合同、项目、报销、付款、AP、代账交接、审计和高敏附件继续 OA 主办。考勤/审批镜像、审批回调、OA 应急接管、恢复回写和 RuleOps 尚未实现;审批模板 ID、审批单号 `sp_no`、真实回调配置、补偿拉取、镜像数据模型和 HR 写接口仍需后续独立合同处理;不得跳过 WAPC2F、WCBK1、WACP3、WADM1 直接进入 `wecom_attendance_approval_mirror_v1`、`oa_hr_emergency_mode_v1`、`wecom_recovery_writeback_v1` 或 `wecom_ruleops_v1`。HRWD 已完成 OA 驱动企业微信通讯录同步,并通过 `HRWDTEST-20260517214548` 真实公网 create/update/disable 验证;测试成员按审计要求保留离职/禁用状态。
- WMSG1 已完成企微应用消息实发与 Deeplink 真机验证:远端报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T234431Z/summary.json` 显示 `checks.message.status=OK`、`errcode=0`、`recipientCount=1`,用户确认收到“OA 运行就绪检查”并可点击进入 OA 通知页面;本证据只证明消息和 Deeplink 可用,不放行审批模板、测试 `sp_no`、真实回调或深度镜像。 - WMSG1 已完成企微应用消息实发与 Deeplink 真机验证:远端报告 `/app/artifacts/qa-flow/wecom-runtime-ready-20260518T234431Z/summary.json` 显示 `checks.message.status=OK`、`errcode=0`、`recipientCount=1`,用户确认收到“OA 运行就绪检查”并可点击进入 OA 通知页面;本证据只证明消息和 Deeplink 可用,不放行审批模板、测试 `sp_no`、真实回调或深度镜像。
- WAPC1 已完成企微审批配置准备清单:首批只准备请假、补卡、外出、加班模板;每个模板需准备模板 ID、适用范围、字段项、审批人规则、可见范围和自建应用权限;测试 `sp_no` 必须低风险且不得含采购、合同、报销、发票、银行回单或高敏附件;真实回调 Token/EncodingAESKey 不写入仓库或文档。本证据只代表配置准备口径已固化,不代表真实回调、审批镜像、应急接管、恢复回写或 RuleOps 已实现。 - WAPC1 已完成企微审批配置准备清单:首批只准备请假、补卡、外出、加班模板;每个模板需准备模板 ID、适用范围、字段项、审批人规则、可见范围和自建应用权限;测试 `sp_no` 必须低风险且不得含采购、合同、报销、发票、银行回单或高敏附件;真实回调 Token/EncodingAESKey 不写入仓库或文档。本证据只代表配置准备口径已固化,不代表真实回调、审批镜像、应急接管、恢复回写或 RuleOps 已实现。
- WAPC2 已完成企微审批模板与低风险 `sp_no` 只读 POC 本地实现、部署和公网只读复跑:范围只包括请假和补卡,固定 `WECOM_AGENT_SECRET`,远端报告为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`;本证据只代表模板详情/审批详情只读 runner 已具备且远端 Secret 可用,不代表模板 ID、测试 `sp_no`、真实回调或深度镜像已配置完成。 - WAPC2 已完成企微审批模板与低风险 `sp_no` 只读 POC 本地实现、部署和公网只读复跑:范围只包括请假和补卡,固定 `WECOM_AGENT_SECRET`,远端报告为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`;本证据只代表模板详情/审批详情只读 runner 已具备且远端 Secret 可用,不代表模板 ID、测试 `sp_no`、真实回调或深度镜像已配置完成。
- WPROC1 已修正企微路线与开发流程工程化门禁:后续默认自动化优先,人工只处理批准、密钥/回调配置、企微后台不可 API 化配置、真机确认和风险拍板;WAPC2F 默认使用 `SMOKE002 -> SMOKE101` 非自审链,`SMOKE101` 不可用时停止问答确认;`wecom_attendance_approval_mirror_v1` 前必须完成 WAPC2F、WAPC2 自动复跑、WCBK1、WACP3 和 WADM1。 - WPROC1 已修正企微路线与开发流程工程化门禁:后续默认自动化优先,人工只处理批准、密钥/回调配置、企微后台不可 API 化配置、真机确认和风险拍板;WAPC2F 默认使用 `SMOKE002 -> SMOKE101` 非自审链,`SMOKE101` 不可用时停止问答确认;`wecom_attendance_approval_mirror_v1` 前必须完成 WAPC2F、WAPC2 自动复跑、WCBK1、WACP3 和 WADM1。
- WPROC2 已新增开发流程自动化门禁:`node scripts/qa/check-process-contract.mjs --baseline` 检查核心事实源和 WAPC2F 合同,`wecom-approval-fixture` profile 检查非自审、Secret 固定、live 双开关、缺配置分类和脱敏边界;该门禁已接入 `scripts/check-minimal.sh`。
+8 -6
查看文件
@@ -20,7 +20,7 @@
## 最近事实源链 ## 最近事实源链
R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> MIF7/MIF7T(公网部署与带凭据公网复检已收口) -> DG8 -> DG9 -> R7E -> FBA -> QAOPS9/P2D -> P2-ORG -> P2-FIN-DECISION -> P2-FIN-V1 -> P2-OCR-SAMPLE -> P2Q -> P2AUTO -> P2AF -> P2-FIN-LIVE-DECISION -> P2-FIN-LIVE -> PRELAUNCH -> CASHIER-VOUCHER-V1 -> LAUNCH-DEPLOY-FINANCE -> FIN-PROD-ENABLE -> ACCOUNTING-HANDOFF-V1 -> SYSTEM-COMPLETE-GATE -> LAUNCH-OPS-V1 -> REQ-COMPLETE-AUDIT -> ATTV1 -> LAUNCH-AUTO-OPS-V1 -> AUTO-REMAINING-CLOSEOUT -> HR-WECOM-DIRECTORY-V1 -> HRWD-CONTACT-LIVE-TEST -> WCFB -> WFOC -> DBWFOC -> WFDG -> WDRG -> WCP1 -> WCPC -> WHMS -> WHMSLIVE -> WOUA -> WAPI -> WRRA -> WOUA-FIX -> WRV1 -> WRA1 -> WMSG1 -> WAPC1 -> WAPC2 -> WPROC1。 R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> MIF7/MIF7T(公网部署与带凭据公网复检已收口) -> DG8 -> DG9 -> R7E -> FBA -> QAOPS9/P2D -> P2-ORG -> P2-FIN-DECISION -> P2-FIN-V1 -> P2-OCR-SAMPLE -> P2Q -> P2AUTO -> P2AF -> P2-FIN-LIVE-DECISION -> P2-FIN-LIVE -> PRELAUNCH -> CASHIER-VOUCHER-V1 -> LAUNCH-DEPLOY-FINANCE -> FIN-PROD-ENABLE -> ACCOUNTING-HANDOFF-V1 -> SYSTEM-COMPLETE-GATE -> LAUNCH-OPS-V1 -> REQ-COMPLETE-AUDIT -> ATTV1 -> LAUNCH-AUTO-OPS-V1 -> AUTO-REMAINING-CLOSEOUT -> HR-WECOM-DIRECTORY-V1 -> HRWD-CONTACT-LIVE-TEST -> WCFB -> WFOC -> DBWFOC -> WFDG -> WDRG -> WCP1 -> WCPC -> WHMS -> WHMSLIVE -> WOUA -> WAPI -> WRRA -> WOUA-FIX -> WRV1 -> WRA1 -> WMSG1 -> WAPC1 -> WAPC2 -> WPROC1 -> WPROC2。
- R6、PC6、PA6、FL6、AP6、RI6、LP6 已完成并部署。 - R6、PC6、PA6、FL6、AP6、RI6、LP6 已完成并部署。
- ME6 自动化、公网视觉矩阵和 `ME6-3` 代表性企业微信真机门禁已完成。 - ME6 自动化、公网视觉矩阵和 `ME6-3` 代表性企业微信真机门禁已完成。
@@ -72,6 +72,7 @@ R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> M
- WAPC1 是 WMSG1 后的企微审批配置准备清单合同:只固化请假、补卡、外出、加班模板准备项、低风险 `sp_no`、真实回调配置项和 POC 准入,不开发镜像。 - WAPC1 是 WMSG1 后的企微审批配置准备清单合同:只固化请假、补卡、外出、加班模板准备项、低风险 `sp_no`、真实回调配置项和 POC 准入,不开发镜像。
- WAPC2 是 WAPC1 后的请假/补卡审批只读 POC 合同:新增 `server/src/scripts/check-wecom-approval-poc.js` 和 `npm run check:wecom-approval-poc`,固定 `WECOM_AGENT_SECRET` 读取 `gettemplatedetail`/`getapprovaldetail`;缺模板 ID 或低风险 `sp_no` 时报告 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,不放行深度镜像。 - WAPC2 是 WAPC1 后的请假/补卡审批只读 POC 合同:新增 `server/src/scripts/check-wecom-approval-poc.js` 和 `npm run check:wecom-approval-poc`,固定 `WECOM_AGENT_SECRET` 读取 `gettemplatedetail`/`getapprovaldetail`;缺模板 ID 或低风险 `sp_no` 时报告 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG`,不放行深度镜像。
- WPROC1 是 WAPC2 后的企微路线与开发流程工程化修正合同:只更新合同和事实源,不写业务代码、不部署、不写 OA/企微数据;固定后续顺序为 `WAPC2F -> WAPC2 自动复跑 -> WCBK1 -> WACP3 -> WADM1 -> wecom_attendance_approval_mirror_v1`,并修正 WAPC2F 默认非自审链为 `SMOKE002 -> SMOKE101`。 - WPROC1 是 WAPC2 后的企微路线与开发流程工程化修正合同:只更新合同和事实源,不写业务代码、不部署、不写 OA/企微数据;固定后续顺序为 `WAPC2F -> WAPC2 自动复跑 -> WCBK1 -> WACP3 -> WADM1 -> wecom_attendance_approval_mirror_v1`,并修正 WAPC2F 默认非自审链为 `SMOKE002 -> SMOKE101`。
- WPROC2 是 WPROC1 后的开发流程自动化门禁合同:新增 `scripts/qa/check-process-contract.mjs` process gate,并接入 `scripts/check-minimal.sh`;WAPC2F 实施前必须先通过 baseline gate 和 `wecom-approval-fixture` profile。本轮不部署、不写 OA/企微数据、不实现 WAPC2F 业务 runner。
## 当前活跃治理流 ## 当前活跃治理流
@@ -131,6 +132,7 @@ R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> M
| `WAPC1` | `issues/2026-05-19_08-44-58-wecom-approval-config-prep-v1.csv` | 已完成:企微审批配置准备清单 | 固化 WMSG1 后下一步为审批配置准备,不直接进入深度镜像;首批模板为请假、补卡、外出、加班;准备模板 ID、低风险 `sp_no`、真实回调配置项和后续 POC 准入 | 不改业务代码/API/schema/UI;不部署;不接真实回调;不调用企微写接口;不配置模板或 `sp_no` | | `WAPC1` | `issues/2026-05-19_08-44-58-wecom-approval-config-prep-v1.csv` | 已完成:企微审批配置准备清单 | 固化 WMSG1 后下一步为审批配置准备,不直接进入深度镜像;首批模板为请假、补卡、外出、加班;准备模板 ID、低风险 `sp_no`、真实回调配置项和后续 POC 准入 | 不改业务代码/API/schema/UI;不部署;不接真实回调;不调用企微写接口;不配置模板或 `sp_no` |
| `WAPC2` | `issues/2026-05-19_09-34-16-wecom-approval-template-spno-poc-v1.csv` | 已部署并公网只读复跑:企微审批模板与低风险 `sp_no` 只读 POC | 新增 QA-only runner、只读集成服务和 focused 单测;范围请假+补卡;固定 `WECOM_AGENT_SECRET` 调用 `gettemplatedetail` / `getapprovaldetail`;远端报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG` | 不新增公开 API/schema/UI;不接真实回调;不调用企微写接口;不写 OA/企微数据;不进入深度镜像 | | `WAPC2` | `issues/2026-05-19_09-34-16-wecom-approval-template-spno-poc-v1.csv` | 已部署并公网只读复跑:企微审批模板与低风险 `sp_no` 只读 POC | 新增 QA-only runner、只读集成服务和 focused 单测;范围请假+补卡;固定 `WECOM_AGENT_SECRET` 调用 `gettemplatedetail` / `getapprovaldetail`;远端报告 `/app/artifacts/qa-flow/wecom-approval-poc-20260519T020429Z/summary.json` 为 `PARTIAL_APPROVAL_POC_NEEDS_CONFIG` | 不新增公开 API/schema/UI;不接真实回调;不调用企微写接口;不写 OA/企微数据;不进入深度镜像 |
| `WPROC1` | `issues/2026-05-19_10-43-50-wecom-process-route-engineering-v1.csv` | 当前路线与流程治理:企微工程化门禁修正 | 固化三层门禁、Definition of Ready、Definition of Done、自动化优先、非自审和高风险能力先 POC;修正 WAPC2F 默认链为 `SMOKE002 -> SMOKE101` | docs-only/contract-only;不改业务代码、不部署、不写 OA/企微数据;WAPC2 后仍需 WAPC2F、WCBK1、WACP3、WADM1 后才能进入深度镜像 | | `WPROC1` | `issues/2026-05-19_10-43-50-wecom-process-route-engineering-v1.csv` | 当前路线与流程治理:企微工程化门禁修正 | 固化三层门禁、Definition of Ready、Definition of Done、自动化优先、非自审和高风险能力先 POC;修正 WAPC2F 默认链为 `SMOKE002 -> SMOKE101` | docs-only/contract-only;不改业务代码、不部署、不写 OA/企微数据;WAPC2 后仍需 WAPC2F、WCBK1、WACP3、WADM1 后才能进入深度镜像 |
| `WPROC2` | `issues/2026-05-19_11-15-10-process-gate-automation-v1.csv` | 当前流程自动化门禁:process gate 框架 | 新增 `check-process-contract` QA-only CLI、WAPC2F profile、最小门禁接入和事实源回写;WAPC2F 实施前先跑 baseline gate | 不部署、不改业务 API/schema/UI、不写 OA/企微数据、不实现 WAPC2F runner |
旧 Issue CSV 不删除、不批量回写、不移动到归档目录。若新治理流替代旧合同,只在新 CSV 的 `Notes` 或本索引说明 supersedes,旧文件保留历史审计语义。 旧 Issue CSV 不删除、不批量回写、不移动到归档目录。若新治理流替代旧合同,只在新 CSV 的 `Notes` 或本索引说明 supersedes,旧文件保留历史审计语义。
@@ -150,17 +152,17 @@ R6 -> PC6 -> PA6 -> FL6 -> AP6 -> RI6 -> LP6 -> ME6/QG6 -> DG7/MRF7 -> MIA7 -> M
| 文档 | 用途 | | 文档 | 用途 |
| --- | --- | | --- | --- |
| [海音达OA-MVP需求规格说明书](./海音达OA-MVP需求规格说明书.md) | PRD 主事实源;WAPC1/WAPC2/WPROC1 后包含企微审批配置、只读 POC 和后续工程化前置 | | [海音达OA-MVP需求规格说明书](./海音达OA-MVP需求规格说明书.md) | PRD 主事实源;WAPC1/WAPC2/WPROC1/WPROC2 后包含企微审批配置、只读 POC、工程化前置和 process gate 口径 |
| [文档事实源状态矩阵](./文档事实源状态矩阵.md) | 文档分类、删除恢复和冲突规则 | | [文档事实源状态矩阵](./文档事实源状态矩阵.md) | 文档分类、删除恢复和冲突规则 |
| [产品设计规则](./产品设计规则.md) | PC、移动、企业微信 WebView 设计事实源;DG8 后飞书工作台/飞书审批为唯一主 UI/布局参考;DG9 后按页面分层和样板选型 | | [产品设计规则](./产品设计规则.md) | PC、移动、企业微信 WebView 设计事实源;DG8 后飞书工作台/飞书审批为唯一主 UI/布局参考;DG9 后按页面分层和样板选型 |
| [企微优先开发路线图](./企微优先开发路线图.md) | WDRG/WCP1/WCPC/WHMS/WHMSLIVE/WOUA/WAPI/WRRA/WOUA-FIX/WRV1/WRA1/WMSG1/WAPC1/WAPC2/WPROC1 后企微优先 HR/考勤改造的阶段顺序、准入/退出门禁、并行规则、禁止跳阶段、API/Secret 口径、运行优先、消息实发、审批配置、只读 POC、自动样件、回调、补偿拉取和模型设计事实源 | | [企微优先开发路线图](./企微优先开发路线图.md) | WDRG/WCP1/WCPC/WHMS/WHMSLIVE/WOUA/WAPI/WRRA/WOUA-FIX/WRV1/WRA1/WMSG1/WAPC1/WAPC2/WPROC1/WPROC2 后企微优先 HR/考勤改造的阶段顺序、准入/退出门禁、并行规则、禁止跳阶段、API/Secret 口径、运行优先、消息实发、审批配置、只读 POC、process gate、自动样件、回调、补偿拉取和模型设计事实源 |
| [企微 API 能力目录](./企微API能力目录.md) | WAPI/WAPC1/WAPC2/WPROC1 后企微官方 API、Secret 矩阵、权限/可信 IP/回调模板、读写边界、运行优先、审批配置、只读 POC、WAPC2F/WCBK1/WACP3/WADM1 决策事实源 | | [企微 API 能力目录](./企微API能力目录.md) | WAPI/WAPC1/WAPC2/WPROC1/WPROC2 后企微官方 API、Secret 矩阵、权限/可信 IP/回调模板、读写边界、运行优先、审批配置、只读 POC、WAPC2F/WCBK1/WACP3/WADM1 决策事实源 |
| [产品口径](./产品口径.md) | 已拍板产品边界和业务规则;WAPC1/WAPC2/WPROC1 后包含审批配置、只读 POC 和工程化前置阶段顺序 | | [产品口径](./产品口径.md) | 已拍板产品边界和业务规则;WAPC1/WAPC2/WPROC1/WPROC2 后包含审批配置、只读 POC、工程化前置阶段顺序和 process gate |
| [需求 - 统一审批中心规约](./需求-统一审批中心规约.md) | OA 主办审批、企微主办 HR/考勤员工日常审批镜像、催办、超时提醒、审批效率 | | [需求 - 统一审批中心规约](./需求-统一审批中心规约.md) | OA 主办审批、企微主办 HR/考勤员工日常审批镜像、催办、超时提醒、审批效率 |
| [报销发票附件规则](./报销发票附件规则.md) | 报销、发票、OCR、附件细则 | | [报销发票附件规则](./报销发票附件规则.md) | 报销、发票、OCR、附件细则 |
| [需求 - 报销发票 OCR 规约](./需求-报销发票OCR规约.md) | 报销发票 OCR 模块规约 | | [需求 - 报销发票 OCR 规约](./需求-报销发票OCR规约.md) | 报销发票 OCR 模块规约 |
| [需求 - 企业微信基础设施规约](./需求-企业微信基础设施规约.md) | 企业微信入口、身份、消息、deeplink、HR/考勤员工日常审批、打卡、人事助手、按域镜像、OA 接管和恢复回写 | | [需求 - 企业微信基础设施规约](./需求-企业微信基础设施规约.md) | 企业微信入口、身份、消息、deeplink、HR/考勤员工日常审批、打卡、人事助手、按域镜像、OA 接管和恢复回写 |
| [需求 - 请假考勤修正规约](./需求-请假考勤修正规约.md) | 企微请假/补卡/外出/加班、WAPC1 审批配置准备、WAPC2 请假/补卡只读 POC、WPROC1 后续门禁、考勤镜像、OA 应急接管和恢复回写 | | [需求 - 请假考勤修正规约](./需求-请假考勤修正规约.md) | 企微请假/补卡/外出/加班、WAPC1 审批配置准备、WAPC2 请假/补卡只读 POC、WPROC1/WPROC2 后续门禁、考勤镜像、OA 应急接管和恢复回写 |
| [需求 - 采购费用审批规约](./需求-采购费用审批规约.md) | 采购、费用、附件、审批规则 | | [需求 - 采购费用审批规约](./需求-采购费用审批规约.md) | 采购、费用、附件、审批规则 |
| [需求 - 合同附件归档规约](./需求-合同附件归档规约.md) | 合同台账和附件归档边界 | | [需求 - 合同附件归档规约](./需求-合同附件归档规约.md) | 合同台账和附件归档边界 |
| [需求 - 项目轻管理规约](./需求-项目轻管理规约.md) | 项目轻管理边界 | | [需求 - 项目轻管理规约](./需求-项目轻管理规约.md) | 项目轻管理边界 |
+7 -1
查看文件
@@ -2,7 +2,7 @@
**文档状态**:当前测试事实源。 **文档状态**:当前测试事实源。
**适用范围**:hyb-oa MVP 首轮开发 A3-A8,以及后续所有非微小改动。 **适用范围**:hyb-oa MVP 首轮开发 A3-A8,以及后续所有非微小改动。
**路线口径**:WFOC/DBWFOC/WFDG/WDRG 后,HR/考勤员工日常审批优先复用企业微信成熟能力,OA 做按域镜像、人工接管、恢复回写、财务闭环和审计中台;报销、采购、合同、项目、PDF OCR、付款批次、AP 台账、代账交接和高敏附件继续由 OA 主办;企业微信只做脱敏消息和 OA deeplink;飞书不进入当前路线。后续企微/OA 运行时迁移前必须先读 [企微优先开发路线图](./企微优先开发路线图.md),再做对应 POC。WPROC1 后,WAPC2 不能直接进入 `wecom_attendance_approval_mirror_v1`,必须先完成 WAPC2F、WCBK1、WACP3 和 WADM1;缺配置或权限时记录 `NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不得伪造成通过。 **路线口径**:WFOC/DBWFOC/WFDG/WDRG 后,HR/考勤员工日常审批优先复用企业微信成熟能力,OA 做按域镜像、人工接管、恢复回写、财务闭环和审计中台;报销、采购、合同、项目、PDF OCR、付款批次、AP 台账、代账交接和高敏附件继续由 OA 主办;企业微信只做脱敏消息和 OA deeplink;飞书不进入当前路线。后续企微/OA 运行时迁移前必须先读 [企微优先开发路线图](./企微优先开发路线图.md),再做对应 POC。WPROC1 后,WAPC2 不能直接进入 `wecom_attendance_approval_mirror_v1`,必须先完成 WAPC2F、WCBK1、WACP3 和 WADM1;WPROC2 后先跑 `check-process-contract` process gate;缺配置或权限时记录 `NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不得伪造成通过。
本文回答“什么时候测试、测什么、怎么判定通过、怎么记录跳过”。具体业务验收仍以主 PRD、模块规约和最新 Issue CSV 为准。 本文回答“什么时候测试、测什么、怎么判定通过、怎么记录跳过”。具体业务验收仍以主 PRD、模块规约和最新 Issue CSV 为准。
@@ -51,6 +51,12 @@ WPROC1 后,企微 HR/考勤相关 Issue 在测试层面同步执行三层门
| 能力门禁 | runner 必须输出真实 `PASS`、`NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不能把缺 Secret、权限、可信 IP、模板、回调或可见范围写成通过。 | | 能力门禁 | runner 必须输出真实 `PASS`、`NEEDS_CONFIG` 或 `SKIP/BLOCKED_BY_EXTERNAL_CONFIG`,不能把缺 Secret、权限、可信 IP、模板、回调或可见范围写成通过。 |
| 实现门禁 | Issue CSV、静态检查、单测、回归、公网验证、状态回填和中文提交必须按 `Test_Method` 闭环。 | | 实现门禁 | Issue CSV、静态检查、单测、回归、公网验证、状态回填和中文提交必须按 `Test_Method` 闭环。 |
WPROC2 把上述要求固化为自动化 process gate:
- 基线门禁:`node scripts/qa/check-process-contract.mjs --baseline`,已接入 `scripts/check-minimal.sh`。
- 合同门禁:`node scripts/qa/check-process-contract.mjs --issue <csv> --profile <profile> --json`。
- WAPC2F 必须使用 `wecom-approval-fixture` profile;后续企微高风险合同至少使用 `wecom` profile。
Definition of Ready: Definition of Ready:
- Issue CSV 已写清主流程、异常流程、权限、外部配置和脱敏报告边界。 - Issue CSV 已写清主流程、异常流程、权限、外部配置和脱敏报告边界。
@@ -1,10 +1,10 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
"WAPC2F-0","合同建档与边界冻结","建立 WAPC2F 企微审批 POC 样件自动生成合同;承接 WAPC2 当前缺模板 ID 和低风险 sp_no 的配置缺口,本轮目标是尽量自动创建专用测试模板和测试审批单。","1) CSV 校验通过;2) 范围限定 OA-POC 前缀请假/补卡测试模板和低风险测试审批单;3) 固定 WECOM_AGENT_SECRET;4) 默认 dry-run;5) 默认测试链为申请人 SMOKE002 -> 审批人 SMOKE101,禁止自审;6) 不修改正式模板、不接真实回调、不写 OA 业务数据、不进入 wecom_attendance_approval_mirror_v1。","受影响流程:WAPC2 缺配置 -> 自动生成 POC 样件 -> 复跑模板/审批详情只读 POC;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv。","python3|manual","TODO","TODO","TODO","issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv","[]","本合同允许规划自动写企微测试样件,但真实 live 写入仍需后续实施前确认;回滚路径:撤回本轮代码/文档,企微后台中 OA-POC 测试模板和测试单如已生成需人工隐藏/停用或保留审计。" "WAPC2F-0","合同建档与边界冻结","建立 WAPC2F 企微审批 POC 样件自动生成合同;承接 WAPC2 当前缺模板 ID 和低风险 sp_no 的配置缺口,本轮目标是尽量自动创建专用测试模板和测试审批单。","1) CSV 校验通过;2) 范围限定 OA-POC 前缀请假/补卡测试模板和低风险测试审批单;3) 固定 WECOM_AGENT_SECRET;4) 默认 dry-run;5) 默认测试链为申请人 SMOKE002 -> 审批人 SMOKE101,禁止自审;6) 不修改正式模板、不接真实回调、不写 OA 业务数据、不进入 wecom_attendance_approval_mirror_v1。","受影响流程:WAPC2 缺配置 -> 自动生成 POC 样件 -> 复跑模板/审批详情只读 POC;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json。","python3|node|manual","TODO","TODO","TODO","issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv","[]","WPROC2 baseline gate 通过后才能实施;本合同允许规划自动写企微测试样件,但真实 live 写入仍需后续实施前确认;回滚路径:撤回本轮代码/文档,企微后台中 OA-POC 测试模板和测试单如已生成需人工隐藏/停用或保留审计。"
"WAPC2F-1","路线自动化优先修正","更新路线图和事实源,把 WAPC2 后续阶段调整为自动化优先:WAPC2F 自动生成样件 -> WAPC2 复跑 -> WCBK1 回调 POC -> WACP3 补偿拉取 POC -> WADM1 镜像数据模型 -> 镜像实现。","1) 文档明确后续能自动化的动作优先用 QA-only runner 执行;2) 人工只负责批准写入、配置不可自动化的后台项和确认风险;3) 不再默认要求手工创建模板或测试单;4) 不把自动生成 POC 样件误读为正式模板配置完成。","受影响流程:企微审批路线治理;验证步骤:node scripts/qa/audit-docs.mjs --check-registry;rg -n 'WAPC2F|自动生成|OA-POC|WCBK1|WACP3|WADM1|wecom_attendance_approval_mirror_v1' docs .agents/skills/hyb-oa-delivery/SKILL.md。","node|rg","TODO","TODO","TODO","docs/企微优先开发路线图.md|docs/企微API能力目录.md|docs/需求-统一审批中心规约.md|docs/需求-企业微信基础设施规约.md|docs/管理员手册.md|docs/文档索引.md|docs/文档事实源状态矩阵.md|.agents/skills/hyb-oa-delivery/SKILL.md","[""WAPC2F-0""]","文档只记录自动化策略和边界,不保存 Secret、Token、完整 template_id、完整 sp_no 或原始 payload。" "WAPC2F-1","路线自动化优先修正","更新路线图和事实源,把 WAPC2 后续阶段调整为自动化优先:WAPC2F 自动生成样件 -> WAPC2 复跑 -> WCBK1 回调 POC -> WACP3 补偿拉取 POC -> WADM1 镜像数据模型 -> 镜像实现。","1) 文档明确后续能自动化的动作优先用 QA-only runner 执行;2) 人工只负责批准写入、配置不可自动化的后台项和确认风险;3) 不再默认要求手工创建模板或测试单;4) 不把自动生成 POC 样件误读为正式模板配置完成。","受影响流程:企微审批路线治理;验证步骤:node scripts/qa/audit-docs.mjs --check-registry;rg -n 'WAPC2F|自动生成|OA-POC|WCBK1|WACP3|WADM1|wecom_attendance_approval_mirror_v1' docs .agents/skills/hyb-oa-delivery/SKILL.md。","node|rg","TODO","TODO","TODO","docs/企微优先开发路线图.md|docs/企微API能力目录.md|docs/需求-统一审批中心规约.md|docs/需求-企业微信基础设施规约.md|docs/管理员手册.md|docs/文档索引.md|docs/文档事实源状态矩阵.md|.agents/skills/hyb-oa-delivery/SKILL.md","[""WAPC2F-0""]","文档只记录自动化策略和边界,不保存 Secret、Token、完整 template_id、完整 sp_no 或原始 payload。"
"WAPC2F-2","企微审批写接口调研与安全门禁","核对企业微信创建审批模板和提交审批申请官方 API 的实际字段、权限、可见范围、可信 IP、审批人规则和限制;固化 live 写入双重或三重确认。","1) create_template/applyevent 的方法、路径、Secret 和字段结构明确;2) 若官方接口不支持所需模板或测试单自动生成,改为 SKIP/BLOCKED_BY_EXTERNAL_CONFIG;3) live 写入必须同时指定 CLI 写入参数和 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 不尝试其他 Secret。","受影响流程:自动样件生成前置安全审查;验证步骤:rg -n '创建审批模板|提交审批申请|applyevent|create_template|WECOM_APPROVAL_FIXTURE_WRITE' docs server/src/scripts server/tests。","rg|manual","TODO","TODO","TODO","docs/企微API能力目录.md|server/src/scripts/check-wecom-approval-fixtures.js|server/src/services/integrations/wecomApproval.js","[""WAPC2F-1""]","若官方文档或远端 API 返回能力不支持,后续只记录不可自动化项,不做绕路试错。" "WAPC2F-2","企微审批写接口调研与安全门禁","核对企业微信创建审批模板和提交审批申请官方 API 的实际字段、权限、可见范围、可信 IP、审批人规则和限制;固化 live 写入双重或三重确认。","1) create_template/applyevent 的方法、路径、Secret 和字段结构明确;2) 若官方接口不支持所需模板或测试单自动生成,改为 SKIP/BLOCKED_BY_EXTERNAL_CONFIG;3) live 写入必须同时指定 CLI 写入参数和 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 不尝试其他 Secret。","受影响流程:自动样件生成前置安全审查;验证步骤:rg -n '创建审批模板|提交审批申请|applyevent|create_template|WECOM_APPROVAL_FIXTURE_WRITE' docs server/src/scripts server/tests。","rg|manual","TODO","TODO","TODO","docs/企微API能力目录.md|server/src/scripts/check-wecom-approval-fixtures.js|server/src/services/integrations/wecomApproval.js","[""WAPC2F-1""]","若官方文档或远端 API 返回能力不支持,后续只记录不可自动化项,不做绕路试错;live 写入前必须明确清理/隐藏/停用或保留审计方式。"
"WAPC2F-3","QA-only 样件生成 runner","新增 QA-only runner check-wecom-approval-fixtures,用于 dry-run/live 创建 OA-POC 请假/补卡测试模板、提交低风险测试审批单,并输出脱敏 summary.json。","1) package.json 增加 check:wecom-approval-fixtures;2) 默认 dry-run 只构建脱敏 payload;3) live 写入必须显式 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 支持指定申请人/审批人员工号,默认申请人 SMOKE002、审批人 SMOKE101;5) 预检两者 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid;6) 命中自审时硬阻断;7) 报告不输出完整模板 ID、完整 sp_no、userid、手机号、邮箱、token、secret、表单值、附件、评论或原始 payload。","受影响流程:自动创建测试模板和测试审批单;验证步骤:cd server && node --check src/scripts/check-wecom-approval-fixtures.js;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js --reporter=verbose。","node|vitest","TODO","TODO","TODO","server/src/scripts/check-wecom-approval-fixtures.js|server/package.json","[""WAPC2F-2""]","runner 只用于 QA 样件生成;不新增公开业务 API,不改 Prisma schema,不改前端;如果 SMOKE101 不可用,不自动切换为 HYD000007 或其他审批人,返回配置缺口并问答确认。" "WAPC2F-3","QA-only 样件生成 runner","新增 QA-only runner check-wecom-approval-fixtures,用于 dry-run/live 创建 OA-POC 请假/补卡测试模板、提交低风险测试审批单,并输出脱敏 summary.json。","1) package.json 增加 check:wecom-approval-fixtures;2) 默认 dry-run 只构建脱敏 payload;3) live 写入必须显式 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 支持指定申请人/审批人员工号,默认申请人 SMOKE002、审批人 SMOKE101;5) 预检两者 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid;6) 命中自审时硬阻断;7) 报告不输出完整模板 ID、完整 sp_no、完整 userid、手机号、邮箱、token、secret、表单值、附件、评论或原始 payload。","受影响流程:自动创建测试模板和测试审批单;验证步骤:node scripts/qa/check-process-contract.mjs --baseline --json;cd server && node --check src/scripts/check-wecom-approval-fixtures.js;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js --reporter=verbose。","node|vitest","TODO","TODO","TODO","server/src/scripts/check-wecom-approval-fixtures.js|server/package.json","[""WAPC2F-2""]","WPROC2 baseline gate 通过后才能实施;runner 只用于 QA 样件生成;不新增公开业务 API,不改 Prisma schema,不改前端;如果 SMOKE101 不可用,不自动切换为 HYD000007 或其他审批人,返回配置缺口并问答确认;live 写入留下的 OA-POC 测试模板/测试单需按清理、隐藏、停用或保留审计方式处理。"
"WAPC2F-4","审批模板创建与测试审批提交集成","扩展企微审批集成服务,固定 WECOM_AGENT_SECRET 调用创建审批模板和提交审批申请接口,并复用 WAPC2 脱敏、错误分类和无 fallback 规则。","1) 创建模板只创建 OA-POC 前缀测试模板;2) 提交审批只提交低风险无附件测试单;3) 申请人/审批人命中同一 OA 员工或同一企微 userid 时返回自审阻断;4) API 错误、权限、可见范围、可信 IP 或模板能力限制均返回 BLOCKED_BY_EXTERNAL_CONFIG;5) 不修改或覆盖正式模板。","受影响流程:企微审批测试样件写入;验证步骤:cd server && node --check src/services/integrations/wecomApproval.js;focused vitest 覆盖固定 Secret、无 fallback、dry-run/live 分支、自审阻断和 API 错误分类。","node|vitest","TODO","TODO","TODO","server/src/services/integrations/wecomApproval.js","[""WAPC2F-3""]","真实写企微测试模板可能在企微后台留下记录,报告和最终说明必须提醒管理员后续隐藏/停用/保留审计。" "WAPC2F-4","审批模板创建与测试审批提交集成","扩展企微审批集成服务,固定 WECOM_AGENT_SECRET 调用创建审批模板和提交审批申请接口,并复用 WAPC2 脱敏、错误分类和无 fallback 规则。","1) 创建模板只创建 OA-POC 前缀测试模板;2) 提交审批只提交低风险无附件测试单;3) 申请人/审批人命中同一 OA 员工或同一企微 userid 时返回自审阻断;4) API 错误、权限、可见范围、可信 IP 或模板能力限制均返回 BLOCKED_BY_EXTERNAL_CONFIG;5) 不修改或覆盖正式模板。","受影响流程:企微审批测试样件写入;验证步骤:node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json;cd server && node --check src/services/integrations/wecomApproval.js;focused vitest 覆盖固定 Secret、无 fallback、dry-run/live 分支、自审阻断和 API 错误分类。","node|vitest","TODO","TODO","TODO","server/src/services/integrations/wecomApproval.js","[""WAPC2F-3""]","真实写企微测试模板可能在企微后台留下记录;回滚/清理口径为后续隐藏、停用、人工清理或保留审计,报告和最终说明必须提醒管理员。"
"WAPC2F-5","自动复跑 WAPC2 只读 POC","样件生成成功后,runner 自动把生成的模板 ID 和 sp_no 传给现有 check:wecom-approval-poc,验证 gettemplatedetail/getapprovaldetail 只读链路。","1) 样件生成成功后自动复用 WAPC2 runner 或等价内部函数复跑;2) 目标结论 PASS_APPROVAL_POC;3) 若只生成部分样件则返回 PARTIAL_APPROVAL_POC_NEEDS_CONFIG;4) 若企微阻断则返回 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。","受影响流程:自动生成样件 -> 自动只读验证 -> 输出一份可审计结论;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。","vitest|node","TODO","TODO","TODO","server/src/scripts/check-wecom-approval-fixtures.js|server/src/scripts/check-wecom-approval-poc.js","[""WAPC2F-4""]","自动复跑不得把生成的完整 ID 或 sp_no 写入报告;只允许脱敏前缀和计数。" "WAPC2F-5","自动复跑 WAPC2 只读 POC","样件生成成功后,runner 自动把生成的模板 ID 和 sp_no 传给现有 check:wecom-approval-poc,验证 gettemplatedetail/getapprovaldetail 只读链路。","1) 样件生成成功后自动复用 WAPC2 runner 或等价内部函数复跑;2) 目标结论 PASS_APPROVAL_POC;3) 若只生成部分样件则返回 PARTIAL_APPROVAL_POC_NEEDS_CONFIG;4) 若企微阻断则返回 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。","受影响流程:自动生成样件 -> 自动只读验证 -> 输出一份可审计结论;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。","vitest|node","TODO","TODO","TODO","server/src/scripts/check-wecom-approval-fixtures.js|server/src/scripts/check-wecom-approval-poc.js","[""WAPC2F-4""]","自动复跑不得把生成的完整 ID 或 sp_no 写入报告;只允许脱敏前缀和计数。"
"WAPC2F-6","Focused 单测与隐私回归","新增 focused vitest 覆盖样件生成 runner、写入保护、无 Secret fallback、脱敏报告、自动复跑和阻断分类。","1) 覆盖 dry-run 默认不写;2) 覆盖缺 WECOM_APPROVAL_FIXTURE_WRITE 时 live 不写;3) 覆盖 WECOM_AGENT_SECRET 固定选择;4) 覆盖创建模板、提交测试单、自动复跑;5) 覆盖申请人/审批人相同时自审硬阻断;6) 覆盖 SMOKE101 不可用时不自动换人;7) 覆盖隐私字段不泄露。","受影响流程:WAPC2F 本地质量门禁;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。","vitest","TODO","TODO","TODO","server/tests/unit/scripts/check-wecom-approval-fixtures.test.js|server/tests/unit/scripts/check-wecom-approval-poc.test.js","[""WAPC2F-5""]","单测使用 mock fetch,不访问公网,不写企微。" "WAPC2F-6","Focused 单测与隐私回归","新增 focused vitest 覆盖样件生成 runner、写入保护、无 Secret fallback、脱敏报告、自动复跑和阻断分类。","1) 覆盖 dry-run 默认不写;2) 覆盖缺 WECOM_APPROVAL_FIXTURE_WRITE 时 live 不写;3) 覆盖 WECOM_AGENT_SECRET 固定选择;4) 覆盖创建模板、提交测试单、自动复跑;5) 覆盖申请人/审批人相同时自审硬阻断;6) 覆盖 SMOKE101 不可用时不自动换人;7) 覆盖隐私字段不泄露。","受影响流程:WAPC2F 本地质量门禁;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。","vitest","TODO","TODO","TODO","server/tests/unit/scripts/check-wecom-approval-fixtures.test.js|server/tests/unit/scripts/check-wecom-approval-poc.test.js","[""WAPC2F-5""]","单测使用 mock fetch,不访问公网,不写企微。"
"WAPC2F-7","本地门禁与公网受控验证","本地门禁通过后,以 SYNC_ENV=0 受控部署;远端先 dry-run,再在单次进程内设置 WECOM_APPROVAL_FIXTURE_WRITE=1 执行 live 样件生成和 WAPC2 自动复跑。","1) 本地 CSV、node --check、prisma validate、focused vitest、文档审计、skill 校验和 git diff --check 通过;2) SYNC_ENV=0 部署,不同步本地 env;3) live 写入只创建 OA-POC 测试样件,申请链固定 SMOKE002 -> SMOKE101;4) 公网 /ready 和 runtime smoke 通过;5) 报告结论真实记录 PASS/PARTIAL/SKIP。","受影响流程:公网自动化 POC 样件生成和只读验证;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;cd server && npm run prisma:validate;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose;node scripts/qa/audit-docs.mjs --check-registry;SYNC_ENV=0 bash deploy/trialrun/deploy.sh;远端 npm run check:wecom-approval-fixtures。","python3|node|npm|vitest|bash|ssh|curl","TODO","TODO","TODO","N/A","[""WAPC2F-6""]","公网 live 写入前最终说明必须再次提示会在企微后台留下 OA-POC 测试模板/审批记录;不得修改正式模板;若 SMOKE101 不可用,停止并问答确认,不自动换审批人。" "WAPC2F-7","本地门禁与公网受控验证","本地门禁通过后,以 SYNC_ENV=0 受控部署;远端先 dry-run,再在单次进程内设置 WECOM_APPROVAL_FIXTURE_WRITE=1 执行 live 样件生成和 WAPC2 自动复跑。","1) WPROC2 baseline gate、CSV、node --check、prisma validate、focused vitest、文档审计、skill 校验和 git diff --check 通过;2) SYNC_ENV=0 部署,不同步本地 env;3) live 写入只创建 OA-POC 测试样件,申请链固定 SMOKE002 -> SMOKE101;4) 公网 /ready 和 runtime smoke 通过;5) 报告结论真实记录 PASS/PARTIAL/SKIP。","受影响流程:公网自动化 POC 样件生成和只读验证;验证步骤:node scripts/qa/check-process-contract.mjs --baseline --json;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;cd server && npm run prisma:validate;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose;node scripts/qa/audit-docs.mjs --check-registry;SYNC_ENV=0 bash deploy/trialrun/deploy.sh;远端 npm run check:wecom-approval-fixtures。","python3|node|npm|vitest|bash|ssh|curl","TODO","TODO","TODO","N/A","[""WAPC2F-6""]","WPROC2 baseline gate 是实施前置;公网 live 写入前最终说明必须再次提示会在企微后台留下 OA-POC 测试模板/审批记录;不得修改正式模板;若 SMOKE101 不可用,停止并问答确认,不自动换审批人;清理方式为隐藏、停用、人工清理或保留审计。"
"WAPC2F-8","状态回填、中文提交与下一阶段问答","根据验证结果回填状态并中文提交;最终用问答方式让用户决定是否进入 WCBK1 回调只读 POC、WACP3 补偿拉取 POC 或暂停。","1) Issue 状态按 Test_Method 通过情况回填;2) 中文提交引用 WAPC2F;3) 最终说明包含当前状态、改了什么、测试了什么、结果是什么、剩余风险和下一步问答;4) 不直接进入回调或镜像实现。","受影响流程:WAPC2F 交付闭环和后续路线决策;验证步骤:git status --short;git log --oneline -1;最终问答列出 WCBK1/WACP3/WADM1 选择。","git|manual","TODO","TODO","TODO","issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv|N/A","[""WAPC2F-7""]","后续动作默认自动化优先;人工只处理写入批准、企微后台无法 API 化的配置和真机确认。" "WAPC2F-8","状态回填、中文提交与下一阶段问答","根据验证结果回填状态并中文提交;最终用问答方式让用户决定是否进入 WCBK1 回调只读 POC、WACP3 补偿拉取 POC 或暂停。","1) Issue 状态按 Test_Method 通过情况回填;2) 中文提交引用 WAPC2F;3) 最终说明包含当前状态、改了什么、测试了什么、结果是什么、剩余风险和下一步问答;4) 不直接进入回调或镜像实现。","受影响流程:WAPC2F 交付闭环和后续路线决策;验证步骤:git status --short;git log --oneline -1;最终问答列出 WCBK1/WACP3/WADM1 选择。","git|manual","TODO","TODO","TODO","issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv|N/A","[""WAPC2F-7""]","后续动作默认自动化优先;人工只处理写入批准、企微后台无法 API 化的配置和真机确认;本行不写企微数据,若前序 live 生成样件则按隐藏、停用、人工清理或保留审计处理。"
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
2 WAPC2F-0 合同建档与边界冻结 建立 WAPC2F 企微审批 POC 样件自动生成合同;承接 WAPC2 当前缺模板 ID 和低风险 sp_no 的配置缺口,本轮目标是尽量自动创建专用测试模板和测试审批单。 1) CSV 校验通过;2) 范围限定 OA-POC 前缀请假/补卡测试模板和低风险测试审批单;3) 固定 WECOM_AGENT_SECRET;4) 默认 dry-run;5) 默认测试链为申请人 SMOKE002 -> 审批人 SMOKE101,禁止自审;6) 不修改正式模板、不接真实回调、不写 OA 业务数据、不进入 wecom_attendance_approval_mirror_v1。 受影响流程:WAPC2 缺配置 -> 自动生成 POC 样件 -> 复跑模板/审批详情只读 POC;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv。 受影响流程:WAPC2 缺配置 -> 自动生成 POC 样件 -> 复跑模板/审批详情只读 POC;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json。 python3|manual python3|node|manual TODO TODO TODO issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv [] 本合同允许规划自动写企微测试样件,但真实 live 写入仍需后续实施前确认;回滚路径:撤回本轮代码/文档,企微后台中 OA-POC 测试模板和测试单如已生成需人工隐藏/停用或保留审计。 WPROC2 baseline gate 通过后才能实施;本合同允许规划自动写企微测试样件,但真实 live 写入仍需后续实施前确认;回滚路径:撤回本轮代码/文档,企微后台中 OA-POC 测试模板和测试单如已生成需人工隐藏/停用或保留审计。
3 WAPC2F-1 路线自动化优先修正 更新路线图和事实源,把 WAPC2 后续阶段调整为自动化优先:WAPC2F 自动生成样件 -> WAPC2 复跑 -> WCBK1 回调 POC -> WACP3 补偿拉取 POC -> WADM1 镜像数据模型 -> 镜像实现。 1) 文档明确后续能自动化的动作优先用 QA-only runner 执行;2) 人工只负责批准写入、配置不可自动化的后台项和确认风险;3) 不再默认要求手工创建模板或测试单;4) 不把自动生成 POC 样件误读为正式模板配置完成。 受影响流程:企微审批路线治理;验证步骤:node scripts/qa/audit-docs.mjs --check-registry;rg -n 'WAPC2F|自动生成|OA-POC|WCBK1|WACP3|WADM1|wecom_attendance_approval_mirror_v1' docs .agents/skills/hyb-oa-delivery/SKILL.md。 node|rg TODO TODO TODO docs/企微优先开发路线图.md|docs/企微API能力目录.md|docs/需求-统一审批中心规约.md|docs/需求-企业微信基础设施规约.md|docs/管理员手册.md|docs/文档索引.md|docs/文档事实源状态矩阵.md|.agents/skills/hyb-oa-delivery/SKILL.md ["WAPC2F-0"] 文档只记录自动化策略和边界,不保存 Secret、Token、完整 template_id、完整 sp_no 或原始 payload。
4 WAPC2F-2 企微审批写接口调研与安全门禁 核对企业微信创建审批模板和提交审批申请官方 API 的实际字段、权限、可见范围、可信 IP、审批人规则和限制;固化 live 写入双重或三重确认。 1) create_template/applyevent 的方法、路径、Secret 和字段结构明确;2) 若官方接口不支持所需模板或测试单自动生成,改为 SKIP/BLOCKED_BY_EXTERNAL_CONFIG;3) live 写入必须同时指定 CLI 写入参数和 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 不尝试其他 Secret。 受影响流程:自动样件生成前置安全审查;验证步骤:rg -n '创建审批模板|提交审批申请|applyevent|create_template|WECOM_APPROVAL_FIXTURE_WRITE' docs server/src/scripts server/tests。 rg|manual TODO TODO TODO docs/企微API能力目录.md|server/src/scripts/check-wecom-approval-fixtures.js|server/src/services/integrations/wecomApproval.js ["WAPC2F-1"] 若官方文档或远端 API 返回能力不支持,后续只记录不可自动化项,不做绕路试错。 若官方文档或远端 API 返回能力不支持,后续只记录不可自动化项,不做绕路试错;live 写入前必须明确清理/隐藏/停用或保留审计方式。
5 WAPC2F-3 QA-only 样件生成 runner 新增 QA-only runner check-wecom-approval-fixtures,用于 dry-run/live 创建 OA-POC 请假/补卡测试模板、提交低风险测试审批单,并输出脱敏 summary.json。 1) package.json 增加 check:wecom-approval-fixtures;2) 默认 dry-run 只构建脱敏 payload;3) live 写入必须显式 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 支持指定申请人/审批人员工号,默认申请人 SMOKE002、审批人 SMOKE101;5) 预检两者 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid;6) 命中自审时硬阻断;7) 报告不输出完整模板 ID、完整 sp_no、userid、手机号、邮箱、token、secret、表单值、附件、评论或原始 payload。 1) package.json 增加 check:wecom-approval-fixtures;2) 默认 dry-run 只构建脱敏 payload;3) live 写入必须显式 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;4) 支持指定申请人/审批人员工号,默认申请人 SMOKE002、审批人 SMOKE101;5) 预检两者 active、已绑定企微、可见、不是同一 OA 员工且不是同一企微 userid;6) 命中自审时硬阻断;7) 报告不输出完整模板 ID、完整 sp_no、完整 userid、手机号、邮箱、token、secret、表单值、附件、评论或原始 payload。 受影响流程:自动创建测试模板和测试审批单;验证步骤:cd server && node --check src/scripts/check-wecom-approval-fixtures.js;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js --reporter=verbose。 受影响流程:自动创建测试模板和测试审批单;验证步骤:node scripts/qa/check-process-contract.mjs --baseline --json;cd server && node --check src/scripts/check-wecom-approval-fixtures.js;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js --reporter=verbose。 node|vitest TODO TODO TODO server/src/scripts/check-wecom-approval-fixtures.js|server/package.json ["WAPC2F-2"] runner 只用于 QA 样件生成;不新增公开业务 API,不改 Prisma schema,不改前端;如果 SMOKE101 不可用,不自动切换为 HYD000007 或其他审批人,返回配置缺口并问答确认。 WPROC2 baseline gate 通过后才能实施;runner 只用于 QA 样件生成;不新增公开业务 API,不改 Prisma schema,不改前端;如果 SMOKE101 不可用,不自动切换为 HYD000007 或其他审批人,返回配置缺口并问答确认;live 写入留下的 OA-POC 测试模板/测试单需按清理、隐藏、停用或保留审计方式处理。
6 WAPC2F-4 审批模板创建与测试审批提交集成 扩展企微审批集成服务,固定 WECOM_AGENT_SECRET 调用创建审批模板和提交审批申请接口,并复用 WAPC2 脱敏、错误分类和无 fallback 规则。 1) 创建模板只创建 OA-POC 前缀测试模板;2) 提交审批只提交低风险无附件测试单;3) 申请人/审批人命中同一 OA 员工或同一企微 userid 时返回自审阻断;4) API 错误、权限、可见范围、可信 IP 或模板能力限制均返回 BLOCKED_BY_EXTERNAL_CONFIG;5) 不修改或覆盖正式模板。 受影响流程:企微审批测试样件写入;验证步骤:cd server && node --check src/services/integrations/wecomApproval.js;focused vitest 覆盖固定 Secret、无 fallback、dry-run/live 分支、自审阻断和 API 错误分类。 受影响流程:企微审批测试样件写入;验证步骤:node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json;cd server && node --check src/services/integrations/wecomApproval.js;focused vitest 覆盖固定 Secret、无 fallback、dry-run/live 分支、自审阻断和 API 错误分类。 node|vitest TODO TODO TODO server/src/services/integrations/wecomApproval.js ["WAPC2F-3"] 真实写企微测试模板可能在企微后台留下记录,报告和最终说明必须提醒管理员后续隐藏/停用/保留审计。 真实写企微测试模板可能在企微后台留下记录;回滚/清理口径为后续隐藏、停用、人工清理或保留审计,报告和最终说明必须提醒管理员。
7 WAPC2F-5 自动复跑 WAPC2 只读 POC 样件生成成功后,runner 自动把生成的模板 ID 和 sp_no 传给现有 check:wecom-approval-poc,验证 gettemplatedetail/getapprovaldetail 只读链路。 1) 样件生成成功后自动复用 WAPC2 runner 或等价内部函数复跑;2) 目标结论 PASS_APPROVAL_POC;3) 若只生成部分样件则返回 PARTIAL_APPROVAL_POC_NEEDS_CONFIG;4) 若企微阻断则返回 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。 受影响流程:自动生成样件 -> 自动只读验证 -> 输出一份可审计结论;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。 vitest|node TODO TODO TODO server/src/scripts/check-wecom-approval-fixtures.js|server/src/scripts/check-wecom-approval-poc.js ["WAPC2F-4"] 自动复跑不得把生成的完整 ID 或 sp_no 写入报告;只允许脱敏前缀和计数。
8 WAPC2F-6 Focused 单测与隐私回归 新增 focused vitest 覆盖样件生成 runner、写入保护、无 Secret fallback、脱敏报告、自动复跑和阻断分类。 1) 覆盖 dry-run 默认不写;2) 覆盖缺 WECOM_APPROVAL_FIXTURE_WRITE 时 live 不写;3) 覆盖 WECOM_AGENT_SECRET 固定选择;4) 覆盖创建模板、提交测试单、自动复跑;5) 覆盖申请人/审批人相同时自审硬阻断;6) 覆盖 SMOKE101 不可用时不自动换人;7) 覆盖隐私字段不泄露。 受影响流程:WAPC2F 本地质量门禁;验证步骤:cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose。 vitest TODO TODO TODO server/tests/unit/scripts/check-wecom-approval-fixtures.test.js|server/tests/unit/scripts/check-wecom-approval-poc.test.js ["WAPC2F-5"] 单测使用 mock fetch,不访问公网,不写企微。
9 WAPC2F-7 本地门禁与公网受控验证 本地门禁通过后,以 SYNC_ENV=0 受控部署;远端先 dry-run,再在单次进程内设置 WECOM_APPROVAL_FIXTURE_WRITE=1 执行 live 样件生成和 WAPC2 自动复跑。 1) 本地 CSV、node --check、prisma validate、focused vitest、文档审计、skill 校验和 git diff --check 通过;2) SYNC_ENV=0 部署,不同步本地 env;3) live 写入只创建 OA-POC 测试样件,申请链固定 SMOKE002 -> SMOKE101;4) 公网 /ready 和 runtime smoke 通过;5) 报告结论真实记录 PASS/PARTIAL/SKIP。 1) WPROC2 baseline gate、CSV、node --check、prisma validate、focused vitest、文档审计、skill 校验和 git diff --check 通过;2) SYNC_ENV=0 部署,不同步本地 env;3) live 写入只创建 OA-POC 测试样件,申请链固定 SMOKE002 -> SMOKE101;4) 公网 /ready 和 runtime smoke 通过;5) 报告结论真实记录 PASS/PARTIAL/SKIP。 受影响流程:公网自动化 POC 样件生成和只读验证;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;cd server && npm run prisma:validate;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose;node scripts/qa/audit-docs.mjs --check-registry;SYNC_ENV=0 bash deploy/trialrun/deploy.sh;远端 npm run check:wecom-approval-fixtures。 受影响流程:公网自动化 POC 样件生成和只读验证;验证步骤:node scripts/qa/check-process-contract.mjs --baseline --json;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;cd server && npm run prisma:validate;cd server && npx vitest run tests/unit/scripts/check-wecom-approval-fixtures.test.js tests/unit/scripts/check-wecom-approval-poc.test.js --reporter=verbose;node scripts/qa/audit-docs.mjs --check-registry;SYNC_ENV=0 bash deploy/trialrun/deploy.sh;远端 npm run check:wecom-approval-fixtures。 python3|node|npm|vitest|bash|ssh|curl TODO TODO TODO N/A ["WAPC2F-6"] 公网 live 写入前最终说明必须再次提示会在企微后台留下 OA-POC 测试模板/审批记录;不得修改正式模板;若 SMOKE101 不可用,停止并问答确认,不自动换审批人。 WPROC2 baseline gate 是实施前置;公网 live 写入前最终说明必须再次提示会在企微后台留下 OA-POC 测试模板/审批记录;不得修改正式模板;若 SMOKE101 不可用,停止并问答确认,不自动换审批人;清理方式为隐藏、停用、人工清理或保留审计。
10 WAPC2F-8 状态回填、中文提交与下一阶段问答 根据验证结果回填状态并中文提交;最终用问答方式让用户决定是否进入 WCBK1 回调只读 POC、WACP3 补偿拉取 POC 或暂停。 1) Issue 状态按 Test_Method 通过情况回填;2) 中文提交引用 WAPC2F;3) 最终说明包含当前状态、改了什么、测试了什么、结果是什么、剩余风险和下一步问答;4) 不直接进入回调或镜像实现。 受影响流程:WAPC2F 交付闭环和后续路线决策;验证步骤:git status --short;git log --oneline -1;最终问答列出 WCBK1/WACP3/WADM1 选择。 git|manual TODO TODO TODO issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv|N/A ["WAPC2F-7"] 后续动作默认自动化优先;人工只处理写入批准、企微后台无法 API 化的配置和真机确认。 后续动作默认自动化优先;人工只处理写入批准、企微后台无法 API 化的配置和真机确认;本行不写企微数据,若前序 live 生成样件则按隐藏、停用、人工清理或保留审计处理。
@@ -0,0 +1,9 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
"WPROC2-0","合同建档与边界冻结","建立 WPROC2 开发流程自动化门禁合同;本轮只把 WPROC1 文档规则升级为可执行 QA-only process gate,不部署、不写 OA/企微数据、不实现 WAPC2F 业务 runner。","1) CSV 校验通过;2) 范围限定 Issue CSV、QA 脚本、单测、最小门禁接入和事实源回写;3) 不新增公开业务 API、Prisma schema、前端页面或 feature flag;4) 不调用企微写接口。","受影响流程:开发流程治理;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_11-15-10-process-gate-automation-v1.csv。","python3|manual","DONE","DONE","DONE","issues/2026-05-19_11-15-10-process-gate-automation-v1.csv","[]","回滚路径:撤回 WPROC2 Issue、check-process-contract 脚本、测试、check-minimal 接入和事实源回写;本轮无数据库、部署、远端配置或企微写入;已通过 CSV 校验。"
"WPROC2-1","新增流程门禁 CLI","新增 QA-only CLI scripts/qa/check-process-contract.mjs,支持 --baseline 和 --issue <csv> --profile <profile> --json,首批 profile 为 general、wecom、wecom-approval-fixture、docs-only。","1) CLI 只读,不修改仓库或远端;2) --baseline 检查核心事实源、WPROC1/WPROC2 口径和 WAPC2F 合同;3) 单 Issue 检查输出 PASS/FAIL、errors、warnings 和 checks;4) 支持 CommonJS/Vitest 通过动态 import 复用导出函数。","受影响流程:本地/CI 流程门禁;验证步骤:node --check scripts/qa/check-process-contract.mjs;node scripts/qa/check-process-contract.mjs --baseline --json。","node","DONE","DONE","DONE","scripts/qa/check-process-contract.mjs","[""WPROC2-0""]","脚本不得打印 Secret、token、完整 userid、完整 template_id、完整 sp_no 或原始 payload;仅输出规则命中摘要;node --check 与 baseline JSON 均通过。"
"WPROC2-2","固化合同规则检查","在 process gate 中固化 CSV 必填列、状态值、Dependencies JSON、Test_Method 业务流程步骤、回滚/清理说明、事实源读取和缺配置分类检查。","1) 合法 WAPC2F 合同通过 wecom-approval-fixture profile;2) 缺 Dependencies JSON、缺业务流程 Test_Method、缺回滚/清理说明或缺配置分类时失败;3) docs-only profile 不误判为企微写入合同。","受影响流程:Issue CSV 质量门禁;验证步骤:node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json;focused vitest。","node|vitest","DONE","DONE","DONE","scripts/qa/check-process-contract.mjs|server/tests/unit/scripts/check-process-contract.test.js","[""WPROC2-1""]","规则按当前 WPROC1/WAPC2F 口径实现;后续 profile 扩展另建 Issue;WAPC2F profile 与 focused vitest 均通过。"
"WPROC2-3","固化企微审批高风险检查","为 wecom-approval-fixture profile 增加 Secret 固定、无 fallback、dry-run 默认、live 双开关、非自审链路、WAPC2F 阶段顺序和脱敏输出检查。","1) 必须命中 WECOM_AGENT_SECRET、WECOM_APPROVAL_FIXTURE_WRITE=1、dry-run、SMOKE002、SMOKE101、禁止自审;2) 不允许默认 wangshunli 自审链;3) 必须命中 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG;4) 必须声明不输出手机号、邮箱、token、secret、完整 userid、完整 template_id、完整 sp_no 或原始 payload。","受影响流程:企微审批 POC 样件生成前置门禁;验证步骤:cd server && npx vitest run tests/unit/scripts/check-process-contract.test.js --reporter=verbose。","vitest|node","DONE","DONE","DONE","scripts/qa/check-process-contract.mjs|server/tests/unit/scripts/check-process-contract.test.js","[""WPROC2-2""]","该门禁只检查合同和事实源,不创建模板、不提交审批单、不访问公网企微、不写企微数据,因此无需清理;focused vitest 8 项通过。"
"WPROC2-4","接入最小门禁","在 scripts/check-minimal.sh 增加 process gate baseline 检查,使 ci-minimal 通过既有入口自动执行流程门禁;不单独修改 GitHub workflow。","1) scripts/check-minimal.sh 包含 node scripts/qa/check-process-contract.mjs --baseline;2) bash -n scripts/check-minimal.sh 通过;3) bash scripts/check-minimal.sh 通过或真实记录环境阻断。","受影响流程:本地最小门禁和 ci-minimal;验证步骤:bash -n scripts/check-minimal.sh;bash scripts/check-minimal.sh。","bash|node","DONE","DONE","DONE","scripts/check-minimal.sh","[""WPROC2-3""]","bash -n scripts/check-minimal.sh 与 bash scripts/check-minimal.sh 已通过;完整最小门禁包含 process gate、Prisma、后端静态、前端 typecheck/build 和 feature matrix。"
"WPROC2-5","更新 WAPC2F 合同前置说明","修正 WAPC2F 合同说明,不通过跨 CSV Dependencies 强绑;用 Notes 和 Test_Method 声明 WPROC2 baseline gate 是实施前置,并补充 process gate 命令。","1) WAPC2F 不新增跨 CSV Dependencies;2) WAPC2F Test_Method 包含 check-process-contract;3) Notes 说明 WPROC2 是实施前置;4) WAPC2F CSV 校验仍通过。","受影响流程:WAPC2F 进入实现前检查;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json。","python3|node","DONE","DONE","DONE","issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv","[""WPROC2-4""]","不回填 WAPC2F DONE;WAPC2F 仍是后续实现合同;WAPC2F CSV 校验和 profile gate 均通过。"
"WPROC2-6","回写事实源和 skill","更新开发交付规约、测试门禁、企微路线图、API 能力目录、文档索引、事实源矩阵和项目 skill,登记 WPROC2 和 check-process-contract。","1) 事实源说明 WPROC2 是 WAPC2F 前置 process gate;2) skill 要求企微高风险开发先跑 process gate;3) 文档审计和 skill 校验通过。","受影响流程:后续 agent 读取顺序和流程执行;验证步骤:node scripts/qa/audit-docs.mjs --check-registry;python3 /home/shunli/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/hyb-oa-delivery;rg -n 'WPROC2|check-process-contract|process gate' docs .agents/skills/hyb-oa-delivery/SKILL.md。","node|python3|rg","DONE","DONE","DONE","docs/开发交付与变更管理规约.md|docs/测试规约与回归门禁.md|docs/企微优先开发路线图.md|docs/企微API能力目录.md|docs/文档索引.md|docs/文档事实源状态矩阵.md|.agents/skills/hyb-oa-delivery/SKILL.md","[""WPROC2-5""]","不新建独立流程文档;优先更新现有事实源;文档审计通过但保留既有 24 个未登记文档 warning,skill 校验通过。"
"WPROC2-7","门禁验证、状态回填和提交","执行 WPROC2 Test Plan,按真实结果回填 WPROC2 状态并中文提交。","1) WPROC2/WAPC2F CSV 校验通过;2) node --check、process gate 自测、focused vitest、文档审计、skill 校验、关键词核验、git diff --check 和 check-minimal 通过或真实记录 SKIP/阻断;3) Issue 状态回填真实;4) 中文 commit 引用 WPROC2。","受影响流程:WPROC2 交付闭环;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_11-15-10-process-gate-automation-v1.csv;node --check scripts/qa/check-process-contract.mjs;node scripts/qa/check-process-contract.mjs --baseline --json;cd server && npx vitest run tests/unit/scripts/check-process-contract.test.js --reporter=verbose;bash scripts/check-minimal.sh;git diff --check。","python3|node|vitest|bash|git","DONE","DONE","DONE","N/A","[""WPROC2-6""]","本轮不部署;无公网 URL 变更;无 OA/企微业务数据写入;提交前门禁按最终 diff 复跑。"
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
2 WPROC2-0 合同建档与边界冻结 建立 WPROC2 开发流程自动化门禁合同;本轮只把 WPROC1 文档规则升级为可执行 QA-only process gate,不部署、不写 OA/企微数据、不实现 WAPC2F 业务 runner。 1) CSV 校验通过;2) 范围限定 Issue CSV、QA 脚本、单测、最小门禁接入和事实源回写;3) 不新增公开业务 API、Prisma schema、前端页面或 feature flag;4) 不调用企微写接口。 受影响流程:开发流程治理;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_11-15-10-process-gate-automation-v1.csv。 python3|manual DONE DONE DONE issues/2026-05-19_11-15-10-process-gate-automation-v1.csv [] 回滚路径:撤回 WPROC2 Issue、check-process-contract 脚本、测试、check-minimal 接入和事实源回写;本轮无数据库、部署、远端配置或企微写入;已通过 CSV 校验。
3 WPROC2-1 新增流程门禁 CLI 新增 QA-only CLI scripts/qa/check-process-contract.mjs,支持 --baseline 和 --issue <csv> --profile <profile> --json,首批 profile 为 general、wecom、wecom-approval-fixture、docs-only。 1) CLI 只读,不修改仓库或远端;2) --baseline 检查核心事实源、WPROC1/WPROC2 口径和 WAPC2F 合同;3) 单 Issue 检查输出 PASS/FAIL、errors、warnings 和 checks;4) 支持 CommonJS/Vitest 通过动态 import 复用导出函数。 受影响流程:本地/CI 流程门禁;验证步骤:node --check scripts/qa/check-process-contract.mjs;node scripts/qa/check-process-contract.mjs --baseline --json。 node DONE DONE DONE scripts/qa/check-process-contract.mjs ["WPROC2-0"] 脚本不得打印 Secret、token、完整 userid、完整 template_id、完整 sp_no 或原始 payload;仅输出规则命中摘要;node --check 与 baseline JSON 均通过。
4 WPROC2-2 固化合同规则检查 在 process gate 中固化 CSV 必填列、状态值、Dependencies JSON、Test_Method 业务流程步骤、回滚/清理说明、事实源读取和缺配置分类检查。 1) 合法 WAPC2F 合同通过 wecom-approval-fixture profile;2) 缺 Dependencies JSON、缺业务流程 Test_Method、缺回滚/清理说明或缺配置分类时失败;3) docs-only profile 不误判为企微写入合同。 受影响流程:Issue CSV 质量门禁;验证步骤:node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json;focused vitest。 node|vitest DONE DONE DONE scripts/qa/check-process-contract.mjs|server/tests/unit/scripts/check-process-contract.test.js ["WPROC2-1"] 规则按当前 WPROC1/WAPC2F 口径实现;后续 profile 扩展另建 Issue;WAPC2F profile 与 focused vitest 均通过。
5 WPROC2-3 固化企微审批高风险检查 为 wecom-approval-fixture profile 增加 Secret 固定、无 fallback、dry-run 默认、live 双开关、非自审链路、WAPC2F 阶段顺序和脱敏输出检查。 1) 必须命中 WECOM_AGENT_SECRET、WECOM_APPROVAL_FIXTURE_WRITE=1、dry-run、SMOKE002、SMOKE101、禁止自审;2) 不允许默认 wangshunli 自审链;3) 必须命中 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG;4) 必须声明不输出手机号、邮箱、token、secret、完整 userid、完整 template_id、完整 sp_no 或原始 payload。 受影响流程:企微审批 POC 样件生成前置门禁;验证步骤:cd server && npx vitest run tests/unit/scripts/check-process-contract.test.js --reporter=verbose。 vitest|node DONE DONE DONE scripts/qa/check-process-contract.mjs|server/tests/unit/scripts/check-process-contract.test.js ["WPROC2-2"] 该门禁只检查合同和事实源,不创建模板、不提交审批单、不访问公网企微、不写企微数据,因此无需清理;focused vitest 8 项通过。
6 WPROC2-4 接入最小门禁 在 scripts/check-minimal.sh 增加 process gate baseline 检查,使 ci-minimal 通过既有入口自动执行流程门禁;不单独修改 GitHub workflow。 1) scripts/check-minimal.sh 包含 node scripts/qa/check-process-contract.mjs --baseline;2) bash -n scripts/check-minimal.sh 通过;3) bash scripts/check-minimal.sh 通过或真实记录环境阻断。 受影响流程:本地最小门禁和 ci-minimal;验证步骤:bash -n scripts/check-minimal.sh;bash scripts/check-minimal.sh。 bash|node DONE DONE DONE scripts/check-minimal.sh ["WPROC2-3"] bash -n scripts/check-minimal.sh 与 bash scripts/check-minimal.sh 已通过;完整最小门禁包含 process gate、Prisma、后端静态、前端 typecheck/build 和 feature matrix。
7 WPROC2-5 更新 WAPC2F 合同前置说明 修正 WAPC2F 合同说明,不通过跨 CSV Dependencies 强绑;用 Notes 和 Test_Method 声明 WPROC2 baseline gate 是实施前置,并补充 process gate 命令。 1) WAPC2F 不新增跨 CSV Dependencies;2) WAPC2F Test_Method 包含 check-process-contract;3) Notes 说明 WPROC2 是实施前置;4) WAPC2F CSV 校验仍通过。 受影响流程:WAPC2F 进入实现前检查;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv;node scripts/qa/check-process-contract.mjs --issue issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv --profile wecom-approval-fixture --json。 python3|node DONE DONE DONE issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv ["WPROC2-4"] 不回填 WAPC2F DONE;WAPC2F 仍是后续实现合同;WAPC2F CSV 校验和 profile gate 均通过。
8 WPROC2-6 回写事实源和 skill 更新开发交付规约、测试门禁、企微路线图、API 能力目录、文档索引、事实源矩阵和项目 skill,登记 WPROC2 和 check-process-contract。 1) 事实源说明 WPROC2 是 WAPC2F 前置 process gate;2) skill 要求企微高风险开发先跑 process gate;3) 文档审计和 skill 校验通过。 受影响流程:后续 agent 读取顺序和流程执行;验证步骤:node scripts/qa/audit-docs.mjs --check-registry;python3 /home/shunli/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/hyb-oa-delivery;rg -n 'WPROC2|check-process-contract|process gate' docs .agents/skills/hyb-oa-delivery/SKILL.md。 node|python3|rg DONE DONE DONE docs/开发交付与变更管理规约.md|docs/测试规约与回归门禁.md|docs/企微优先开发路线图.md|docs/企微API能力目录.md|docs/文档索引.md|docs/文档事实源状态矩阵.md|.agents/skills/hyb-oa-delivery/SKILL.md ["WPROC2-5"] 不新建独立流程文档;优先更新现有事实源;文档审计通过但保留既有 24 个未登记文档 warning,skill 校验通过。
9 WPROC2-7 门禁验证、状态回填和提交 执行 WPROC2 Test Plan,按真实结果回填 WPROC2 状态并中文提交。 1) WPROC2/WAPC2F CSV 校验通过;2) node --check、process gate 自测、focused vitest、文档审计、skill 校验、关键词核验、git diff --check 和 check-minimal 通过或真实记录 SKIP/阻断;3) Issue 状态回填真实;4) 中文 commit 引用 WPROC2。 受影响流程:WPROC2 交付闭环;验证步骤:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-19_11-15-10-process-gate-automation-v1.csv;node --check scripts/qa/check-process-contract.mjs;node scripts/qa/check-process-contract.mjs --baseline --json;cd server && npx vitest run tests/unit/scripts/check-process-contract.test.js --reporter=verbose;bash scripts/check-minimal.sh;git diff --check。 python3|node|vitest|bash|git DONE DONE DONE N/A ["WPROC2-6"] 本轮不部署;无公网 URL 变更;无 OA/企微业务数据写入;提交前门禁按最终 diff 复跑。
+11 -4
查看文件
@@ -3,14 +3,21 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
echo "=== [1/4] Server Prisma Validate ===" echo "=== [1/5] Process Contract Gate ==="
(
cd "$ROOT_DIR"
node scripts/qa/check-process-contract.mjs --baseline
)
echo ""
echo "=== [2/5] Server Prisma Validate ==="
( (
cd "$ROOT_DIR/server" cd "$ROOT_DIR/server"
npm run prisma:validate npm run prisma:validate
) )
echo "" echo ""
echo "=== [2/4] Server Static Checks ===" echo "=== [3/5] Server Static Checks ==="
( (
cd "$ROOT_DIR/server" cd "$ROOT_DIR/server"
node --check src/routes/reimbursements.js node --check src/routes/reimbursements.js
@@ -62,7 +69,7 @@ echo "=== [2/4] Server Static Checks ==="
) )
echo "" echo ""
echo "=== [3/4] Client Typecheck + Build ===" echo "=== [4/5] Client Typecheck + Build ==="
( (
cd "$ROOT_DIR/client" cd "$ROOT_DIR/client"
npm run typecheck npm run typecheck
@@ -70,7 +77,7 @@ echo "=== [3/4] Client Typecheck + Build ==="
) )
echo "" echo ""
echo "=== [4/4] Feature Matrix Consistency ===" echo "=== [5/5] Feature Matrix Consistency ==="
( (
cd "$ROOT_DIR" cd "$ROOT_DIR"
python3 scripts/validate-feature-matrix.py python3 scripts/validate-feature-matrix.py
+480
查看文件
@@ -0,0 +1,480 @@
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, "../..");
const REQUIRED_COLUMNS = [
"ID",
"Title",
"Description",
"Acceptance",
"Test_Method",
"Tools",
"Dev_Status",
"Review1_Status",
"Regression_Status",
"Files",
"Dependencies",
"Notes",
];
const VALID_STATUSES = new Set(["TODO", "DOING", "DONE"]);
const VALID_PROFILES = new Set(["general", "wecom", "wecom-approval-fixture", "docs-only"]);
const WAPC2F_ISSUE = "issues/2026-05-19_10-24-43-wecom-approval-fixture-auto-generate-v1.csv";
const WPROC2_ISSUE = "issues/2026-05-19_11-15-10-process-gate-automation-v1.csv";
function usage() {
return `Usage:
node scripts/qa/check-process-contract.mjs --baseline [--json]
node scripts/qa/check-process-contract.mjs --issue <csv> --profile <general|wecom|wecom-approval-fixture|docs-only> [--json]
This QA-only process gate is read-only. It validates Issue CSV contracts and
current WeCom process facts without printing secrets or raw external payloads.`;
}
export function parseArgs(argv = process.argv.slice(2)) {
const options = {
baseline: false,
issue: "",
profile: "general",
json: false,
help: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === "--baseline") {
options.baseline = true;
} else if (arg === "--issue") {
options.issue = argv[index + 1] ?? "";
index += 1;
} else if (arg.startsWith("--issue=")) {
options.issue = arg.slice("--issue=".length);
} else if (arg === "--profile") {
options.profile = argv[index + 1] ?? "";
index += 1;
} else if (arg.startsWith("--profile=")) {
options.profile = arg.slice("--profile=".length);
} else if (arg === "--json") {
options.json = true;
} else if (arg === "--help" || arg === "-h") {
options.help = true;
} else {
throw new Error(`unknown argument: ${arg}`);
}
}
if (!options.help && !options.baseline && !options.issue) {
throw new Error("either --baseline or --issue <csv> is required");
}
if (options.baseline && options.issue) {
throw new Error("--baseline and --issue cannot be used together");
}
if (!VALID_PROFILES.has(options.profile)) {
throw new Error(`unsupported profile: ${options.profile}`);
}
return options;
}
function createResult(scope, profile = "general") {
return {
status: "PASS",
scope,
profile,
checks: [],
errors: [],
warnings: [],
};
}
function addCheck(result, name, status, detail = "") {
result.checks.push({ name, status, detail });
}
function addError(result, code, message) {
result.errors.push({ code, message });
result.status = "FAIL";
}
function addWarning(result, code, message) {
result.warnings.push({ code, message });
}
function splitCsvLine(line) {
const cells = [];
let current = "";
let quoted = false;
for (let index = 0; index < line.length; index += 1) {
const char = line[index];
const next = line[index + 1];
if (quoted && char === "\"" && next === "\"") {
current += "\"";
index += 1;
continue;
}
if (char === "\"") {
quoted = !quoted;
continue;
}
if (!quoted && char === ",") {
cells.push(current);
current = "";
continue;
}
current += char;
}
cells.push(current);
return cells;
}
export function parseIssueCsv(source) {
const lines = source.split(/\r?\n/).filter((line) => line.trim());
if (lines.length === 0) {
return { header: [], rows: [] };
}
const header = splitCsvLine(lines[0]).map((cell) => cell.trim());
const rows = lines.slice(1).map((line, lineIndex) => {
const cells = splitCsvLine(line);
const row = Object.fromEntries(header.map((key, index) => [key, cells[index] ?? ""]));
row.__line = lineIndex + 2;
return row;
});
return { header, rows };
}
function includesAllColumns(header) {
return REQUIRED_COLUMNS.every((column) => header.includes(column));
}
function textOfRows(rows) {
return rows.map((row) => REQUIRED_COLUMNS.map((column) => row[column] ?? "").join(" ")).join("\n");
}
function normalize(value) {
return String(value ?? "").toLowerCase();
}
function hasTerm(text, term) {
return normalize(text).includes(normalize(term));
}
function hasAny(text, terms) {
return terms.some((term) => hasTerm(text, term));
}
function hasAll(text, terms) {
return terms.every((term) => hasTerm(text, term));
}
function validateBasicCsv({ result, header, rows }) {
if (!includesAllColumns(header)) {
const missing = REQUIRED_COLUMNS.filter((column) => !header.includes(column));
addError(result, "csv.required_columns", `missing required columns: ${missing.join(", ")}`);
} else {
addCheck(result, "csv.required_columns", "PASS", "all required columns exist");
}
if (rows.length === 0) {
addError(result, "csv.rows", "Issue CSV has no rows");
return;
}
addCheck(result, "csv.rows", "PASS", `${rows.length} rows`);
const ids = new Set();
for (const row of rows) {
const rowId = row.ID || `line ${row.__line}`;
if (!row.ID) {
addError(result, "csv.id", `missing ID at line ${row.__line}`);
} else if (ids.has(row.ID)) {
addError(result, "csv.id", `duplicate ID: ${row.ID}`);
} else {
ids.add(row.ID);
}
for (const statusField of ["Dev_Status", "Review1_Status", "Regression_Status"]) {
if (!VALID_STATUSES.has(row[statusField])) {
addError(result, "csv.status", `${rowId} has invalid ${statusField}: ${row[statusField] || "<empty>"}`);
}
}
try {
const deps = JSON.parse(row.Dependencies || "");
if (!Array.isArray(deps) || deps.some((item) => typeof item !== "string")) {
addError(result, "csv.dependencies", `${rowId} Dependencies must be a JSON string array`);
} else {
for (const dep of deps) {
if (!ids.has(dep) && !rows.some((candidate) => candidate.ID === dep)) {
addError(result, "csv.dependencies", `${rowId} depends on unknown row: ${dep}`);
}
}
}
} catch (error) {
addError(result, "csv.dependencies", `${rowId} Dependencies is not valid JSON array`);
}
const testMethod = row.Test_Method || "";
if (!hasAll(testMethod, ["受影响流程", "验证步骤"])) {
addError(result, "csv.test_method", `${rowId} Test_Method must include affected business flow and reproducible steps`);
}
if (!row.Files || !row.Files.trim()) {
addError(result, "csv.files", `${rowId} Files must not be empty`);
}
if (!row.Notes || !row.Notes.trim()) {
addError(result, "csv.notes", `${rowId} Notes must not be empty`);
}
const rowText = REQUIRED_COLUMNS.map((column) => row[column] ?? "").join(" ");
const hasRiskyWriteMarker = /(--live|WECOM_APPROVAL_FIXTURE_WRITE|live 写入|真实写|写企微|企微后台|applyevent|create_template|submit-test-approvals|部署|生产)/i.test(rowText);
if (hasRiskyWriteMarker && !hasAny(rowText, ["回滚", "清理", "隐藏", "停用", "保留审计", "不部署", "不写", "不得修改正式模板"])) {
addError(result, "csv.rollback", `${rowId} mentions live/write/public risk but lacks rollback or cleanup wording`);
}
}
if (!result.errors.some((item) => item.code.startsWith("csv."))) {
addCheck(result, "csv.format", "PASS", "IDs, statuses, dependencies, Test_Method, Files and Notes are valid");
}
}
function validateDocsOnly({ result, rows }) {
const text = textOfRows(rows);
if (hasAny(text, ["不改业务代码", "docs-only", "contract-only", "文档"])) {
addCheck(result, "profile.docs_only_scope", "PASS", "docs-only or contract-only boundary declared");
} else {
addWarning(result, "profile.docs_only_scope", "docs-only profile did not find explicit docs-only wording");
}
}
function validateWecom({ result, rows }) {
const text = textOfRows(rows);
if (!hasAny(text, ["WECOM_", "Secret", "企微", "企业微信"])) {
addError(result, "wecom.scope", "WeCom profile must mention WeCom scope and Secret/API source");
}
if (!hasAny(text, ["固定 WECOM", "固定 `WECOM", "Secret 来源", "Secret 矩阵"])) {
addError(result, "wecom.secret_source", "WeCom contract must fix its Secret source");
}
if (!hasAny(text, ["不尝试其他 Secret", "无 fallback", "不得靠多个 Secret", "不允许运行时猜 Secret", "不再用运行时 Secret fallback"])) {
addError(result, "wecom.secret_source", "WeCom contract must fix Secret source and disallow runtime Secret guessing");
}
if (!hasAny(text, ["NEEDS_CONFIG", "SKIP/BLOCKED_BY_EXTERNAL_CONFIG", "BLOCKED_BY_EXTERNAL_CONFIG"])) {
addError(result, "wecom.external_config", "WeCom contract must classify missing config or permission as NEEDS_CONFIG or SKIP/BLOCKED_BY_EXTERNAL_CONFIG");
}
if (!hasAny(text, ["只读", "dry-run", "默认 dry-run", "不写"])) {
addError(result, "wecom.read_or_dry_run", "WeCom contract must default to read-only or dry-run");
}
if (!result.errors.some((item) => item.code.startsWith("wecom."))) {
addCheck(result, "profile.wecom", "PASS", "Secret, external config, and read/dry-run gates are declared");
}
}
function validateWecomApprovalFixture({ result, rows }) {
validateWecom({ result, rows });
const text = textOfRows(rows);
const requiredTerms = [
"WAPC2F",
"OA-POC",
"WECOM_AGENT_SECRET",
"WECOM_APPROVAL_FIXTURE_WRITE=1",
"--live",
"--create-templates",
"--submit-test-approvals",
"dry-run",
"SMOKE002",
"SMOKE101",
"自审",
"BLOCKED_BY_EXTERNAL_CONFIG",
"NEEDS_CONFIG",
];
for (const term of requiredTerms) {
if (!hasTerm(text, term)) {
addError(result, "fixture.required_term", `WAPC2F contract must mention ${term}`);
}
}
if (hasAny(text, ["默认 wangshunli", "申请人 wangshunli", "审批人 wangshunli", "wangshunli -> wangshunli"])) {
addError(result, "fixture.self_approval", "WAPC2F must not default to wangshunli self-approval");
}
if (!hasAny(text, ["不是同一 OA 员工", "不是同一企微 userid", "禁止自审", "自审硬阻断"])) {
addError(result, "fixture.non_self_approval", "WAPC2F must explicitly block self-approval by OA employee and WeCom userid");
}
const routePattern = /WAPC2F[\s\S]{0,240}WCBK1[\s\S]{0,240}WACP3[\s\S]{0,240}WADM1/;
if (!routePattern.test(text)) {
addError(result, "fixture.route_order", "WAPC2F route must show WAPC2F before WCBK1, WACP3 and WADM1");
}
const privacyTerms = [
"手机号",
"邮箱",
"token",
"secret",
"完整模板 ID",
"完整 sp_no",
"完整 userid",
"原始 payload",
];
for (const term of privacyTerms) {
if (!hasTerm(text, term)) {
addError(result, "fixture.privacy", `WAPC2F contract must declare no ${term} in reports`);
}
}
if (!result.errors.some((item) => item.code.startsWith("fixture."))) {
addCheck(result, "profile.wecom_approval_fixture", "PASS", "WAPC2F non-self, write switch, route and privacy gates are declared");
}
}
export function evaluateIssueContract({ csvText, issuePath = "", profile = "general" }) {
const result = createResult(issuePath || "inline issue", profile);
const { header, rows } = parseIssueCsv(csvText);
validateBasicCsv({ result, header, rows });
if (profile === "docs-only") {
validateDocsOnly({ result, rows });
} else if (profile === "wecom") {
validateWecom({ result, rows });
} else if (profile === "wecom-approval-fixture") {
validateWecomApprovalFixture({ result, rows });
}
return result;
}
function readRepoText(relativePath, root = repoRoot) {
return fs.readFileSync(path.join(root, relativePath), "utf8");
}
function pathExists(relativePath, root = repoRoot) {
return fs.existsSync(path.join(root, relativePath));
}
function mergeChild(parent, child, label) {
parent.checks.push({
name: label,
status: child.status,
detail: `${child.errors.length} errors, ${child.warnings.length} warnings`,
});
for (const error of child.errors) {
addError(parent, `${label}.${error.code}`, error.message);
}
for (const warning of child.warnings) {
addWarning(parent, `${label}.${warning.code}`, warning.message);
}
}
export function evaluateBaseline({ root = repoRoot } = {}) {
const result = createResult("baseline", "baseline");
const requiredPaths = [
"docs/开发交付与变更管理规约.md",
"docs/测试规约与回归门禁.md",
"docs/企微优先开发路线图.md",
"docs/企微API能力目录.md",
"docs/文档索引.md",
"docs/文档事实源状态矩阵.md",
".agents/skills/hyb-oa-delivery/SKILL.md",
WAPC2F_ISSUE,
];
for (const relativePath of requiredPaths) {
if (!pathExists(relativePath, root)) {
addError(result, "baseline.required_path", `missing required path: ${relativePath}`);
}
}
if (!result.errors.some((item) => item.code === "baseline.required_path")) {
addCheck(result, "baseline.required_paths", "PASS", `${requiredPaths.length} required paths exist`);
}
const factPaths = requiredPaths.filter((item) => item !== WAPC2F_ISSUE);
const factText = factPaths
.filter((relativePath) => pathExists(relativePath, root))
.map((relativePath) => readRepoText(relativePath, root))
.join("\n");
for (const term of ["WPROC2", "check-process-contract", "process gate", "Definition of Ready", "Definition of Done", "WAPC2F"]) {
if (!hasTerm(factText, term)) {
addError(result, "baseline.fact_source", `core fact sources must mention ${term}`);
}
}
if (!result.errors.some((item) => item.code === "baseline.fact_source")) {
addCheck(result, "baseline.fact_sources", "PASS", "WPROC2 process gate terms are in core fact sources");
}
if (pathExists(WAPC2F_ISSUE, root)) {
const wapc2f = evaluateIssueContract({
csvText: readRepoText(WAPC2F_ISSUE, root),
issuePath: WAPC2F_ISSUE,
profile: "wecom-approval-fixture",
});
mergeChild(result, wapc2f, "wapc2f");
}
if (pathExists(WPROC2_ISSUE, root)) {
const wproc2 = evaluateIssueContract({
csvText: readRepoText(WPROC2_ISSUE, root),
issuePath: WPROC2_ISSUE,
profile: "general",
});
mergeChild(result, wproc2, "wproc2");
}
return result;
}
function formatTextResult(result) {
const lines = [`process-contract: status=${result.status} scope=${result.scope} profile=${result.profile}`];
for (const check of result.checks) {
lines.push(`- ${check.status} ${check.name}${check.detail ? `: ${check.detail}` : ""}`);
}
for (const warning of result.warnings) {
lines.push(`warning ${warning.code}: ${warning.message}`);
}
for (const error of result.errors) {
lines.push(`error ${error.code}: ${error.message}`);
}
return lines.join("\n");
}
async function main() {
let options;
try {
options = parseArgs();
} catch (error) {
console.error(error.message);
console.error(usage());
process.exit(2);
}
if (options.help) {
console.log(usage());
return;
}
const result = options.baseline
? evaluateBaseline()
: evaluateIssueContract({
csvText: readRepoText(options.issue),
issuePath: options.issue,
profile: options.profile,
});
if (options.json) {
console.log(JSON.stringify(result, null, 2));
} else {
console.log(formatTextResult(result));
}
if (result.status !== "PASS") {
process.exit(1);
}
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
main().catch((error) => {
console.error(error?.stack || error?.message || String(error));
process.exit(1);
});
}
@@ -0,0 +1,143 @@
const path = require("node:path");
const { pathToFileURL } = require("node:url");
let gate;
function csvEscape(value) {
return `"${String(value).replace(/"/g, "\"\"")}"`;
}
function buildCsv(rows) {
const header = [
"ID",
"Title",
"Description",
"Acceptance",
"Test_Method",
"Tools",
"Dev_Status",
"Review1_Status",
"Regression_Status",
"Files",
"Dependencies",
"Notes",
];
return [
header.join(","),
...rows.map((row) => header.map((column) => csvEscape(row[column] ?? "")).join(",")),
].join("\n");
}
function validFixtureRow(overrides = {}) {
return {
ID: "WAPC2F-0",
Title: "合法企微审批样件合同",
Description: "WAPC2F 自动生成 OA-POC 请假/补卡测试模板;路线:WAPC2F -> WCBK1 -> WACP3 -> WADM1 -> wecom_attendance_approval_mirror_v1。",
Acceptance: "固定 WECOM_AGENT_SECRET;不尝试其他 Secret;默认 dry-run;live 必须 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;申请人 SMOKE002 -> 审批人 SMOKE101;禁止自审,不是同一 OA 员工,不是同一企微 userid;缺配置记录 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。",
Test_Method: "受影响流程:WAPC2 缺配置 -> 自动生成 POC 样件 -> WAPC2 自动复跑;验证步骤:node scripts/qa/check-process-contract.mjs --issue fixture.csv --profile wecom-approval-fixture --json。",
Tools: "node|vitest",
Dev_Status: "TODO",
Review1_Status: "TODO",
Regression_Status: "TODO",
Files: "scripts/qa/check-wecom-approval-fixtures.js|server/package.json",
Dependencies: "[]",
Notes: "回滚路径:撤回代码;企微后台 OA-POC 测试模板或测试单如已生成需隐藏、停用或保留审计;报告不得输出手机号、邮箱、token、secret、完整模板 ID、完整 sp_no、完整 userid 或原始 payload;无 fallback。",
...overrides,
};
}
function evaluate(rows, profile = "wecom-approval-fixture") {
return gate.evaluateIssueContract({
csvText: buildCsv(rows),
issuePath: "fixture.csv",
profile,
});
}
function errorCodes(result) {
return result.errors.map((item) => item.code);
}
describe("check-process-contract", () => {
beforeAll(async () => {
const scriptPath = path.resolve(__dirname, "../../../../scripts/qa/check-process-contract.mjs");
gate = await import(pathToFileURL(scriptPath).href);
});
it("passes a valid WAPC2F fixture contract", () => {
const result = evaluate([validFixtureRow()]);
expect(result.status).toBe("PASS");
expect(errorCodes(result)).toEqual([]);
expect(result.checks.some((item) => item.name === "profile.wecom_approval_fixture")).toBe(true);
});
it("fails when Dependencies is not a JSON array", () => {
const result = evaluate([validFixtureRow({ Dependencies: "WAPC2F-0" })]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("csv.dependencies");
});
it("fails when Test_Method lacks affected business flow wording", () => {
const result = evaluate([validFixtureRow({ Test_Method: "验证步骤:node scripts/qa/check-process-contract.mjs --baseline。" })]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("csv.test_method");
});
it("fails self-approval defaults", () => {
const result = evaluate([
validFixtureRow({
Acceptance: "默认 wangshunli -> wangshunli;固定 WECOM_AGENT_SECRET;默认 dry-run;live 必须 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;缺配置记录 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。",
}),
]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("fixture.self_approval");
});
it("fails when live write switch is missing", () => {
const row = validFixtureRow({
Acceptance: "固定 WECOM_AGENT_SECRET;不尝试其他 Secret;默认 dry-run;live 必须 --live --create-templates --submit-test-approvals;申请人 SMOKE002 -> 审批人 SMOKE101;禁止自审;缺配置记录 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。",
});
const result = evaluate([row]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("fixture.required_term");
expect(result.errors.some((item) => item.message.includes("WECOM_APPROVAL_FIXTURE_WRITE=1"))).toBe(true);
});
it("fails when Secret fallback is not explicitly forbidden", () => {
const row = validFixtureRow({
Acceptance: "固定 WECOM_AGENT_SECRET;默认 dry-run;live 必须 --live --create-templates --submit-test-approvals 且 WECOM_APPROVAL_FIXTURE_WRITE=1;申请人 SMOKE002 -> 审批人 SMOKE101;禁止自审;缺配置记录 NEEDS_CONFIG 或 SKIP/BLOCKED_BY_EXTERNAL_CONFIG。",
Notes: "回滚路径:撤回代码;企微后台 OA-POC 测试模板或测试单如已生成需隐藏、停用或保留审计;报告不得输出手机号、邮箱、token、secret、完整模板 ID、完整 sp_no、完整 userid 或原始 payload。",
});
const result = evaluate([row]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("wecom.secret_source");
});
it("fails when privacy report boundary is incomplete", () => {
const row = validFixtureRow({
Notes: "回滚路径:撤回代码;企微后台 OA-POC 测试模板或测试单如已生成需隐藏、停用或保留审计;报告不得输出手机号、邮箱、token、secret、完整模板 ID、完整 userid 或原始 payload;无 fallback。",
});
const result = evaluate([row]);
expect(result.status).toBe("FAIL");
expect(errorCodes(result)).toContain("fixture.privacy");
});
it("parses CLI options for baseline and issue profiles", () => {
expect(gate.parseArgs(["--baseline", "--json"])).toMatchObject({
baseline: true,
json: true,
});
expect(gate.parseArgs(["--issue", "a.csv", "--profile", "wecom"])).toMatchObject({
issue: "a.csv",
profile: "wecom",
});
expect(() => gate.parseArgs(["--issue", "a.csv", "--profile", "unknown"])).toThrow(/unsupported profile/);
});
});