oh-my-muse/docs/agent-specs/2026-06-09-P1R7CompletedApproval执行版.md
zizi 85c5422cb8 test(p1r): 收口 P1R-7 completed approval 门禁
仅将 events:streamEvents 按用户批准推进为 completed,并保留 Events 其它 operation 与 Account/Content/Market/Meta 的 needs_verification 边界。
2026-06-10 10:34:15 +08:00

658 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 reviewPASS无 P0/P1/P2/P3 blocker。
- Lorentz fresh final spec/scope reviewPASS无 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 AIAI terminal event -> AI outbox -> worker -> Events -> SSE evidence 已收口。
- P1R-7c KnowledgeKnowledge source owner event -> Knowledge outbox -> worker -> Events -> SSE evidence 已收口。
- P1R-7d MarketMarket governance terminal fact -> Market outbox -> worker -> Events -> SSE evidence 已收口。
- P1R-7e AccountAccount quota adjustment terminal fact -> Account outbox -> worker -> Events -> SSE evidence 已收口。
- P1R-7f ContentContent `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 0preflight
执行位置:
```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 6P1R 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` testsfailures/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 7protected 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 9fresh 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。