236 lines
7.2 KiB
Markdown
236 lines
7.2 KiB
Markdown
# P1R0 基线门禁收口留痕
|
||
|
||
## 任务背景
|
||
|
||
本次执行 `docs/superpowers/plans/2026-05-25-P1R-0-baseline-gate.md`,目标是为 P1R 真实 API 改造建立可重复运行的基线门禁。
|
||
|
||
P1R-0 不负责实现真实业务 API,不修改生产 Controller、Service、Mapper 或 DDL。它只回答:
|
||
|
||
- OpenAPI 合同里到底有多少 operation。
|
||
- 当前 `muse-cloud/` 后端对每个 operation 是真实专用入口、catch-all 合同入口、通用持久化入口、SSE 占位入口,还是缺入口。
|
||
- 哪些 operation 绝不能在 P1R-0 阶段被误判为完成。
|
||
- 后续 P1R-1 到 P1R-7 应该基于哪份机器可读矩阵继续推进。
|
||
|
||
## 计划原始目标
|
||
|
||
计划要求新增一套 API 覆盖矩阵门禁:
|
||
|
||
- 新增 `muse-cloud/scripts/p1r-audit-api-coverage.py`。
|
||
- 解析 `docs/api-contracts/*/openapi.yaml`。
|
||
- 扫描 `muse-cloud/` Java 源码。
|
||
- 生成:
|
||
- `docs/superpowers/reports/p1r-api-coverage.json`
|
||
- `docs/superpowers/reports/p1r-api-coverage.md`
|
||
- 新增 Maven 测试:
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.java`
|
||
- 保证 P1R-0 不把 catch-all、generic persistence、SSE placeholder、missing 这类非真实实现标记为完成。
|
||
|
||
## 实际完成内容
|
||
|
||
P1R-0 在独立 worktree 中完成:
|
||
|
||
```text
|
||
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/feature-p1r-0-baseline-gate
|
||
```
|
||
|
||
分支:
|
||
|
||
```text
|
||
feature/p1r-0-baseline-gate
|
||
```
|
||
|
||
关键提交:
|
||
|
||
```text
|
||
97f1f3a chore(p1r): 生成 API 覆盖基线矩阵
|
||
7d35ce7 fix(p1r): 修正 API 覆盖矩阵识别规则
|
||
4084fce fix(p1r): 收紧 API 覆盖矩阵路由匹配
|
||
0d16c21 fix(p1r): 修正 API 覆盖矩阵必填与入口归属
|
||
9a32e3d fix(p1r): 强化覆盖矩阵完成状态校验
|
||
83d7df1 test(p1r): 增加 API 覆盖矩阵门禁
|
||
19e673c fix(p1r): 对齐基线门禁验证规则
|
||
```
|
||
|
||
实际产物:
|
||
|
||
- 审计脚本:`muse-cloud/scripts/p1r-audit-api-coverage.py`
|
||
- JSON 报告:`docs/superpowers/reports/p1r-api-coverage.json`
|
||
- Markdown 报告:`docs/superpowers/reports/p1r-api-coverage.md`
|
||
- Maven 门禁:`muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.java`
|
||
- 规格与计划命令同步更新:
|
||
- `docs/superpowers/specs/2026-05-25-P1R-0-baseline-gate-design.md`
|
||
- `docs/superpowers/plans/2026-05-25-P1R-0-baseline-gate.md`
|
||
|
||
## 关键结果
|
||
|
||
最终报告统计:
|
||
|
||
```text
|
||
totalOperations=233
|
||
completedOperations=0
|
||
catchAllOperations=36
|
||
genericPersistenceOperations=180
|
||
ssePlaceholderOperations=2
|
||
missingOperations=0
|
||
```
|
||
|
||
`completedOperations=0` 是预期结果。P1R-0 是基线审计,不跑领域真实验收,所以不能宣称任何 operation 已完成。
|
||
|
||
非真实实现状态规则已经统一到脚本、Maven 测试、规格和计划:
|
||
|
||
- `catch_all`
|
||
- `generic_persistence`
|
||
- `sse_placeholder`
|
||
- `missing`
|
||
|
||
这些 implementationStatus 对应的 completionStatus 只能是:
|
||
|
||
- `incomplete`
|
||
- `blocked`
|
||
|
||
不能是 `completed`,也不能是 `needs_verification`。
|
||
|
||
## Maven 行为结论
|
||
|
||
计划原始命令是:
|
||
|
||
```bash
|
||
cd muse-cloud
|
||
mvn -o test -pl muse-server -am -Dtest=P1rApiCoverageReportTest
|
||
```
|
||
|
||
实测该命令会失败在上游模块,例如 `muse-common`:
|
||
|
||
```text
|
||
No tests matching pattern "P1rApiCoverageReportTest" were executed!
|
||
```
|
||
|
||
根因:
|
||
|
||
- `-pl muse-server -am` 会把 `muse-server` 的上游 reactor 模块一起拉入构建。
|
||
- `-Dtest=P1rApiCoverageReportTest` 是全局 surefire 参数。
|
||
- 上游模块没有这个测试类,默认会因为“指定测试不存在”失败。
|
||
|
||
正确行为不是修改父 POM。父 POM 全局关闭 `failIfNoSpecifiedTests` 会改变全仓测试语义,容易掩盖测试名拼写错误。
|
||
|
||
正确的局部命令是:
|
||
|
||
```bash
|
||
cd muse-cloud
|
||
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
|
||
mvn -o test -pl muse-server -am -Dtest=P1rApiCoverageReportTest -Dsurefire.failIfNoSpecifiedTests=false
|
||
```
|
||
|
||
含义:
|
||
|
||
- 运行环境必须是 Java 21。
|
||
- 上游 reactor 模块没有 `P1rApiCoverageReportTest` 不应失败。
|
||
- 真正需要执行目标门禁测试的是 `muse-server`。
|
||
|
||
## 验证记录
|
||
|
||
执行过的验证:
|
||
|
||
```bash
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
Generated docs/superpowers/reports/p1r-api-coverage.json
|
||
Generated docs/superpowers/reports/p1r-api-coverage.md
|
||
```
|
||
|
||
报告一致性验证:
|
||
|
||
```bash
|
||
python3 - <<'PY'
|
||
import json
|
||
from pathlib import Path
|
||
report = json.loads(Path("docs/superpowers/reports/p1r-api-coverage.json").read_text())
|
||
summary = report["summary"]
|
||
count = len(report["operations"])
|
||
assert summary["totalOperations"] == count, (summary["totalOperations"], count)
|
||
assert summary["completedOperations"] == 0, summary["completedOperations"]
|
||
for op in report["operations"]:
|
||
assert op["completionStatus"] != "completed", op["operationId"]
|
||
if op["implementationStatus"] in {"catch_all", "generic_persistence", "sse_placeholder", "missing"}:
|
||
assert op["completionStatus"] in {"incomplete", "blocked"}, op["operationId"]
|
||
print("P1R-0 report consistency OK:", count, "operations")
|
||
PY
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
P1R-0 report consistency OK: 233 operations
|
||
```
|
||
|
||
脚本负例验证:
|
||
|
||
- 将内存中的 non-real operation 临时改成 `needs_verification`。
|
||
- 调用 `validate_report(report)`。
|
||
- 结果按预期失败,说明脚本会拒绝 non-real `needs_verification`。
|
||
|
||
输出:
|
||
|
||
```text
|
||
P1R-0 negative validate_report OK: adminCreateCallAttributionJob
|
||
```
|
||
|
||
Maven 门禁:
|
||
|
||
```bash
|
||
cd muse-cloud
|
||
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
|
||
mvn -o test -pl muse-server -am -Dtest=P1rApiCoverageReportTest -Dsurefire.failIfNoSpecifiedTests=false
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
Running cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest
|
||
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
|
||
BUILD SUCCESS
|
||
```
|
||
|
||
## 当前集成状态
|
||
|
||
截至本留痕创建时:
|
||
|
||
- P1R-0 已在 `feature/p1r-0-baseline-gate` 分支完成并提交。
|
||
- 用户曾要求合并到 `main`,但随后中断该回合并改为“进行总结留痕”。
|
||
- 因此当前记录只确认 P1R-0 分支完成,不确认已经合并到 `main`。
|
||
- 主工作区 `/Users/qingse/Sync/local-git/oh-my-muse` 当时仍在 `feature/p1-muse-cloud-backend-20260524`,且有其他未提交或未跟踪内容,不能当作干净 main 合并面。
|
||
|
||
后续如果要继续合并,需要重新执行:
|
||
|
||
```bash
|
||
cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/feature-p1r-0-baseline-gate
|
||
git status --short
|
||
git branch --show-current
|
||
```
|
||
|
||
确认干净后,再按实际 base 分支执行 merge / PR 流程。
|
||
|
||
## 下个阶段
|
||
|
||
下个阶段是:
|
||
|
||
```text
|
||
P1R-1 Content Real API spec + plan
|
||
```
|
||
|
||
P1R-1 不应该继续做基线扫描,而应该基于 P1R-0 报告开始真实业务 API 改造设计。
|
||
|
||
建议步骤:
|
||
|
||
1. 从 `docs/superpowers/reports/p1r-api-coverage.json` 筛出 Content 域 operation。
|
||
2. 分清哪些 Content operation 仍是 `catch_all` 或 `generic_persistence`。
|
||
3. 写 P1R-1 Content Real API 规格,明确真实 Controller、Service、DTO、持久化、幂等、权限和审计闭环。
|
||
4. 写 P1R-1 执行计划。
|
||
5. 再进入实现,不要直接从 catch-all 适配拼接到另一个临时 spec。
|
||
|
||
P1R-1 的核心目标是把 Content 域从“合同可响应”推进到“真实业务 API 可验收”。
|