仅将 events:streamEvents 按用户批准推进为 completed,并保留 Events 其它 operation 与 Account/Content/Market/Meta 的 needs_verification 边界。
658 lines
26 KiB
Markdown
658 lines
26 KiB
Markdown
# P1R7 Completed Approval 执行版
|
||
|
||
日期:2026-06-09
|
||
|
||
## 结论
|
||
|
||
本执行版只推进 P1R-7 Events End-to-End Acceptance 的 completed approval 执行准备,审批对象唯一:
|
||
|
||
```text
|
||
events:streamEvents / GET /app-api/muse/events
|
||
```
|
||
|
||
推荐实现方式是 operation-level approval:保留既有 AI / Knowledge domain-level completed,新增 `events:streamEvents` 单项 operation-level completed。禁止把整个 `events` domain 加入 completed 白名单,禁止连带推进 Market、Account、Content、Meta 或总 P1R-7 completed。
|
||
|
||
本执行版当前只允许进入 fresh execution review;双 PASS 前不得实现、不得修改 scanner、不得修改 coverage report、不得提交或 push。执行版双 PASS 后,仍必须由用户单独明确批准,才允许在真实 worktree 更新 scanner / report / gate。
|
||
|
||
## Review 前置状态
|
||
|
||
审阅版:
|
||
|
||
- `docs/agent-specs/2026-06-09-P1R7CompletedApproval审阅版.md`
|
||
|
||
审阅版 fresh review gate:
|
||
|
||
- Curie fresh quality/feasibility review:PASS,无 P0/P1/P2/P3 blocker。
|
||
- Lorentz fresh final spec/scope review:PASS,无 P0/P1 blocker。
|
||
- Descartes 超时关闭,不计入 gate。
|
||
- Godel 返回空结果,不计入 gate。
|
||
- Gibbs 对旧版 PASS 后提出的非阻塞反馈已修订到审阅版,不计入最终新版本 PASS gate。
|
||
|
||
审阅版双 PASS 只代表可以编写本执行版,不代表用户已经批准真实 coverage 状态推进。
|
||
|
||
## 当前已验证事实
|
||
|
||
### 工作区
|
||
|
||
- 正确 worktree:`/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0`。
|
||
- 当前分支:`dev/1.0.0`。
|
||
- `git pull --ff-only origin dev/1.0.0` 已返回 `Already up to date.`。
|
||
- 当前最新提交:
|
||
|
||
```text
|
||
f84c18f test(p1r): 收口 Content 事件传播真实链路门禁
|
||
```
|
||
|
||
- 当前未提交变更只应来自 completed approval 文档:
|
||
- `docs/agent-specs/.agent`
|
||
- `docs/agent-specs/2026-06-09-P1R7CompletedApproval审阅版.md`
|
||
- `docs/agent-specs/2026-06-09-P1R7CompletedApproval执行版.md`
|
||
|
||
### 当前 coverage
|
||
|
||
当前真实 coverage summary:
|
||
|
||
```text
|
||
totalOperations 233
|
||
completedOperations 100
|
||
needsVerificationOperations 133
|
||
incompleteOperations 0
|
||
genericPersistenceOperations 0
|
||
ssePlaceholderOperations 0
|
||
```
|
||
|
||
当前 domain 状态:
|
||
|
||
```text
|
||
account 33 dedicated/needs_verification:33
|
||
ai 41 dedicated/completed:41
|
||
content 51 dedicated/needs_verification:51
|
||
events 1 dedicated/needs_verification:1
|
||
knowledge 59 dedicated/completed:59
|
||
market 32 dedicated/needs_verification:32
|
||
meta 16 dedicated/needs_verification:16
|
||
```
|
||
|
||
Events 当前唯一 operation:
|
||
|
||
```text
|
||
events streamEvents GET /app-api/muse/events dedicated needs_verification P1R-7 End-to-End Acceptance
|
||
```
|
||
|
||
### P1R-7 evidence 现状
|
||
|
||
- P1R-7a Events SSE:`streamEvents` 已从 `sse_placeholder / incomplete` 推进到 `dedicated / needs_verification`。
|
||
- P1R-7b AI:AI terminal event -> AI outbox -> worker -> Events -> SSE evidence 已收口。
|
||
- P1R-7c Knowledge:Knowledge source owner event -> Knowledge outbox -> worker -> Events -> SSE evidence 已收口。
|
||
- P1R-7d Market:Market governance terminal fact -> Market outbox -> worker -> Events -> SSE evidence 已收口。
|
||
- P1R-7e Account:Account quota adjustment terminal fact -> Account outbox -> worker -> Events -> SSE evidence 已收口。
|
||
- P1R-7f Content:Content `saveBlock` 首次成功 -> Content outbox -> worker -> Events -> SSE evidence 已收口。
|
||
|
||
这些 evidence 支撑 `events:streamEvents` completed approval,但不支撑 Market / Account / Content / Meta domain completed。
|
||
|
||
## 范围
|
||
|
||
本执行版允许的后续实现范围:
|
||
|
||
- 修改 `muse-cloud/scripts/p1r-audit-api-coverage.py`。
|
||
- 修改 `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.java`。
|
||
- 在用户明确批准后,重新生成:
|
||
- `docs/superpowers/reports/p1r-api-coverage.json`
|
||
- `docs/superpowers/reports/p1r-api-coverage.md`
|
||
- 新增 completed approval 真实推进留痕:
|
||
- `docs/memorys/2026-06-09-P1R7CompletedApproval状态推进.md`
|
||
- 更新:
|
||
- `docs/agent-specs/.agent`
|
||
|
||
本执行版禁止:
|
||
|
||
- 修改任何 OpenAPI:
|
||
- `docs/api-contracts/account/openapi.yaml`
|
||
- `docs/api-contracts/ai/openapi.yaml`
|
||
- `docs/api-contracts/content/openapi.yaml`
|
||
- `docs/api-contracts/events/openapi.yaml`
|
||
- `docs/api-contracts/knowledge/openapi.yaml`
|
||
- `docs/api-contracts/market/openapi.yaml`
|
||
- `docs/api-contracts/meta/openapi.yaml`
|
||
- 修改业务实现代码。
|
||
- 修改 Events source owner propagation 实现。
|
||
- 把 `events` 整个 domain 加入 approved domain。
|
||
- 推进 Market 32 operations completed。
|
||
- 推进 Account 33 operations completed。
|
||
- 推进 Content 51 operations completed。
|
||
- 推进 Meta 16 operations completed。
|
||
- 把 P1R-7f 或任一 owner evidence 直接写成该 owner domain completed。
|
||
- 宣称总 P1R / 全业务域 completed。
|
||
|
||
## 目标状态
|
||
|
||
用户明确批准并完成实现后,coverage summary 必须变成:
|
||
|
||
```text
|
||
totalOperations 233
|
||
completedOperations 101
|
||
needsVerificationOperations 132
|
||
incompleteOperations 0
|
||
genericPersistenceOperations 0
|
||
ssePlaceholderOperations 0
|
||
```
|
||
|
||
domain 状态必须变成:
|
||
|
||
```text
|
||
account 33 dedicated/needs_verification:33
|
||
ai 41 dedicated/completed:41
|
||
content 51 dedicated/needs_verification:51
|
||
events 1 dedicated/completed:1
|
||
knowledge 59 dedicated/completed:59
|
||
market 32 dedicated/needs_verification:32
|
||
meta 16 dedicated/needs_verification:16
|
||
```
|
||
|
||
唯一新增 completed operation 必须是:
|
||
|
||
```text
|
||
events streamEvents GET /app-api/muse/events dedicated completed P1R-7 End-to-End Acceptance
|
||
```
|
||
|
||
## 实现设计
|
||
|
||
### Scanner approval 模型
|
||
|
||
当前 scanner 使用:
|
||
|
||
```python
|
||
APPROVED_COMPLETED_DOMAINS = {"ai", "knowledge"}
|
||
```
|
||
|
||
后续实现必须保留该集合,并新增 operation-level 白名单:
|
||
|
||
```python
|
||
APPROVED_COMPLETED_OPERATIONS = {"events:streamEvents"}
|
||
```
|
||
|
||
推荐新增 helper:
|
||
|
||
```python
|
||
def operation_key(domain: str, operation_id: str) -> str:
|
||
return f"{domain}:{operation_id}"
|
||
```
|
||
|
||
`dedicated_status_for` 必须从只接收 `domain` 改为至少接收 `domain` 与 `operation_id`:
|
||
|
||
```python
|
||
def dedicated_status_for(domain: str, operation_id: str) -> tuple[str, str]:
|
||
if domain in APPROVED_COMPLETED_DOMAINS or operation_key(domain, operation_id) in APPROVED_COMPLETED_OPERATIONS:
|
||
return (
|
||
"completed",
|
||
"Dedicated entry exists; user-approved P1R acceptance evidence allows this operation to advance to completed coverage.",
|
||
)
|
||
return (
|
||
"needs_verification",
|
||
"Dedicated entry exists; later P1R stage must verify DTO, state machine, persistence, and real external closure.",
|
||
)
|
||
```
|
||
|
||
`classify_implementation` 调用点必须传入 `operation_id`:
|
||
|
||
```python
|
||
dedicated_completion, dedicated_notes = dedicated_status_for(domain, operation_id)
|
||
```
|
||
|
||
`approved_completed_operation(operation)` 必须允许 approved domain 或 approved operation key:
|
||
|
||
```python
|
||
def approved_completed_operation(operation: dict[str, Any]) -> bool:
|
||
if operation["implementationStatus"] != "dedicated":
|
||
return False
|
||
if operation["domain"] in APPROVED_COMPLETED_DOMAINS:
|
||
return True
|
||
return operation_key(operation["domain"], operation["operationId"]) in APPROVED_COMPLETED_OPERATIONS
|
||
```
|
||
|
||
中文注释必须说明:AI / Knowledge 是历史 domain-level 用户批准;Events 本次只批准 `streamEvents`,不得给未来 Events operation 自动继承 completed。
|
||
|
||
### Report gate approval 模型
|
||
|
||
`P1rApiCoverageReportTest` 必须同步新增 operation-level 白名单:
|
||
|
||
```java
|
||
/** 已获用户批准、并有 P1R 外部端到端验收证据支撑的 completed operation。 */
|
||
private static final Set<String> APPROVED_COMPLETED_OPERATIONS = Set.of(
|
||
"events:streamEvents"
|
||
);
|
||
```
|
||
|
||
推荐新增 helper:
|
||
|
||
```java
|
||
private static String operationKey(JsonNode operation) {
|
||
return operation.path("domain").asText() + ":" + operation.path("operationId").asText();
|
||
}
|
||
```
|
||
|
||
`should_only_mark_approved_dedicated_operations_as_completed` 必须改为:
|
||
|
||
```java
|
||
assertTrue(
|
||
APPROVED_COMPLETED_DOMAINS.contains(operation.path("domain").asText())
|
||
|| APPROVED_COMPLETED_OPERATIONS.contains(operationKey(operation)),
|
||
operationId + " 只有已批准 domain 或 operation 可以标记为 completed"
|
||
);
|
||
```
|
||
|
||
必须新增测试断言 completed summary 与非目标 domain:
|
||
|
||
```java
|
||
@Test
|
||
void should_only_promote_events_stream_events_for_p1r7_completed_approval() throws IOException {
|
||
JsonNode operations = readOperations();
|
||
|
||
int completed = 0;
|
||
for (JsonNode operation : operations) {
|
||
if ("completed".equals(operation.path("completionStatus").asText())) {
|
||
completed++;
|
||
}
|
||
}
|
||
assertEquals(101, completed, "P1R-7 completed approval 后 completed 总数只能从 100 增至 101");
|
||
|
||
assertOperationStatus("events", "streamEvents", "dedicated", "completed");
|
||
assertDomainStatusCount("market", "dedicated", "needs_verification", 32);
|
||
assertDomainStatusCount("account", "dedicated", "needs_verification", 33);
|
||
assertDomainStatusCount("content", "dedicated", "needs_verification", 51);
|
||
assertDomainStatusCount("meta", "dedicated", "needs_verification", 16);
|
||
}
|
||
```
|
||
|
||
helper 可以按本测试类现有风格实现,不做长期抽象。
|
||
|
||
### Coverage report 生成
|
||
|
||
用户明确批准前:
|
||
|
||
- 只能在 `/tmp` 隔离副本验证 scanner 修改后的报告输出。
|
||
- 真实 worktree 的 `docs/superpowers/reports/p1r-api-coverage.json` 和 `.md` 必须保持无 diff。
|
||
|
||
用户明确批准后:
|
||
|
||
- 才允许在真实 worktree 执行:
|
||
|
||
```bash
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
|
||
```
|
||
|
||
并把真实 report 更新纳入本阶段提交。
|
||
|
||
## 执行步骤
|
||
|
||
### Task 0:preflight
|
||
|
||
执行位置:
|
||
|
||
```bash
|
||
cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
|
||
```
|
||
|
||
命令:
|
||
|
||
```bash
|
||
pwd
|
||
git status --short --branch
|
||
git log --oneline -5
|
||
git pull --ff-only origin dev/1.0.0
|
||
git diff --name-only -- docs/api-contracts/account/openapi.yaml docs/api-contracts/ai/openapi.yaml docs/api-contracts/content/openapi.yaml docs/api-contracts/events/openapi.yaml docs/api-contracts/knowledge/openapi.yaml docs/api-contracts/market/openapi.yaml docs/api-contracts/meta/openapi.yaml muse-cloud/scripts/p1r-audit-api-coverage.py docs/superpowers/reports/p1r-api-coverage.json docs/superpowers/reports/p1r-api-coverage.md
|
||
git diff --cached --name-only -- docs/api-contracts/account/openapi.yaml docs/api-contracts/ai/openapi.yaml docs/api-contracts/content/openapi.yaml docs/api-contracts/events/openapi.yaml docs/api-contracts/knowledge/openapi.yaml docs/api-contracts/market/openapi.yaml docs/api-contracts/meta/openapi.yaml muse-cloud/scripts/p1r-audit-api-coverage.py docs/superpowers/reports/p1r-api-coverage.json docs/superpowers/reports/p1r-api-coverage.md
|
||
```
|
||
|
||
期望:
|
||
|
||
- `pwd` 是正确 worktree。
|
||
- `git pull` 为 fast-forward 或 already up to date。
|
||
- protected staged / unstaged diff 为空。
|
||
- 若存在非本文档范围的 dirty 变更,必须停止并先确认来源。
|
||
|
||
### Task 1:执行版 review gate
|
||
|
||
本文件写完后必须派发:
|
||
|
||
- fresh execution spec/scope review。
|
||
- fresh execution quality/feasibility review。
|
||
|
||
双 PASS 前不得实现 Task 2 之后任何内容。
|
||
|
||
### Task 2:用户 completed 推进批准
|
||
|
||
执行版双 PASS 后,必须让用户明确批准以下三项:
|
||
|
||
1. 本轮只审批 `events:streamEvents / GET /app-api/muse/events`。
|
||
2. 采用 operation-level approval,不采用 `events` domain-level 白名单。
|
||
3. 允许在真实 worktree 修改 scanner、coverage gate test 与 coverage report,把 completed summary 从 `100/133` 推进到 `101/132`。
|
||
|
||
没有这三项明确批准,不得进入 Task 3。
|
||
|
||
### Task 3:修改 scanner 与 report gate
|
||
|
||
允许修改:
|
||
|
||
- `muse-cloud/scripts/p1r-audit-api-coverage.py`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rEventsRealApiGateTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAiRealApiGateTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rKnowledgeRealApiGateTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketRealApiGateTest.java`
|
||
|
||
必须做到:
|
||
|
||
- 新增 `APPROVED_COMPLETED_OPERATIONS = {"events:streamEvents"}`。
|
||
- `dedicated_status_for` 支持 operation-level approval。
|
||
- `approved_completed_operation` 支持 approved domain 或 approved operation key。
|
||
- JUnit gate 同步支持 operation-level approval。
|
||
- JUnit gate 新增 `events:streamEvents` 唯一新增 completed 的断言。
|
||
- JUnit gate 明确断言 Market / Account / Content / Meta 仍为 `dedicated / needs_verification`。
|
||
- 既有 RealApi gate 只允许同步本轮 approved coverage 口径:
|
||
- `completedOperations = 101`
|
||
- `needsVerificationOperations = 132`
|
||
- `events:streamEvents = dedicated / completed`
|
||
- `summary.ssePlaceholderOperations = 0`
|
||
- 非目标 Market / Account / Content / Meta 仍为 `dedicated / needs_verification`
|
||
|
||
不得修改:
|
||
|
||
- OpenAPI。
|
||
- 业务实现。
|
||
- P1R owner propagation 代码。
|
||
|
||
### Task 4:隔离 scanner 预验证
|
||
|
||
在真实 report 更新前,必须先隔离验证:
|
||
|
||
```bash
|
||
tmpdir=$(mktemp -d /tmp/p1r7-completed-approval-impl-scan.XXXXXX)
|
||
rsync -a --delete --exclude .git --exclude 'muse-cloud/**/target' ./ "$tmpdir"/
|
||
cd "$tmpdir"
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
|
||
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
jq -r '.operations | group_by(.domain)[] | [.[0].domain, (length|tostring), ([group_by(.implementationStatus + "/" + .completionStatus)[] | (.[0].implementationStatus + "/" + .[0].completionStatus + ":" + (length|tostring))] | join(", "))] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
jq -r '.operations[] | select(.domain == "events") | [.domain,.operationId,.method,.path,.implementationStatus,.completionStatus,.targetStage] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
```
|
||
|
||
期望 summary:
|
||
|
||
```text
|
||
233 101 132 0 0 0
|
||
```
|
||
|
||
期望 domain:
|
||
|
||
```text
|
||
account dedicated/needs_verification:33
|
||
ai dedicated/completed:41
|
||
content dedicated/needs_verification:51
|
||
events dedicated/completed:1
|
||
knowledge dedicated/completed:59
|
||
market dedicated/needs_verification:32
|
||
meta dedicated/needs_verification:16
|
||
```
|
||
|
||
期望 Events:
|
||
|
||
```text
|
||
events streamEvents GET /app-api/muse/events dedicated completed P1R-7 End-to-End Acceptance
|
||
```
|
||
|
||
回到真实 worktree 后,必须确认真实 report 仍无 diff:
|
||
|
||
```bash
|
||
cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
|
||
git diff --name-only -- docs/superpowers/reports/p1r-api-coverage.json docs/superpowers/reports/p1r-api-coverage.md
|
||
```
|
||
|
||
### Task 5:真实 report 更新
|
||
|
||
只有 Task 2 用户批准后才允许执行:
|
||
|
||
```bash
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
|
||
```
|
||
|
||
随后必须核对:
|
||
|
||
```bash
|
||
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
jq -r '.operations | group_by(.domain)[] | [.[0].domain, (length|tostring), ([group_by(.implementationStatus + "/" + .completionStatus)[] | (.[0].implementationStatus + "/" + .[0].completionStatus + ":" + (length|tostring))] | join(", "))] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
jq -r '.operations[] | select(.domain == "events") | [.domain,.operationId,.method,.path,.implementationStatus,.completionStatus,.targetStage] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
|
||
```
|
||
|
||
输出必须等于 Task 4 期望。
|
||
|
||
### Task 6:P1R focused gates
|
||
|
||
从 `muse-cloud` 执行:
|
||
|
||
```bash
|
||
JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o test \
|
||
-pl muse-server -am \
|
||
-Dtest=P1rContentEventsPublishMigrationSqlTest,P1rContentEventsPublishDependencyTest,P1rContentEventsPublishEndToEndTest,P1rAccountEventsPublishMigrationSqlTest,P1rAccountEventsPublishDependencyTest,P1rAccountEventsPublishEndToEndTest,P1rMarketEventsPublishMigrationSqlTest,P1rMarketEventsPublishDependencyTest,P1rMarketEventsPublishEndToEndTest,P1rKnowledgeEventsPublishMigrationSqlTest,P1rKnowledgeEventsPublishDependencyTest,P1rKnowledgeEventsPublishEndToEndTest,P1rAiEventsPublishMigrationSqlTest,P1rAiEventsPublishDependencyTest,P1rAiEventsPublishEndToEndTest,P1rApiCoverageReportTest,P1rEventsRealApiGateTest,P1rEventsRouteOwnershipTest,P1rAiRealApiGateTest,P1rAiRouteOwnershipTest,P1rKnowledgeRealApiGateTest,P1rKnowledgeRouteOwnershipTest,P1rMarketRealApiGateTest,P1rMarketRouteOwnershipTest,P1rAccountRealApiGateTest,P1rAccountRouteOwnershipTest,P1rContentRealApiGateTest,P1rMetaRealApiGateTest \
|
||
-Dsurefire.failIfNoSpecifiedTests=false
|
||
```
|
||
|
||
目标测试类和静态 test count 下限:
|
||
|
||
| 测试类 | 最少 tests |
|
||
|---|---:|
|
||
| `P1rContentEventsPublishMigrationSqlTest` | 3 |
|
||
| `P1rContentEventsPublishDependencyTest` | 2 |
|
||
| `P1rContentEventsPublishEndToEndTest` | 5 |
|
||
| `P1rAccountEventsPublishMigrationSqlTest` | 3 |
|
||
| `P1rAccountEventsPublishDependencyTest` | 2 |
|
||
| `P1rAccountEventsPublishEndToEndTest` | 4 |
|
||
| `P1rMarketEventsPublishMigrationSqlTest` | 3 |
|
||
| `P1rMarketEventsPublishDependencyTest` | 2 |
|
||
| `P1rMarketEventsPublishEndToEndTest` | 4 |
|
||
| `P1rKnowledgeEventsPublishMigrationSqlTest` | 3 |
|
||
| `P1rKnowledgeEventsPublishDependencyTest` | 2 |
|
||
| `P1rKnowledgeEventsPublishEndToEndTest` | 5 |
|
||
| `P1rAiEventsPublishMigrationSqlTest` | 4 |
|
||
| `P1rAiEventsPublishDependencyTest` | 2 |
|
||
| `P1rAiEventsPublishEndToEndTest` | 4 |
|
||
| `P1rApiCoverageReportTest` | 6 |
|
||
| `P1rEventsRealApiGateTest` | 5 |
|
||
| `P1rEventsRouteOwnershipTest` | 4 |
|
||
| `P1rAiRealApiGateTest` | 7 |
|
||
| `P1rAiRouteOwnershipTest` | 7 |
|
||
| `P1rKnowledgeRealApiGateTest` | 8 |
|
||
| `P1rKnowledgeRouteOwnershipTest` | 6 |
|
||
| `P1rMarketRealApiGateTest` | 6 |
|
||
| `P1rMarketRouteOwnershipTest` | 4 |
|
||
| `P1rAccountRealApiGateTest` | 4 |
|
||
| `P1rAccountRouteOwnershipTest` | 4 |
|
||
| `P1rContentRealApiGateTest` | 5 |
|
||
| `P1rMetaRealApiGateTest` | 4 |
|
||
|
||
合计最少 `108` tests,failures/errors/skipped 必须均为 0。
|
||
|
||
执行后必须用 XML 计数脚本确认每个目标类实际运行,禁止空跑:
|
||
|
||
```bash
|
||
python3 - <<'PY'
|
||
from pathlib import Path
|
||
import xml.etree.ElementTree as ET
|
||
|
||
expected = {
|
||
"P1rContentEventsPublishMigrationSqlTest": 3,
|
||
"P1rContentEventsPublishDependencyTest": 2,
|
||
"P1rContentEventsPublishEndToEndTest": 5,
|
||
"P1rAccountEventsPublishMigrationSqlTest": 3,
|
||
"P1rAccountEventsPublishDependencyTest": 2,
|
||
"P1rAccountEventsPublishEndToEndTest": 4,
|
||
"P1rMarketEventsPublishMigrationSqlTest": 3,
|
||
"P1rMarketEventsPublishDependencyTest": 2,
|
||
"P1rMarketEventsPublishEndToEndTest": 4,
|
||
"P1rKnowledgeEventsPublishMigrationSqlTest": 3,
|
||
"P1rKnowledgeEventsPublishDependencyTest": 2,
|
||
"P1rKnowledgeEventsPublishEndToEndTest": 5,
|
||
"P1rAiEventsPublishMigrationSqlTest": 4,
|
||
"P1rAiEventsPublishDependencyTest": 2,
|
||
"P1rAiEventsPublishEndToEndTest": 4,
|
||
"P1rApiCoverageReportTest": 6,
|
||
"P1rEventsRealApiGateTest": 5,
|
||
"P1rEventsRouteOwnershipTest": 4,
|
||
"P1rAiRealApiGateTest": 7,
|
||
"P1rAiRouteOwnershipTest": 7,
|
||
"P1rKnowledgeRealApiGateTest": 8,
|
||
"P1rKnowledgeRouteOwnershipTest": 6,
|
||
"P1rMarketRealApiGateTest": 6,
|
||
"P1rMarketRouteOwnershipTest": 4,
|
||
"P1rAccountRealApiGateTest": 4,
|
||
"P1rAccountRouteOwnershipTest": 4,
|
||
"P1rContentRealApiGateTest": 5,
|
||
"P1rMetaRealApiGateTest": 4,
|
||
}
|
||
report_dir = Path("muse-server/target/surefire-reports")
|
||
total = 0
|
||
for cls, minimum in expected.items():
|
||
path = report_dir / f"TEST-cn.iocoder.muse.server.framework.api.{cls}.xml"
|
||
if not path.exists():
|
||
raise SystemExit(f"missing surefire XML: {cls}")
|
||
root = ET.parse(path).getroot()
|
||
tests = int(root.attrib.get("tests", "0"))
|
||
failures = int(root.attrib.get("failures", "0"))
|
||
errors = int(root.attrib.get("errors", "0"))
|
||
skipped = int(root.attrib.get("skipped", "0"))
|
||
print(f"{cls}\t{tests}\t{failures}\t{errors}\t{skipped}")
|
||
if tests < minimum or failures or errors or skipped:
|
||
raise SystemExit(f"invalid surefire result: {cls}")
|
||
total += tests
|
||
if total < 108:
|
||
raise SystemExit(f"total tests too small: {total}")
|
||
print(f"p1r_completed_approval_gate_tests={total}")
|
||
PY
|
||
```
|
||
|
||
### Task 7:protected diff 与 whitespace
|
||
|
||
执行:
|
||
|
||
```bash
|
||
git diff --check
|
||
git diff --name-only -- docs/api-contracts/account/openapi.yaml docs/api-contracts/ai/openapi.yaml docs/api-contracts/content/openapi.yaml docs/api-contracts/events/openapi.yaml docs/api-contracts/knowledge/openapi.yaml docs/api-contracts/market/openapi.yaml docs/api-contracts/meta/openapi.yaml
|
||
git diff --cached --name-only -- docs/api-contracts/account/openapi.yaml docs/api-contracts/ai/openapi.yaml docs/api-contracts/content/openapi.yaml docs/api-contracts/events/openapi.yaml docs/api-contracts/knowledge/openapi.yaml docs/api-contracts/market/openapi.yaml docs/api-contracts/meta/openapi.yaml
|
||
```
|
||
|
||
同时必须执行最终 allowed-diff gate,防止业务实现、OpenAPI、非目标配置、非目标测试或未跟踪文件混入:
|
||
|
||
```bash
|
||
python3 - <<'PY'
|
||
from pathlib import Path
|
||
import subprocess
|
||
import sys
|
||
|
||
allowed_exact = {
|
||
"muse-cloud/scripts/p1r-audit-api-coverage.py",
|
||
"muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.java",
|
||
"muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rEventsRealApiGateTest.java",
|
||
"muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAiRealApiGateTest.java",
|
||
"muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rKnowledgeRealApiGateTest.java",
|
||
"muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketRealApiGateTest.java",
|
||
"docs/superpowers/reports/p1r-api-coverage.json",
|
||
"docs/superpowers/reports/p1r-api-coverage.md",
|
||
"docs/agent-specs/.agent",
|
||
"docs/agent-specs/2026-06-09-P1R7CompletedApproval审阅版.md",
|
||
"docs/agent-specs/2026-06-09-P1R7CompletedApproval执行版.md",
|
||
"docs/memorys/2026-06-09-P1R7CompletedApproval状态推进.md",
|
||
}
|
||
|
||
def changed(args):
|
||
out = subprocess.check_output(["git", "-c", "core.quotePath=false", *args], text=True)
|
||
return {line.strip() for line in out.splitlines() if line.strip()}
|
||
|
||
paths = (
|
||
changed(["diff", "--name-only"])
|
||
| changed(["diff", "--cached", "--name-only"])
|
||
| changed(["ls-files", "--others", "--exclude-standard"])
|
||
)
|
||
unexpected = sorted(path for path in paths if path not in allowed_exact)
|
||
if unexpected:
|
||
print("unexpected_paths=" + ",".join(unexpected))
|
||
sys.exit(1)
|
||
print("allowed_diff_gate=PASS")
|
||
PY
|
||
```
|
||
|
||
期望:
|
||
|
||
- `git diff --check` 无输出。
|
||
- OpenAPI staged / unstaged diff 为空。
|
||
- allowed-diff gate 输出 `allowed_diff_gate=PASS`。
|
||
- `git status --short --untracked-files=all` 只能显示 allowed-diff gate 允许的路径。
|
||
|
||
如果本阶段已经在用户批准后修改 scanner/report,则 `muse-cloud/scripts/p1r-audit-api-coverage.py` 与 `docs/superpowers/reports/*` 允许有本阶段目标 diff;但 OpenAPI 仍必须为空。
|
||
任何 allowed-diff 之外的路径都必须停止并说明来源;不得把额外业务实现、配置、测试或 OpenAPI 改动混入本阶段。
|
||
|
||
### Task 8:留痕
|
||
|
||
用户批准并完成真实推进后,新增:
|
||
|
||
```text
|
||
docs/memorys/2026-06-09-P1R7CompletedApproval状态推进.md
|
||
```
|
||
|
||
必须记录:
|
||
|
||
- 用户批准点。
|
||
- old summary:`233 100 133 0 0 0`。
|
||
- new summary:`233 101 132 0 0 0`。
|
||
- 唯一新增 completed:`events:streamEvents`。
|
||
- Market / Account / Content / Meta 仍为 `dedicated / needs_verification`。
|
||
- scanner/test/report 修改文件。
|
||
- `git diff --stat` 与关键 diff 摘要,证明唯一状态推进来自 `events:streamEvents` operation-level approval。
|
||
- OpenAPI diff 为空。
|
||
- allowed-diff gate 结果。
|
||
- P1R focused gates 与 XML 计数。
|
||
- fresh implementation review 结果。
|
||
|
||
同时更新 `docs/agent-specs/.agent`。
|
||
|
||
### Task 9:fresh implementation review
|
||
|
||
实现和验证完成后,必须派发:
|
||
|
||
- fresh implementation spec/correctness review。
|
||
- fresh implementation quality/data-integrity/testing review。
|
||
|
||
双 PASS 前不得提交、push 或宣称 completed 已完成。
|
||
|
||
## 完成条件
|
||
|
||
只有全部满足,才可说 P1R-7 Events completed approval 已完成:
|
||
|
||
1. 用户明确批准 Task 2 三项。
|
||
2. operation-level approval 已落地,未使用 `events` domain-level 白名单。
|
||
3. coverage summary 为 `233 / 101 / 132 / 0 / 0 / 0`。
|
||
4. `events:streamEvents` 是唯一新增 completed operation。
|
||
5. Market / Account / Content / Meta 仍为 `dedicated / needs_verification`。
|
||
6. OpenAPI diff 为空。
|
||
7. scanner `--check`、P1R focused gates、XML 计数、`git diff --check`、allowed-diff gate 与 `git status --short --untracked-files=all` 通过。
|
||
8. completed approval 状态推进留痕已写入 `docs/memorys`。
|
||
9. fresh implementation 双 review PASS。
|
||
10. 提交 / push 仍需用户明确指令。
|
||
|
||
## 回滚策略
|
||
|
||
如果 scanner 或 gates 失败:
|
||
|
||
- 不运行真实 report 更新,或回退本阶段 report diff。
|
||
- 保留审阅版 / 执行版文档与失败留痕。
|
||
- 修正 scanner/test 后重新跑 `/tmp` 隔离 scanner。
|
||
|
||
如果用户未批准 Task 2:
|
||
|
||
- 保持 `events:streamEvents = dedicated / needs_verification`。
|
||
- 不修改 scanner、coverage report 或 gate test。
|
||
|
||
如果误推进非目标 domain:
|
||
|
||
- 立即停止。
|
||
- 将 Market / Account / Content / Meta 恢复为 `dedicated / needs_verification`。
|
||
- 重跑 scanner、P1R gate、protected diff。
|