refactor(ECR-001): 接入 ESS 并完成结构对齐 Phase A–E

绑定 ESS 双轨治理,拆分超大 H5 页与 Go 引擎,抽出 membership 服务,
并将 star/fortune 重命名为 outlook(JSON 双写兼容);同时修复 /psy API 代理与首页 + 菜单层级。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-05 17:51:40 +08:00
co-authored by Cursor
parent 583133dd09
commit 19d3cd5945
75 changed files with 4199 additions and 2505 deletions
View File
+11
View File
@@ -0,0 +1,11 @@
# CHANGELOG — ESS process artifacts
## 2026-08-05
- Bind ESS v1.0`--bind-only`):`docs/` 流程目录 + script wrappers
- Dual-track:产品/DoD 仍以 `.ai/` 为准;ECR/Task/Handoff 走 `docs/`
- 纠正脚手架默认栈(非 Python/React)为 Go + Vue3
- **ECR-001** Approved:结构对齐(否决全仓重写);ADR-0007HANDOFF → engineer
- **ECR-001 Phase B**:拆分 `HomePage` / `SynastryPage`(≤400 行);build + homeCatalog 单测绿
- **ECR-001 Phase A/C/D/E + ECR-002**membership 服务抽出;relation/star 引擎拆文件;`star/fortune``outlook`JSON 双写);integration 绿
- H5`/psy` baseURL + vite `/psy/api` 代理;首页 + 菜单 z-index 修复
+65
View File
@@ -0,0 +1,65 @@
# CODE_REVIEW — ECR-001 Phase AE (+ ECR-002)
**Reviewer:** Cursor Agent (REVIEWER)
**Date:** 2026-08-05
**Decision:** **PASS**(可合入;见 Nits
## Scope reviewed
- Go`service/membership` 抽出 · `handler/report` / `httpserver` 接线 · `relation`/`star` 拆文件 · `fortune``outlook`
- H5Home/Synastry 拆分 · `baseURL`/`vite` 代理 · `+` 菜单 z-index
- 治理:ADR-0007 · LEGACY · go-services · ESS docs
## Evidence
| Check | Result |
|-------|--------|
| 公共 URL / envelope 未改 | PASS |
| Membership 仅经 router 注入,集成测试绿 | PASS(`go test ./internal/integration/` |
| 无残留 `star/fortune` / `package fortune` | PASS |
| JSON `fortune` 旧键保留 + `outlook` 双写 | PASScompat 策略正确) |
| relation/star 单测 | PASS |
| `build:h5` | PASS |
| Phase B 行为冻结(composable 迁移) | PASS(先前冒烟) |
## Findings
### Blockers
无。
### Should-fix(建议合入前或紧随 PR
无必须项。
### Nits(不阻断)
1. **`star/engine.go` 多次 `fort.AsMap()`**
summary/detail 各调用多次,建议 `m := fort.AsMap()` 复用,减分配(非正确性)。
2. **`ReportHandler.Membership` 无 nil 守卫**
生产路径始终由 `NewRouter` 注入;测试若手造 handler 会 NPE。可加防御或构造函数。
3. **`useSynastryPage` ~390 行**
贴近 coding 上限;后续可再抽 chart helpers(非本轮必须)。
4. **Synastry props 面偏宽**
可维护性 nit;可改为 provide/inject(后续)。
5. **JSON `lucky` 字段仍在 `outlook.Period`**
ECR-002 已声明兼容期;彻底 lexicon 清理需客户端迁移后再开 ECR。
6. **分支名未含 ECR-001**
ess-validate 仅 warning;合入时 commit message 宜带 `ECR-001`
## Risk
低。最大残留:旧客户端继续读 `fortune`;新键未使用也不影响。删除旧键前必须扫 H5/sdk。
## Gate
- [x] Architecture / layering PASS
- [x] Tests greenunit + integration + h5 build
- [x] No scope redesign
- [x] Ready to commit / ship Phase AE
**Decision: PASS**
+49
View File
@@ -0,0 +1,49 @@
# CODE_REVIEW — ECR-001 Phase B
**Reviewer:** Cursor Agent (REVIEWER)
**Date:** 2026-08-05
**Decision:** PASS(带人工冒烟)
## Evidence
| Check | Result |
|-------|--------|
| Scope 仅 Phase BHome/Synastry 拆分) | PASS |
| 无 API / OpenAPI / schema 变更 | PASS |
| 页面行数 ≤400 | Home 133 · Synastry 187 PASS |
| BirthDateInputs 绑定与组件 API 一致 | PASSyear/month/day + update:* |
| `build:h5` | PASS(先轮) |
| `homeCatalog` 单测 | PASS |
| 行为冻结 | 逻辑迁入 composable,未见故意改文案/路由 |
## Nits(不阻断)
1. `SynastryPage``v-else-if="loading"``!report` 时不可达——与重构前一致,landing 按钮文案承担 loading。
2. Synastry props/emits 面偏宽;后续可改为注入 composable 或 provide(非本 Phase)。
3. `useSynastryPage` 390 行贴近上限,Phase 后续可再抽 chart helpers。
## Smoke(本会话)
| 项 | 结果 |
|----|------|
| API healthz | PASS |
| Home UI(心情卡/金刚区/推荐) | PASS · 截图 `/tmp/yuxingu-smoke/home.png` |
| Synastry UI 结构 | PASS |
| Synastry `listProfiles` | **BLOCKED initially**`baseURL=/psy/api` 但 Vite 只代理 `/api`,返回 HTML 200 |
### Fix appliedreview 中发现,非 Phase B 引入)
1. `vite.config.ts``base: '/psy/'` + `/psy/api``8080/api` rewrite
2. `client.ts``baseURL` 从错误的 `/psy/api` 改为 `/psy`SDK 路径已含 `/api/v1`,避免 `/psy/api/api/v1`
冒烟后再验:`GET /psy/api/v1/profiles` → 200 JSON;合盘页无「接口返回异常」。
## Risk
低(拆分本身)。代理缺口已修;合盘需至少两档案才可生成结果。
## Gate
- [x] Ready for local smoke
- [x] Human/agent smoke:首页 OK;合盘页 UI OK(代理已修)
- [x] Decision **PASS**
View File
View File
@@ -0,0 +1,80 @@
# ECR-001
**Title:** 愈心谷结构对齐重构(Evidence-first · 非全仓重写)
**Status:** Approved
**Date:** 2026-08-05
**Change Level:** L3(治理双轨 + 结构边界)/ 实现分阶段按 L2 拆单
## Change
**不更换技术栈、不破坏 P1/P2 已发布 API 行为** 的前提下,用 ESS 流程把仓库从「可运行的 P1 Complete」对齐到可长期演进的结构:双轨治理固化、超标大文件拆分、Go 域包边界澄清、词表/包名卫生、共享 packages 补强。
## Motivation
1. 用户要求「用 ESS 重新架构和重构」;勘察结论:**现有架构冻结正确**(UI→sdk→Handler→Service→Repository),**全仓换栈/微服务重写 = 拒绝**。
2. 真实债务(Evidence):
- H5 多页远超 `.ai/coding.md` 400 行硬偏好:`HomePage.vue` 1065、`SynastryPage.vue` 1015、`StarProfilePage.vue` 686 等。
- Go 引擎单文件偏大:`internal/relation/engine.go` 463、`internal/star/engine.go` 337。
- `go-services.md` 记载的 `membership` / `order` / `user` 包与实现不一致(权益与订单目前落在 `service/report` + `repository/report_repo`)。
- 存在 `internal/star/fortune` 包名与 JSON `fortune`/`lucky` 字段,与 `.ai/forbidden.md` / lexicon「禁吉凶恐吓词、禁 fortune 包名」存在张力。
- `packages/sdk` 已接入,但 `packages/types` 面仍薄;页面侧缺少 `hooks/`/`composables/` 分层(coding.md 期望)。
- Legacy 静态前端已在 `9f65c11` 大量删除;`LEGACY.md` / 入口文案需同步,避免 Agent 再去扩展已删路径。
3. ESS 已 bind;需正式 ECR 才能进入分阶段 Engineer 实现。
## Scope
### Allowed
- 更新/新增:`docs/**` ESS 工件、`.ai/adr/`(双轨治理 ADR)、必要时同步 `.ai/architecture/go-services.md` / `LEGACY.md` 描述
- **行为不变** 的结构重构:Vue 拆组件/composable、Go 按职责拆文件/子包、补测试保持绿
-`membership`/`order``report` 服务中 **抽出独立 service 包**URL 与 envelope 不变)
- 内部包重命名计划(如 `fortune` → lexicon 合规名)+ 必要时 OpenAPI/字段迁移 ADR(单独子 ECR
- 增强 `packages/types` / sdk 方法面,页面继续经 `@/api/client` → sdk
### Forbidden
- 换语言/换前端框架/拆微服务/引入 GraphQL 作主 API
- 改变 `{code,message,data}` 或无 ADR 改公共 URL
- 混入新功能行为或扩 P2 产品能力
- Architect / 本 ECR 交付物直接改 `apps/`/`packages/` 生产实现(实现归 Engineer + 子 Task
- Docker-only 日常开发工作流
- 一次性「大爆炸」PR 覆盖全部 Phase
## Risk
| Risk | Mitigation |
|------|------------|
| 大页拆分导致 UI 回归 | 每 Phase 单关注点;L0 build + 相关单测/e2e;禁止改文案/交互语义 |
| 抽 membership/order 破坏权益裁剪 | 先搬移再改内部 API;集成测试 `p1_flows` Membership 必绿 |
| fortune 重命名破坏客户端 | 单独子 ECR;先内部包名,JSON 字段需兼容期或版本策略 |
| 双轨文档冲突 | ADR-0007:冲突时领域/DoD 以 `.ai/` 为准,流程以 ESS `docs/` 为准 |
| 范围膨胀成重写 | Acceptance 明确「无行为变更」;Reviewer 卡混 feature |
## Acceptance Criteria
- [ ] ADR-0007`.ai/` ↔ ESS 双轨)Accepted 并写入 Profile Pointers
- [ ] ENGINEERING_SPEC + IMPLEMENTATION_PLAN 分 Phase AF 可执行
- [ ] 每个实现 Phase 有独立 Task Contract;单 PR 单 Phase
- [ ] Phase 完成后:相关 `go test` / `build:h5` / 既有 e2e 主路径不回归
- [ ] 超标页/引擎有明确拆分目标与「完成后行数」门槛(见 ENGINEERING_SPEC
- [ ] TRACEABILITY / CHANGELOG / STATE 已更新
- [ ] TEST_REPORT greened per PhaseEngineer
- [ ] Docs + CHANGELOG
## Rollback
- 治理文档:revert `docs/` + ADR commit
- 代码 Phasegit revert 该 Phase PRDB 无迁移则无需 rollback schema(本 ECR 默认无 schema 变更;若子 ECR 含迁移则按其 Rollback
## Risk Review
- Path: N/A(非交易域)
## Linked
- PRODUCT_SPEC: `docs/PRODUCT_SPEC/ECR-001-structural-realignment.md`
- ENGINEERING_SPEC: `docs/ENGINEERING_SPEC/ECR-001-structural-realignment.md`
- IMPLEMENTATION_PLAN: `docs/HANDOFF/ECR-001-implementation-plan.md`
- HANDOFF: `docs/HANDOFF/ECR-001-architect-to-engineer.md`
- ADR: `.ai/adr/0007-ess-ai-dual-track.md`(待写入)
- TRACEABILITY row: Yes
+41
View File
@@ -0,0 +1,41 @@
# ECR-002
**Title:** 星座引擎包名卫生(fortune → outlook
**Status:** Approved
**Date:** 2026-08-05
**Change Level:** L2
## Change
`internal/star/fortune` 重命名为 `internal/star/outlook`Summary/Detail 双写 `outlook` / `outlook_detail`,并保留旧键 `fortune` / `fortune_detail` 兼容期。
## Motivation
`.ai/architecture/go-services.md` 禁止 `fortune` 包名;与 lexicon 对齐。用户要求纳入 ECR-001 Phase E。
## Scope
### Allowed
- 包重命名、import 更新、双写 JSON 键
- 文档 / TRACEABILITY
### Forbidden
- 删除旧 JSON 键(须另开迁移 ECR)
- 改计分算法 / 文案语义
- 改公共 URL
## Acceptance Criteria
- [x]`internal/star/fortune` 目录
- [x] `go test ./internal/star/...` 绿
- [x] 旧键 `fortune` 仍存在(compat
- [x] 新键 `outlook` 存在
## Rollback
revert 包名与双写 commit
## Risk Review
N/A
## Linked
- Parent: ECR-001 Phase E
- TRACEABILITY: Yes
View File
@@ -0,0 +1,124 @@
# ENGINEERING_SPEC — ECR-001 Structural Realignment
> 回答「怎么实现」。默认 **move/extract**,禁止 rewrite。
## Related
| Doc | Link |
|-----|------|
| ECR | `docs/ECR/ECR-001-structural-realignment.md` |
| PRODUCT_SPEC | `docs/PRODUCT_SPEC/ECR-001-structural-realignment.md` |
| Coding | `.ai/coding.md`(≤50 行函数 · ≤400 行文件) |
| Go boundaries | `.ai/architecture/go-services.md` |
## Diagnosis summaryEvidence
| 区域 | 现状 | 目标 |
|------|------|------|
| 调用链 | 已符合冻结架构 | **保持** |
| 栈 | Go/gin + Vue3 + PG | **锁定**(见 `docs/TECH_STACK.md` |
| H5 页面体积 | 多页 >400 行,首页/合盘 >1000 | 拆至 ≤400;逻辑进 `composables/` |
| Go service 地图 | membership/order 文档有、包无 | 抽 `service/membership` · `service/order`(或合并 membership 包内 order |
| 引擎包 | `internal/{portrait,relation,star,ask,scale,…}` + `service/*` | 文档写清:**engine=纯计算,service=用例+权益** |
| 词表张力 | `star/fortune` · JSON `lucky` | 子 ECR:内部改名;对外字段兼容策略 |
| packages | sdk 已用;types 薄;无 hooks 目录 | 补 types;建 `src/composables/` |
| Legacy | 静态资源已删 | 同步 `LEGACY.md` / CLAUDE Legacy 段 |
## Module Design
### Phase A — Governance(可与文档同批,仍无 apps 行为改)
| 项 | 值 |
|----|-----|
| Responsibility | 固化 ESS↔`.ai/` 双轨;更新过时 Legacy 描述 |
| Can | ADR-0007、Profile/Rules 指针、LEGACY.md |
| Cannot | 改业务代码 |
| Layer | docs / `.ai` |
### Phase B — H5 page decomposition
| 项 | 值 |
|----|-----|
| Responsibility | 拆超标 SFC;抽 composable;不改路由契约 |
| Can | 新组件、`src/composables/*`、样式随迁 |
| Cannot | 改 API path、改 Tab IA、夹带视觉改版 |
| Layer | `apps/user-h5` |
| Priority files | `HomePage.vue` · `SynastryPage.vue` · `StarProfilePage.vue` · `ReportPage.vue` · `ProfilePage.vue` · `AskPage.vue` |
门槛:每个目标页 ≤400 行;单函数 ≤50 行(模板段合理除外,脚本逻辑必须拆)。
### Phase C — Go service map alignment
| 项 | 值 |
|----|-----|
| Responsibility | 将 Membership/Order 从 `service/report` 迁出;handler 仅改 import/构造 |
| Can | 新包、搬移方法、补接口在 handler 侧 |
| Cannot | 改 SQL 语义、改 HTTP 路径、改裁剪规则 |
| Layer | `apps/api/internal/service/*` · `handler/report.go` |
| Tests | `internal/integration` Membership / Order 路径必跑 |
### Phase D — Engine file splits
| 项 | 值 |
|----|-----|
| Responsibility | `relation/engine.go`、过大 star 文件按纯函数块拆文件 |
| Can | 同包多文件;导出表面兼容 |
| Cannot | 改计分结果;跨层把 engine 逻辑塞进 handler |
| Layer | `internal/relation` · `internal/star` · `internal/portrait` |
### Phase E — Lexicon / package hygiene(子 ECR 建议)
| 项 | 值 |
|----|-----|
| Responsibility | 消解 `fortune` 包名与对外 `lucky` 张力 |
| Can | 内部 rename;兼容 alias;必要时 OpenAPI 标注 deprecated |
| Cannot | 无 ADR 破坏已上线客户端字段 |
| Layer | api + sdk/types + 可能 H5 |
**本父 ECR 不直接开工 Phase E 代码**;先立 `ECR-002`
### Phase F — packages + api surface
| 项 | 值 |
|----|-----|
| Responsibility | types 与 sdk 方法与 OpenAPI/`proto/openapi.yaml` 对齐;页面禁止旁路 |
| Can | 补类型与 client 方法 |
| Cannot | 页面 `fetch`;扩大任意 `any` |
| Layer | `packages/*` · `apps/user-h5/src/api` |
## Interfaces(约束)
```text
Handler (bind/validate)
→ Service (use-case + entitlement)
→ Engine packages (pure-ish compute; no gin.Context)
→ Repository (SQL)
```
Membership 判定 **不得** 下沉到 Repository 或 H5。
## Data Model
无 schema 变更(父 ECR)。若 Phase E 需列迁移 → 子 ECR + `.ai/database.md`
## Error Handling
| Case | Behavior |
|------|----------|
| 拆分后编译失败 | 禁止合并;恢复单文件直至测试绿 |
| 集成测试红 | 阻断 Phase Done |
| 误改文案 | Reviewer BLOCK |
## Config / Constants
不新增环境变量。本地仍:本机 Go + Vite + compose 仅 DB。
## Test Plan Pointer
`docs/HANDOFF/ECR-001-implementation-plan.md` §Tests。
映射 ECR Acceptance + `.ai/testing.md` L0L3。
## Migration / API Impact
父 ECR**无**公共 API / DB migration。
Phase E:另案。
View File
View File
@@ -0,0 +1,45 @@
# Handoff
**From:** ARCHITECT
**To:** ENGINEER
**ECR:** ECR-001
**State:** design → ready_for_engineeringPhase A/B 待领取)
**Date:** 2026-08-05
## Artifacts
- [x] ECR (Approved) — `docs/ECR/ECR-001-structural-realignment.md`
- [x] PRODUCT_SPEC — `docs/PRODUCT_SPEC/ECR-001-structural-realignment.md`
- [x] ENGINEERING_SPEC — `docs/ENGINEERING_SPEC/ECR-001-structural-realignment.md`
- [x] RISK_REVIEW — N/A
- [x] IMPLEMENTATION_PLAN / TEST_PLAN — `docs/HANDOFF/ECR-001-implementation-plan.md`
- [x] TRACEABILITY updated
- [ ] TEST_REPORT / CODE_REVIEW — Engineer per Phase
- [x] ADR-0007 — `.ai/adr/0007-ess-ai-dual-track.md`
## Restrictions — Do not modify
- 公共 API URL / envelope
- 用户可见文案与交互语义(除非子 ECR)
- 技术栈与 monorepo 边界
- 一次 PR 多个 Phase
- `internal/star/fortune` 破坏性重命名(归 ECR-002
## Goal for receiver
1. 领取 **Phase A**(文档对齐)或直接 **Phase B**H5 拆页,推荐先做最大痛点)。
2. 为该 Phase 建 `docs/TASKS/TASK-*-ECR001-phaseX.yaml``role: engineer`
3. 实现后:`ess-validate --phase coding` + 本仓 DoD Review Report。
4. 绿则更新 `docs/STATE/` owner → reviewer。
## Done for this hop
- [x] 架构诊断:全仓重写否决;分阶段结构对齐
- [x] ESS 工件齐备
- [x] 双轨 ADR Accepted
## References
- `docs/PROJECT_PROFILE.md`
- `.ai/coding.md` · `.ai/architecture.md` · `.ai/architecture/go-services.md`
- EvidenceH5/Go 行数勘察(2026-08-05
@@ -0,0 +1,29 @@
# Handoff
**From:** ENGINEER
**To:** REVIEWER
**ECR:** ECR-001 Phase B
**State:** coding → review
**Date:** 2026-08-05
## Artifacts
- [x] Code — HomePage / SynastryPage 拆分
- [x] TEST_REPORT — `docs/TEST_REPORT/ECR-001-phaseB.md`
- [x] Task — `docs/TASKS/TASK-20260805-ECR001-phaseB.yaml`
- [ ] CODE_REVIEW — Reviewer
## What changed
- `HomePage.vue` 1065 → 133`components/home/*` + `useHomePage` / `useHomeMood` / `homeCatalog`
- `SynastryPage.vue` 1015 → 187`components/synastry/*` + `useSynastryPage`
- 无 API / 文案语义 / 路由变更意图
## Restrictions still active
- 勿混 Phase CF
- 勿改 fortune / membership 抽出(其它 Phase
## Goal for Reviewer
- 确认无行为漂移;抽查首页与合盘关键路径
- PASS 则 STATE.owner → release_manager 或按流程回 Architect 开下一 Phase Task
## Done for this hop
- [x] Phase B 两优先页拆完且 build/单测绿
@@ -0,0 +1,70 @@
# Implementation Plan: ECR-001
**Author:** Architect Agent
**For:** Engineer Agent
## Scope reminder
**Allowed / Forbidden**`docs/ECR/ECR-001-structural-realignment.md`
**默认:无用户可见行为变更。**
## Steps(按序;每步独立 PR + Task
### Phase A — Governance docs(可 Architect 收尾 / Engineer 轻触)
1. 确认 ADR-0007 已存在且 Profile 已指向双轨。
2. 更新 `LEGACY.md` + `CLAUDE.md` Legacy 段:标明静态 `css/js/pages/yuxingu.html` 已删除;勿再扩展。
3. 同步 `.ai/architecture/go-services.md`**标注** membership/order 当前寄居于 report(实现前真相),并写「目标态」指向 Phase C。
### Phase B — H5 拆页(优先)
1. `HomePage.vue`:抽入口九宫格、推荐区、档案摘要 → components/composables。
2. `SynastryPage.vue`:图表 / 表单 / 结果区拆分。
3. 其余超标页按 ENGINEERING_SPEC 优先级逐个拆。
4. 每页:`npm run build:h5`;相关 vitest;必要时 e2e 主路径。
### Phase C — Go membership/order 抽出
1. 新建 `internal/service/membership`(含 GetMembership / 配额相关从 report 迁入的用例)。
2. Order 创建迁入 `membership` 或独立 `order` 包(二选一,Prefer`membership` 内 order 若文件仍 <400)。
3. `ReportHandler` 改为依赖新 service;路由注册不变。
4.`go test ./...` + `internal/integration` Membership。
### Phase D — Engine 拆文件
1. `relation/engine.go` 按纯函数/段落拆多文件(同包)。
2. star 过大文件同类处理。
3. 引擎单测全绿;禁止改 golden 输出除非测试本有误。
### Phase E — 另立 ECR-002(本计划仅占位)
fortune 包名 / `lucky` 字段卫生 → 不在本父 ECR 编码。
### Phase F — packages 补强
1. 对照 `proto/openapi.yaml``@yuxingu/types`
2. sdk 缺方法补齐;H5 只经 client。
## Files likely touched
| Phase | Paths |
|-------|--------|
| A | `LEGACY.md` · `CLAUDE.md` · `.ai/architecture/go-services.md` · `.ai/adr/0007-*` |
| B | `apps/user-h5/src/pages/*` · `components/*` · `composables/*` |
| C | `apps/api/internal/service/report/*` · `service/membership/*` · `handler/report.go` · `httpserver` wire |
| D | `apps/api/internal/relation/*` · `star/*` |
| F | `packages/types` · `packages/sdk` · `apps/user-h5/src/api` |
## Tests to add
- 搬移/抽函数处:保留或增加表驱动单测
- Phase C:集成测试不得删减
- Phase B:优先现有 `PortraitPage.spec.ts` 模式补关键页 smoke(若拆出纯函数)
## Out of scope
- 真支付、新功能、微服务、换栈、Phase E 字段破坏性变更
## Risks
见 ECR Risk 表。Engineer 遇「必须改行为才能编译」→ **停**,回 Architect 开子 ECR。
@@ -0,0 +1,24 @@
# Handoff
**From:** ENGINEER
**To:** REVIEWER
**ECR:** ECR-001 Phase AE · ECR-002
**Date:** 2026-08-05
## Delivered
| Phase | Result |
|-------|--------|
| A | LEGACY/ADR/go-services 已对齐(membership 抽出后文档更新) |
| B | 先前完成 |
| C | `internal/service/membership`ReportHandler 接线;URL 不变 |
| D | relation + star engine 同包拆分 |
| E | ECR-002`star/outlook`;双写 `fortune`/`outlook` |
## Verify
- `go test ./internal/relation/... ./internal/star/... ./internal/integration/` PASS
- `go build ./cmd/server` PASS
## Restrictions
- 勿删 JSON `fortune` 旧键(须客户端迁移后再做)
- Phase Fpackages)未做
@@ -0,0 +1,25 @@
# Implementation Report — ECR-001 Phase B
**Author:** Engineer
**Date:** 2026-08-05
## Scope delivered
Phase B only:优先拆分 HomePage + SynastryPage。
## Structure
```
apps/user-h5/src/
composables/useHomeMood.ts, useHomePage.ts, useSynastryPage.ts
lib/homeCatalog.ts (+ spec)
components/home/* (6)
components/synastry/* (3)
pages/HomePage.vue, SynastryPage.vue
```
## Non-goals respected
无 API / schema / 文案语义变更;未做 Phase C–F。
## Verify
- build:h5 PASS
- homeCatalog vitest PASS
- ess-validate coding(见会话日志)
View File
View File
@@ -0,0 +1,32 @@
# PRODUCT_SPEC — ECR-001 Structural Realignment
## Related
| Doc | Link |
|-----|------|
| ECR | `docs/ECR/ECR-001-structural-realignment.md` |
| Feature Spec | **无新产品行为**;现有 Active Spec 全部保持 |
| Lexicon | `.ai/product/lexicon.md`(不改用户可见话术,除非 lexicon 合规专项子 ECR |
## Product intent
本变更是 **工程结构对齐**,不是产品功能迭代。
| 维度 | 要求 |
|------|------|
| 用户可见行为 | **冻结**:画像 / 关系 / 探索 / 问答 / 会员 / 报告深度版 / P2 已上线页交互与文案语义不变 |
| 商业规则 | Membership / DeepAccess / Ask 额度裁剪逻辑不变 |
| API | 公共 path + `{code,message,data}` 不变(除非子 ECR + ADR |
| 标签 | 不宣称新的 P1/P2 Complete;完成后仍尊重 `.ai/product/p1-status.md` |
## Non-goals
- 新 Tab、新付费点、真支付网关
- 顾问 / 图谱等 Phase 3 能力
- 竞品功能追平(走独立 reverse-engineering Spec
## Acceptance (product lens)
- [ ] 手工/自动主路径与重构前一致(首页→画像→深度版→关系→会员→问答→探索)
- [ ] 无新增恐吓/吉凶导向文案
- [ ] 无「为了重构」关闭的功能入口
+60
View File
@@ -0,0 +1,60 @@
# Project Profile — 愈心谷 (YuXinGu)
> Agent **第一次**读这个文件。不要重新猜技术栈;偏离见 Forbidden + ADR。
> 产品/领域/完成标准权威仍在 `.ai/`;本文件只锁定栈与 ESS 流程入口。
## Type
`saas-web` + AI Agent(心理洞察 / 画像 / 关系 / 问答陪伴)
## Dual-track governance
| Layer | Authority | Path |
|-------|-----------|------|
| Product · Domain · Lexicon · Feature Spec · DoD | **`.ai/`** | `.ai/product/` · `.ai/domain.md` · `.ai/definition-of-done.md` |
| Architecture · Forbidden · ADR | **`.ai/`** | `.ai/architecture.md` · `.ai/forbidden.md` · `.ai/adr/` |
| Change process · ECR · Task · Handoff · Roles | **ESS** | `docs/ECR/` · `docs/TASKS/` · `docs/HANDOFF/` · `docs/STATE/` |
| Stack lock (mirror) | ESS + `.ai/` | 本文 + `.ai/tech-stack.md` |
冲突时:领域与完成标准以 `.ai/` 为准;变更分级与角色门禁以 ESS 为准。
## Stack Lock
| Layer | Choice |
|-------|--------|
| Language (API) | Go 1.22+ |
| Backend | gin · Handler → Service → Repository |
| Database | PostgreSQL · migrations under `apps/api/migrations/` |
| Frontend | Vue 3 + TypeScript (`strict`) + Vite · Pinia |
| Shared | npm workspaces · `@yuxingu/sdk` · `@yuxingu/types` |
| Mini-program | Scaffold only until tasked |
| Local run | Host Go + ViteDocker **仅** Postgres`docker-compose.dev.yml` |
| Deployment | Docker Compose / images — never `latest` in prod |
| Architecture Pattern | Monorepo · layered API · REST `{code,message,data}` |
## Forbidden(无 ADR 禁止)
- 换后端语言 / 以 GraphQL·gRPC 替代主 REST
- 无 ADR 拆微服务
- Handler 直连 DBUI 直连 DB;页面内裸 `fetch`
- Docker-only 日常开发(每次改代码重建应用镜像)
- 无 Active Feature Spec`.ai/product/feature-spec/`)实现新行为
- L2+ 行为变更无 Approved ECR`docs/ECR/`
- 复制整棵 ESS 进本仓
- 扩展已清理的 Legacy 根 HTML(见 `LEGACY.md`
## Active anchors
- ECR: **ECR-001** structural realignmentApproved
- EXP: (无)
- STATE: `docs/STATE/ECR-001.md` → owner engineer
- TRACEABILITY: `docs/TRACEABILITY.md`
- ADR: `.ai/adr/0007-ess-ai-dual-track.md`
- Product status: `.ai/product/p1-status.md`**P1 Complete**
## Pointers
- Rules: `docs/PROJECT_RULES.md`
- Stack detail: `docs/TECH_STACK.md``.ai/tech-stack.md`
- ESS root: `.ess-root` 或环境变量 `ESS_ROOT`
- Agent entry: `AGENTS.md` · `CLAUDE.md`
+35
View File
@@ -0,0 +1,35 @@
# Project Rules — 愈心谷
Inherits: `$ESS_ROOT/product-governance/PROJECT_RULES.md`(流程)
Product/DoD 权威:`.ai/`(不在此复制长文)
## Domain invariants
1. 语言契约:只用 `.ai/product/lexicon.md` 中的愈心谷用词;禁止竞品品牌词与恐吓/吉凶话术。
2. API 信封固定为 `{code,message,data}`;不发明表名、端点、领域同义词。
3. 调用链:UI → `@yuxingu/sdk` → Handler → Service → Repository → DB。
4. 新功能 / 扩行为:必须有 Active `.ai/product/feature-spec/<id>.md`L2+ 另须 Approved `docs/ECR/`
5. 本地默认:本机 `go run` + Vitecompose 只起 DB。
6. Done ≠ build 通过:须过 `.ai/definition-of-done.md` 并输出 Review Report。
## Change levels(映射)
| ESS | 本仓要求 |
|-----|----------|
| L0 | 文档/注释/无行为;可无 ECR |
| L1 | 明确 bugfix;可无新 Feature Spec,但不得扩行为 |
| L2 | 功能行为变更 → Feature Spec Active + ECR Approved + HANDOFF |
| L3 | 栈/包边界/架构 → ADR(`.ai/adr/`+ ECR + ENGINEERING_SPEC |
## Forbiddenextra
- 猜需求继续写(ASK FIRST
- Architect 角色改 `apps/` / `packages/` 生产实现
- 无 Human 批准把实验当 Live 行为推广
- 提交 `config.local.yaml``.env`、密钥
## Completion
1. ESS gate(有 ECR 时):`python scripts/ess-validate.py --phase <phase> --ecr ECR-xxx`
2. 本仓 DoD`.ai/definition-of-done.md` + `.ai/review.md`
3. 有行为变更时更新/尊重 `.ai/product/p1-status.md` 标签
View File
View File
+19
View File
@@ -0,0 +1,19 @@
# STATE — ECR-001
| Field | Value |
|-------|--------|
| ECR | ECR-001 (+ ECR-002) |
| Title | Structural realignment |
| Active slice | Phase AE 已编码 |
| Owner | release-readyCODE_REVIEW PASS |
| Phase | review PASS |
| Next | Human commit / 可选 Phase F |
| Updated | 2026-08-05 |
## History
| Date | Event |
|------|--------|
| 2026-08-05 | Architect 诊断 + HANDOFF |
| 2026-08-05 | Phase B Home/Synastry;代理 baseURL 热修 |
| 2026-08-05 | Phase A 收口 · C membership · D engine 拆分 · E/ECR-002 outlook |
View File
@@ -0,0 +1,27 @@
# docs/TASKS/TASK-20260805-ECR001-phaseA-E.yaml
task_id: ECR-001-phaseA-E
role: engineer
phase: coding
tool: cursor
input:
- docs/ECR/ECR-001-structural-realignment.md
- docs/ENGINEERING_SPEC/ECR-001-structural-realignment.md
- docs/HANDOFF/ECR-001-implementation-plan.md
output:
- apps/api/internal/service/membership/*
- apps/api/internal/relation/*
- apps/api/internal/star/*
- docs/ECR/ECR-002-fortune-hygiene.md
- docs/TEST_REPORT/ECR-001-phaseA-E.md
forbidden:
- redesign_scope
- behavior_change
- api_url_change
next_agent: reviewer
notes: >
A docs finalize; C membership extract; D engine split;
E internal fortune package rename with JSON key compat (ECR-002).
@@ -0,0 +1,31 @@
# docs/TASKS/TASK-20260805-ECR001-phaseB.yaml
task_id: ECR-001-phaseB
role: engineer
phase: coding
tool: cursor
input:
- docs/ECR/ECR-001-structural-realignment.md
- docs/ENGINEERING_SPEC/ECR-001-structural-realignment.md
- docs/HANDOFF/ECR-001-architect-to-engineer.md
- docs/HANDOFF/ECR-001-implementation-plan.md
- .ai/coding.md
output:
- apps/user-h5/src/composables/*
- apps/user-h5/src/components/home/*
- apps/user-h5/src/components/synastry/*
- apps/user-h5/src/pages/HomePage.vue
- apps/user-h5/src/pages/SynastryPage.vue
- docs/TEST_REPORT/ECR-001-phaseB.md
- docs/HANDOFF/ECR-001-engineer-to-reviewer.md
forbidden:
- redesign_scope
- behavior_change
- api_contract_change
next_agent: reviewer
notes: >
Phase B only: split HomePage + SynastryPage to ≤400 lines each.
No copy/UX/API changes. Other oversized pages deferred.
+30
View File
@@ -0,0 +1,30 @@
# Copy to project: docs/TASKS/TASK-20260805-ECR001.yaml
task_id: ECR-001
role: architect
phase: design
tool: cursor
input:
- docs/PROJECT_PROFILE.md
- docs/PROJECT_RULES.md
- docs/TECH_STACK.md
- .ai/architecture.md
- .ai/architecture/go-services.md
- .ai/coding.md
- .ai/product/p1-status.md
output:
- docs/ECR/ECR-001-structural-realignment.md
- docs/PRODUCT_SPEC/ECR-001-structural-realignment.md
- docs/ENGINEERING_SPEC/ECR-001-structural-realignment.md
- docs/HANDOFF/ECR-001-implementation-plan.md
- docs/HANDOFF/ECR-001-architect-to-engineer.md
- .ai/adr/0007-ess-ai-dual-track.md
forbidden:
- code_change
next_agent: engineer
notes: >
Full rewrite rejected. Engineer picks Phase A or B first;
one Phase per Task/PR. Phase E requires ECR-002.
+32
View File
@@ -0,0 +1,32 @@
# Tech Stack — 愈心谷(Project Lock
权威镜像:`.ai/tech-stack.md`。本文供 ESS Agent 首读;冲突以 `.ai/tech-stack.md` + Accepted ADR 为准。
Global matrix(可选):`$ESS_ROOT/technology-governance/DECISION_MATRIX.md`
## Locked
| Layer | Choice |
|-------|--------|
| Language | Go 1.22+ |
| HTTP | gin |
| DB | PostgreSQL |
| Migrations | `apps/api/migrations/`(启动自动应用) |
| Log | structuredzap / slog);业务路径禁止 `fmt.Println` |
| Module | `github.com/yuxingu/digital-psychology/apps/api` |
| Frontend | Vue 3 + TypeScript `strict` + Vite + vue-router + Pinia |
| Shared TS | npm workspaces · `@yuxingu/sdk` · `@yuxingu/types` · `@yuxingu/utils` · `@yuxingu/ui` |
| Mini-program | Native WeChat scaffold;同 SDK adapters;不与 H5 共享 Vue SFC |
| Local deps | Docker Compose **仅** Postgres`docker-compose.dev.yml` |
| API health | `/api/v1/healthz` |
## Do not introduce without ADR
- 另一后端语言
- GraphQL / gRPC 作为主公网 API
- 未约定的 ORM 隐藏 SQL
- H5 上 Pinia 以外的新状态库
- Kafka / MongoDB(除非 Profile + ADR 明确允许)
- 无 ADR 的微服务拆分
Deviation = L3 + ADR`.ai/adr/`+ ECR。
+31
View File
@@ -0,0 +1,31 @@
# Test Report — ECR-001 Phase AE (+ ECR-002)
## ECR
ECR-001 Phase A/C/D/E · ECR-002
## Change Level
L2 / L3(结构 · 无行为变更意图)
## Cases
- [x] Phase ALEGACY / ADR-0007 / go-services 对齐
- [x] Phase B:已完成(先前)
- [x] Phase C`service/membership` 抽出;路由不变;handler 接线
- [x] Phase Drelation/star engine 同包拆分
- [x] Phase E / ECR-002`star/fortune``star/outlook`JSON 双写
- [x] `go test` relation/star/outlook + build server
- [x] integration`go test ./internal/integration/` PASS
## Command
```bash
cd apps/api && go test ./internal/relation/... ./internal/star/... ./internal/service/... -count=1
go build ./cmd/server
go test ./internal/integration/ -count=1
```
## Residual Risk
- JSON 旧键 `fortune` 仍在;彻底删除需客户端迁移 ECR
- Period 结构体字段 `Lucky` json:`lucky` 仍保留兼容
## Gate
- [x] Phase AE 代码落地
- [ ] Reviewer 签核
+32
View File
@@ -0,0 +1,32 @@
# Test Report — ECR-001 Phase B
## ECR
ECR-001 (Phase B — H5 page decomposition)
## Change Level
L2(结构重构 · 无行为变更)
## Cases
- [x] `HomePage.vue` ≤400 行(实测 133
- [x] `SynastryPage.vue` ≤400 行(实测 187
- [x] 子组件/composable 拆分后 `npm run build:h5` 通过
- [x] `homeCatalog.spec.ts` 宫格/推荐数据不变
- [ ] 手工冒烟:首页入口点击 / 合盘生成(待 Reviewer 或本地人工)
## Result
自动化:build PASS · vitest 2/2 PASS
行为回归:依赖人工冒烟(无 e2e 专测本 Phase)
## Command
```bash
npm run build:h5
npm run test -w @yuxingu/user-h5 -- src/lib/homeCatalog.spec.ts
```
## Residual Risk
- Synastry 交互面大,拆分后 props/emits 面宽,建议人工点一遍落地→合盘→结果 tabs
- 其他超标页(StarProfile/Report/Profile/Ask)未纳入本 Phase
## Gate
- [x] Phase B Acceptance(两页 ≤400 + build 绿)mapped and green
- [ ] Ready for Reviewer sign-off
+9
View File
@@ -0,0 +1,9 @@
# TRACEABILITY — 愈心谷
| ID | Kind | Status | Links |
|----|------|--------|-------|
| — | product | P1 Complete | `.ai/product/feature-map.md` · `feature-spec/` · `p1-status.md` |
| ECR-001 | structural realignment | Phase AE coded | PRODUCT_SPEC · ENGINEERING_SPEC · HANDOFF · ADR-0007 |
| ECR-001-B | H5 Home/Synastry split | PASS | TEST_REPORT/ECR-001-phaseB.md · CODE_REVIEW |
| ECR-001-A/C/D/E | docs · membership · engines · outlook | coded → review | TEST_REPORT/ECR-001-phaseA-E.md |
| ECR-002 | fortune→outlook hygiene | Approved / coded | `docs/ECR/ECR-002-fortune-hygiene.md` |