## 背景 用户指令:「先将 codex 的任务一并改为 workbuddy 的任务」。 Codex 已不再运行,当前由 WorkBuddy 承担开发执行,文档署名需同步。 ## 判定规则(用大小写精确区分) | 类别 | 写法 | 处置 | |---|---|---| | 工具署名 | 大写 Codex | → WorkBuddy | | 分支名 | codex/ui-v11-fidelity | → workbuddy-ui-v11-fidelity(去斜杠,规避本仓库 ref 清理) | | 已删除文件的历史路径 | 小写 2026-09-11-codex-baseline-cleanup* | 保持原样(记录真实曾存在的文件名,改了即失真) | 结果:26 个文件、126 处署名替换。残留小写 codex 仅 8 处,全部是历史路径。 ## 文件重命名(git mv,保留历史) - Codex开发执行总指令、项目规则与任务拆解.md → WorkBuddy 同名 - Codex首轮启动提示词 + Phase 01~Phase 26 Jira级任务清单 + 每阶段验收条件.md → WorkBuddy 同名 - docs/善缘丹阳 V1.1 Codex 开发执行计划修订版.md → docs/善缘丹阳 V1.1 WorkBuddy 开发执行计划修订版.md - docs/善缘丹阳 V1.1 Codex-Jira 最终开发任务增量清单.md → docs/善缘丹阳 V1.1 WorkBuddy-Jira 最终开发任务增量清单.md - docs/善缘丹阳 V1.1 Codex最终主启动提示词(整合版).md → docs/善缘丹阳 V1.1 WorkBuddy最终主启动提示词(整合版).md 引用已同步:AGENTS.md 6 处、AGENTS_SUMMARY.md、以及 4 份计划/规格文档。 ## AGENTS.md 两处特别处理 - 「git config user.name = Codex」一句改为不点名工具的表述 - 「feature/ fix/ codex/ ui/ 前缀」示例去掉 codex/ ## 有意未改动 - ui-tests/ui-document-baseline-contracts.mjs 的废弃清单仍列 codex-baseline-cleanup* 那是「必须不存在」的断言目标,改了会让哨兵失去意义 - 仓库 git config user.name 仍是 Codex —— 未擅自改动环境身份。 如需彻底交接:git config user.name WorkBuddy && git config user.email workbuddy@local 验证:UI 契约门禁 13/13;AGENTS.md 零 Codex 残留;5 个新文件名与全部引用一致
18 KiB
善缘丹阳 V1.1 Recovery Implementation Plan
已被取代: 本计划使用 R0~R8 恢复阶段,与客户 V1.1 增量基线不一致。当前唯一修复计划为 善缘丹阳 V1.1 客户需求基线增量开发与修复计划.md。本文件仅保留为审计历史,不再作为执行依据。
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 将当前“模块文件已存在但核心链路不可验证”的 V1.1 恢复为满足业务不变量、可构建、可回归、可人工验收的发布候选版本。
Architecture: 保持 Java 21 + Spring Boot 模块化单体、PostgreSQL、Redis、私有对象存储、Vue 3 管理后台和微信原生小程序。按“安全底座 → 测试底座 → 业务纵切 → 前端闭环 → UAT → RC”恢复,不引入微服务和新基础设施。
Tech Stack: Java 21、Spring Boot 3.x、MyBatis-Plus、Flyway、PostgreSQL、Vue 3、TypeScript、Vite、微信小程序原生、Docker Compose。
Spec: AGENTS.md、docs/善缘丹阳 V1.1 页面级功能清单与交互流程修订版.md、docs/善缘丹阳 V1.1 数据库与API增量设计.md、docs/superpowers/specs/2026-09-13-reference-driven-dual-client-ui-redesign-design.md、docs/善缘丹阳 V1.1 WorkBuddy-Jira 最终开发任务增量清单.md。
Global Constraints
- 用户永久免费,禁止 VIP、会员、金币和用户付费功能。
- Required 条件是 Hard Constraint,任何推荐路径不得自动放宽。
- Mutual Match 后才能聊天;Block 优先级最高。
- 活动互选必须经过双方分别确认后才创建或复用 Match/Conversation。
- Counselor 只能访问 Assigned Service;Content Editor 零用户婚恋数据权限。
- PostgreSQL 是 Source of Truth;前端 Store 和 Redis 不得覆盖数据库事实。
- 首页结构与 8 个核心入口顺序固定;Banner 仅允许内部目标类型。
- 默认简体中文、Asia/Shanghai、日期
YYYY-MM-DD、金额人民币元。 - 每个阶段结束必须产生真实测试输出和 Completion Report,并暂停等待审核。
执行策略
推荐采用“恢复式纵向切片”:先建立不可绕过的权限与测试门禁,再按首页、咨询/预约、活动互选、内容/服务站逐条打通后端—小程序—后台—测试。不要继续按原 Phase 编号批量补文件,也不要先重做视觉稿。
估算以 1 名全栈工程师持续投入为前提,仅用于排序:恢复到可进入正式 UAT 约需 20~30 个工程日;真实内容、第三方认证、微信审核和生产证书不计入。
Phase R0:冻结错误基线并恢复可追溯性
Files:
- Modify:
docs/STATUS.md - Modify:
docs/JIRA_BACKLOG.md - Create:
docs/RECOVERY_ISSUE_TRACKER.md - Verify:
.git/或新的正式 Git 工作区
Produces: 单一版本号、真实状态矩阵、P0/P1 缺陷清单、可审计提交历史。
- 确认正式代码仓库位置;若当前目录是拷贝,迁回正式仓库后再修改源码。
- 对当前目录做不可变备份或建立恢复分支,记录当前 V027 数据库版本。
- 将 V1.1 状态改为
RECOVERY,撤销“100% 完成、可上线”的结论。 - 把旧 Completion Report 标为“历史记录,需按恢复门禁复验”。
- 统一 Backend、Admin、Miniapp、
VERSION和文档中的版本号为同一个1.1.0-recovery。 - 建立缺陷编号:安全 P0、功能 P1、体验 P2;每项写清复现步骤、影响不变量、验收测试。
Exit Gate: git status 可用;版本唯一;状态文档不存在同一模块既完成又未完成的冲突。
Phase R1:建立不可伪造的质量门禁
Files:
- Modify:
.github/workflows/ci.yml - Modify:
backend/Dockerfile - Modify:
admin-web/package.json - Modify:
miniapp/package.json - Modify:
miniapp/tsconfig.json - Create:
pytest.ini - Create:
tests/e2e/conftest.py - Replace:
tests/e2e/*_test.py中的空壳测试
Produces: 一条失败即阻断的 CI;后端、后台、小程序、迁移、E2E 均有真实门禁。
- 先写一个 CI 自检用例,证明空
pass、未知 pytest mark 和缺失 fixture 会使流水线失败。 - 为 E2E 建立隔离测试数据、用户令牌与操作员令牌 fixture,不再用管理员令牌代替用户。
- 把
run_v11_tests.py拆成可独立运行、可清理数据、每个结果都有断言的测试。 - 将 INV-011~020 改为调用真实 Service/Controller/Database 的行为测试,删除“常量存在即不变量成立”的判定方式。
- 后端镜像构建执行
mvn verify -B,移除maven.test.skip=true。 - Admin CI 顺序固定为
npm ci、npm run type-check、无修复模式 lint、npm run build。 - Miniapp CI 执行
npm ci、npm run type-check,并校验页面注册、WXML 事件处理器和目标路径存在。 - Migration Job 使用临时 PostgreSQL 真正执行 Flyway,不再只检查 SQL 文件非空。
Exit Gate: 全新环境可一次运行全部门禁;故意破坏任一不变量时相应测试会失败。
Phase R2:修复认证、RBAC、DataScope 与敏感数据边界
Files:
- Modify:
backend/src/main/java/com/danyang/match/platform/shared/filter/JwtAuthFilter.java - Replace:
backend/src/main/java/com/danyang/match/platform/shared/filter/PermissionFilter.java - Modify:
backend/src/main/java/com/danyang/match/platform/shared/config/SecurityConfig.java - Modify:
backend/src/main/java/com/danyang/match/platform/counseling/controller/CounselingController.java - Modify:
backend/src/main/java/com/danyang/match/platform/counseling/service/CounselingServiceApp.java - Modify:
backend/src/main/java/com/danyang/match/platform/service_appointment/controller/ServiceAppointmentController.java - Modify:
backend/src/main/java/com/danyang/match/platform/service_appointment/service/ServiceAppointmentService.java - Test:
backend/src/test/java/com/danyang/match/platform/invariants/PermissionMatrixTest.java - Test:
tests/e2e/counseling_permission_test.py - Test:
tests/e2e/service_station_permission_test.py - Test:
tests/e2e/organization_isolation_test.py
Produces: 用户主体与操作员主体分离;接口级 Permission + DataScope;敏感字段按角色裁剪。
- 写失败测试:用户令牌调用后台咨询接口返回 403。
- 写失败测试:服务站人员访问全局用户、咨询队列、全局统计返回 403。
- 写失败测试:Counselor A 访问 Counselor B 的咨询详情、跟进和状态变更返回 403。
- 写失败测试:Matchmaker 与普通管理员无法读取咨询正文和 followup 内容。
- 写失败测试:用户 A 读取用户 B 的预约详情返回 404 或 403,且不泄露记录存在性。
- 将 operator API 统一迁到
/api/v1/operator/...,为每组接口映射明确权限码。 - 控制器只从已验证 Principal 取主体,不再各自解析 Authorization Header。
- 只有具备代办权限的操作员可指定
userId,普通用户请求体中的userId被拒绝。 - 在 Service 层实现 Assigned Counselor、Service Station、Organization DataScope,避免只依赖路由过滤。
- 对咨询 DTO 做角色视图裁剪;日志仅记录咨询 ID、风险级别和脱敏标识。
Exit Gate: INV-011、012、013、018、019、020 行为测试全部通过;无低权限角色能通过直接 API 绕过前端菜单。
Phase R3:首页聚合与 Capability 单一事实源
Files:
- Create:
backend/src/main/java/com/danyang/match/platform/capability/service/CapabilityService.java - Modify:
backend/src/main/java/com/danyang/match/platform/home/service/HomeApplicationService.java - Modify:
backend/src/main/java/com/danyang/match/platform/home/dto/HomeDTO.java - Modify:
backend/src/main/java/com/danyang/match/platform/banner/service/HomeBannerService.java - Test:
backend/src/test/java/com/danyang/match/platform/home/HomeApplicationServiceTest.java - Test:
tests/e2e/home_v11_test.py
Produces: GET /api/v1/home 从真实模块聚合数据,入口顺序固定,所有入口由服务端能力控制。
- 写失败测试,精确断言 8 个入口 code、顺序、目标页面和 enabled 状态。
- 写失败测试,Banner 外链目标、过期 Banner、受众不匹配 Banner 均不会返回。
- 写失败测试,未实名、审核中、暂停寻找、成功牵手五类首页状态分别符合文档。
- CapabilityService 统一读取账户、实名、资料审核、本地资格、关系状态和 Feature Flag。
- 用真实身份记录替换
verified=true,用推荐服务替换空列表。 - 从
service_locations、content_articles读取服务站和婚恋课堂内容,移除硬编码业务对象。 - 修正 8 个入口和全部 CTA 到真实、已注册的内部页面。
- 严格输出固定首页顺序:品牌/状态由前端壳展示,数据区依次为 Banner、8 入口、推荐、公益服务、活动、服务站、婚恋课堂、安全提醒。
Exit Gate: 首页 E2E 覆盖 5 种用户状态、Banner 规则、精确入口顺序和所有目标页面;返回数据无阶段占位值。
Phase R4:活动互选二阶段确认闭环
Files:
- Modify:
backend/src/main/java/com/danyang/match/platform/activity_mutual/service/ActivityMutualConsentService.java - Modify:
backend/src/main/java/com/danyang/match/platform/activity_mutual/controller/ActivityMutualConsentController.java - Modify:
backend/src/main/java/com/danyang/match/platform/relationship/service/RelationshipService.java - Modify:
backend/src/main/resources/db/migration/V024__add_activity_mutual_connection_consents.sql的约束策略通过新增迁移实现,禁止改写已应用迁移 - Create:
backend/src/main/resources/db/migration/V028__harden_activity_mutual_consents.sql - Test:
tests/e2e/activity_mutual_consent_test.py - Test:
backend/src/test/java/com/danyang/match/platform/activity_mutual/ActivityMutualConsentServiceTest.java
Produces: Mutual Interest → 双方分别确认 → 原子创建/复用 Match → 创建/复用 Conversation。
- 写失败测试:单向 Interest 对另一方不可见。
- 写失败测试:Mutual Interest 和单方 Confirm 都不会创建 Match/Conversation。
- 写失败测试:双方并发 Confirm 只生成一个结果。
- 写失败测试:已有 active Match 时复用;曾 Unmatch 时创建新 Match Episode。
- 在单事务内锁定 consent pair、重读双方状态、处理幂等键、创建或复用 Match/Conversation。
- 增加规范化 pair 唯一约束和重复请求冲突处理。
- 返回前端所需的
bothConfirmed、matchId、conversationId、reusedExistingMatch。
Exit Gate: INV-014、015 及“已有 Match 复用/曾 Unmatch 新建”全部在并发测试中通过。
Phase R5:小程序改为单一 TypeScript 运行源并补齐页面闭环
Files:
- Modify:
project.config.json - Modify:
miniapp/project.config.json - Modify:
miniapp/tsconfig.json - Replace:
miniapp/pages/index/index.ts - Remove after verified migration: 与 13 个 TypeScript 页面重复且漂移的手写
.js - Create/complete:
miniapp/pages/service-center/** - Create/complete:
miniapp/pages/service-station/** - Create/complete:
miniapp/pages/service-appointment/** - Create/complete:
miniapp/pages/my-appointments/** - Create/complete:
miniapp/pages/classroom/** - Create/complete:
miniapp/pages/article-detail/** - Create/complete:
miniapp/pages/anti-fraud/** - Create/complete:
miniapp/pages/service-program/** - Create/complete:
miniapp/pages/service-history/** - Modify:
miniapp/app.json
Produces: 一套可编译的 TypeScript 源码;U49~U64 与活动互选页可真实导航和操作。
- 先建立页面注册、handler 存在、内部目标可达的静态失败测试。
- 明确
.ts为唯一手写源;生成.js不纳入人工维护,CI 检测同名双轨漂移。 - 修复请求 Promise 类型、页面级模块作用域、全局类型和
uploadBase定义。 - 重建首页,让 WXML、TS 和
/homeDTO 字段完全一致,并补上婚恋课堂区块。 - 接通 8 个核心入口与 Banner 内部跳转,不再借用本地资格页承载无关业务。
- 补齐服务预约、我的预约、内容列表/详情、反诈、专项服务、服务记录页面。
- 活动互选页覆盖“结果、本人确认、等待对方、双方确认、已有聊天、拒绝/超时”状态。
- 所有提交、取消、拉黑、退出等重要操作提供进度、结果与二次确认。
Exit Gate: npm run type-check 无错误;微信开发者工具编译无错误;首页固定顺序和 U49~U64 核心流程完成真机/模拟器截图验收。
Phase R6:管理后台按角色形成可运营工作台
Files:
- Modify:
admin-web/src/router/index.ts - Modify:
admin-web/src/layouts/MainLayout.vue - Replace:
admin-web/src/modules/counseling/CounselingView.vue - Complete:
admin-web/src/modules/banner/BannerManagementView.vue - Complete:
admin-web/src/modules/content/ContentManagementView.vue - Complete:
admin-web/src/modules/service-station/ServiceStationView.vue - Complete:
admin-web/src/modules/service-appointment/ServiceAppointmentView.vue - Complete:
admin-web/src/modules/service-program/ServiceProgramView.vue - Create:
admin-web/src/modules/counseling/CounselingDetailView.vue - Test:
admin-web/src/**/*.spec.ts
Produces: Platform Admin、Counseling Manager、Counselor、Content Editor、Service Station Operator 各自只看到可执行任务。
- 先写路由与权限测试,证明菜单可见性、直接 URL 访问和 API 403 三层一致。
- 注册
/counseling路由,修复语法和接口路径,拆分队列、我的咨询、详情/跟进职责。 - 将长侧栏按“用户与审核、婚恋服务、公益服务、内容运营、系统治理”分组。
- 工作台优先展示待办、超时、风险和今日服务,不以全零累计数字作为主视觉。
- Banner 编辑器校验内部目标类型、排期、受众和预览。
- 服务站人员只能处理本站预约;Content Editor 页面完全不请求用户婚恋数据。
- 为列表补齐加载、空状态、错误恢复、分页、筛选和操作结果反馈。
Exit Gate: type-check、lint、unit test、build 全通过;五种角色逐一完成登录—待办—详情—处理—审计留痕流程。
Phase R7:业务纵切回归与隐私安全复验
Files:
- Modify:
tests/invariant_integration_test.py - Modify:
tests/uat/UAT-Test-Cases.md - Modify:
tests/README.md - Create:
docs/security/V1.1_SECURITY_RETEST.md - Create:
docs/Phase-R7-Completion-Report.md
Produces: V1.0 核心不变量 + V1.1 新增不变量的完整回归证据。
- 回归 Auth、Profile、Review、Required、Match、Mutual、Block、Chat、RBAC。
- 执行 INV-001~020 的 API + DB 双层断言。
- 对本地资格佐证、咨询附件、聊天图片执行对象存储私有访问和过期 URL 测试。
- 执行 IDOR、水平越权、垂直越权、组织隔离、日志脱敏测试。
- 对注销流程验证预约取消、咨询生命周期、专项项目退出和本地资格失效。
- 生成覆盖实际命令、版本、通过数、失败数和已知限制的完成报告。
Exit Gate: 无 P0/P1 缺陷;20 条不变量全部有失败前例和通过证据;安全复验无发布阻断项。
Phase R8:正式 UAT、内容验收与发布候选
Files:
- Modify:
docs/Go-NoGo-Checklist.md - Modify:
docs/STATUS.md - Modify:
docs/PENDING_DECISIONS.md - Create:
docs/Phase-R8-UAT-Completion-Report.md - Create:
releases/v1.1.0-RC.1/RELEASE_NOTES.md - Create:
releases/v1.1.0-RC.1/FILE_MANIFEST.md
Produces: 有真实运营人员和测试用户签字的 RC,而不是 API 可返回 200 的演示版本。
- 使用独立 UAT 数据库和对象存储,禁止复用开发脏数据。
- 完成服务站扫码→预约→到场、咨询申请→完成、婚前辅导、活动互选→双方确认→聊天四条端到端场景。
- 按角色确认无需 Excel、个人微信和纸质临时台账即可留痕。
- 完成真实 Banner、服务站信息、咨询介绍、婚前辅导、反诈、课堂、关于与主办信息审核。
- 执行移动端、常见 Windows 浏览器、弱网、空数据、错误恢复和无障碍抽查。
- 生产 Smoke 覆盖首页、入口、服务站、咨询、内容、活动互选、Block 与权限矩阵。
- 只有 Go/No-Go 清单全部通过后,才将状态改为
1.1.0-RC.1。
Exit Gate: UAT 签字、真实内容审核、安全复验、备份恢复演练和生产 Smoke 全部有证据。
每阶段统一验收命令
# Backend(本机需 JDK 21 + Maven)
Set-Location backend
mvn verify -B
# Admin Web
Set-Location ..\admin-web
npm ci
npm run type-check
npm run build
# Miniapp
Set-Location ..\miniapp
npm ci
npm run type-check
# E2E
Set-Location ..
python -m pytest -q tests/e2e
# Backend
cd backend && mvn verify -B
# Admin Web
cd ../admin-web && npm ci && npm run type-check && npm run build
# Miniapp
cd ../miniapp && npm ci && npm run type-check
# E2E
cd .. && python3 -m pytest -q tests/e2e
计划自检
- Spec coverage:覆盖首页、8 入口、本地资格、咨询、婚前辅导、多类型活动互选、服务站/预约、内容、专项服务、Analytics、账户生命周期、权限与发布。
- Placeholder scan:计划没有以空任务代替实现;每阶段均有明确文件、失败测试、实现动作和 Exit Gate。
- Type consistency:统一以服务端 Principal、Permission + DataScope、
CapabilityService和/api/v1/operator/**作为跨模块接口约束。 - Scope control:不引入微服务、Kubernetes、Kafka、新 CMS Server 或新咨询 Server。
执行顺序
严格执行 R0 → R1 → R2 → R3 → R4 → R5 → R6 → R7 → R8。R2 未通过前不得处理视觉美化;R7 未通过前不得进入正式 UAT;R8 未通过前不得恢复“可上线”表述。