只推进 Market 4 个 operation-level completed approval,保持 market domain-level allowlist 关闭,并保留剩余 28 个 Market operation 为 needs_verification。
34 KiB
P1R Market Completed Approval 执行版
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:subagent-driven-developmentto implement this plan task-by-task after the explicit approval gate. Steps use checkbox syntax for tracking.
日期:2026-06-11
结论
本执行版推荐第一轮只做 Market operation-level completed approval,不做 Market domain-level 32/32 completed。
第一轮推荐审批 4 个 Marketplace 详情/分类/收藏 operation:
market:getMarketplaceAsset
market:listMarketplaceCategories
market:favoriteAsset
market:unfavoriteAsset
审批后目标 coverage summary 为:
total=233
completed=131
needsVerification=102
incomplete=0
genericPersistence=0
ssePlaceholder=0
Market 域目标状态为:
market total=32
completed=4
needsVerification=28
本执行版只定义实现前置批准项、允许变更范围、TDD 顺序、验证命令、XML 防空跑和回滚策略。当前不得直接实现,不得修改 OpenAPI、scanner、coverage report、业务实现或 gate test。
flowchart TB
Current["当前 Market<br/>32 dedicated / needs_verification"] --> Exec["执行版<br/>锁定第一批 4 个 operation"]
Exec --> Review["fresh execution spec/scope review<br/>fresh execution quality/feasibility review"]
Review --> Approval{"用户明确批准<br/>4 ops / operation-level / OpenAPI commandId / allowed diff"}
Approval -->|否| Stay["保持当前 coverage<br/>233/127/106"]
Approval -->|是| Red["TDD RED<br/>先改 Market/Coverage/legacy gates<br/>旧 report 必须失败"]
Red --> Green["TDD GREEN<br/>Market OpenAPI commandId + scanner operation allowlist + regenerate report"]
Green --> Verify["focused + P1R mixed + Flyway _test<br/>XML 防空跑 + allowed/protected diff"]
Verify --> FreshReview["fresh implementation review"]
当前事实
正确 worktree:
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
当前 HEAD:
f18116a test(p1r): 收口 Account 第一批 completed approval 门禁
当前 coverage summary:
233 127 106 0 0 0
当前 Market 事实:
- Market 32 个 operation 全部为
dedicated / needs_verification。 APPROVED_COMPLETED_DOMAINS当前只包含ai、knowledge。APPROVED_COMPLETED_OPERATIONS当前只包含events:streamEvents、Meta 16 个 operation、Account 第一批 10 个 operation。P1rMarketRealApiGateTest当前明确禁止 Market operation 标记为completed。P1rApiCoverageReportTest当前断言 summarycompleted=127,并断言 Market 32 个 operation 继续needs_verification。P1rEventsRealApiGateTest、P1rAiRealApiGateTest、P1rKnowledgeRealApiGateTest仍硬编码当前 summary 或 Market needs_verification 口径;实现前必须把这些 legacy mixed gate 同步列入单独批准项。favoriteAsset/unfavoriteAsset的 Java Controller 和 Service 强制校验X-Command-Id,但docs/api-contracts/market/openapi.yaml当前未声明该 header,coverage report 因此显示requiresCommandId=false。listMarketplaceRecommendations当前是fallback_popular/fallback_newest可解释排序,不是独立个性化推荐系统读模型。
执行边界
必须先获用户明确批准
实现前必须同时获得以下 4 项批准:
- 批准第一轮 Market completed operation 精确清单为本执行版列出的 4 个 operation。
- 批准只走 operation-level approval,不把
market加入 domain-level completed allowlist。 - 批准只在
docs/api-contracts/market/openapi.yaml的favoriteAsset/unfavoriteAsset增加 requiredX-Command-Idheader 合同;不修改其它 OpenAPI。 - 批准按本执行版修改 scanner、coverage report、Market/Coverage gate、必要 legacy mixed gate、Market focused tests、新增 Market HTTP+DB
_testIT、Flyway assertion、memory 和.agent。
未获 4 项批准前,不得实施本执行版。
如果用户不批准第 3 项,必须把 favoriteAsset / unfavoriteAsset 移出第一批,并重写执行版为纯读候选。
market:listMarketplaceAssets 与 market:listMarketplaceRecommendations 本轮明确不进入 completed approval;前者需要先补 pageNo/pageSize 1..100 边界证据,后者需要先解决 OpenAPI 个性化推荐描述与当前 fallback 排序实现的合同不一致。
本轮允许变更
获批后只允许修改以下路径:
docs/api-contracts/market/openapi.yaml,仅限为favoriteAsset/unfavoriteAsset增加 requiredX-Command-Idheader。muse-cloud/scripts/p1r-audit-api-coverage.pydocs/superpowers/reports/p1r-api-coverage.jsondocs/superpowers/reports/p1r-api-coverage.mdmuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rEventsRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAiRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rKnowledgeRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketDiscoveryFavoriteCompletedApprovalIT.java,新增 Market 详情/分类/收藏 HTTP + 真实 PostgreSQL_test证据。muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketFlywayMigrationIT.java,仅限补充 V6/V8/V15 Market 表、索引、约束、trigger 和 favorite 非法 insert/update assertion。muse-cloud/muse-module-market/muse-module-market-server/src/test/java/cn/iocoder/muse/module/market/controller/app/muse/AppMuseMarketplaceAssetControllerTest.javamuse-cloud/muse-module-market/muse-module-market-server/src/test/java/cn/iocoder/muse/module/market/application/muse/MarketAssetQueryServiceTest.javamuse-cloud/muse-module-market/muse-module-market-server/src/test/java/cn/iocoder/muse/module/market/application/muse/MarketFavoriteServiceTest.javamuse-cloud/muse-module-market/muse-module-market-server/src/test/java/cn/iocoder/muse/module/market/dal/mysql/muse/MuseMarketAssetMapperTest.javadocs/agent-specs/.agentdocs/agent-specs/2026-06-11-P1RMarketCompletedApproval审阅版.mddocs/agent-specs/2026-06-11-P1RMarketCompletedApproval执行版.mddocs/memorys/2026-06-11-P1RMarket状态推进.md
如 implementation 发现必须修改 Market 业务实现、其它 OpenAPI、数据库迁移、Account/Content/Meta gate 或其它文件,必须停下说明原因并重新取得用户批准。
本轮禁止变更
- 不修改除
docs/api-contracts/market/openapi.yaml之外的 OpenAPI。 - 不修改 Market 业务实现来掩盖 coverage 缺口。
- 不新增或修改 Market domain-level completed allowlist。
- 不推进 Market purchase / install / handoff / governanceImpact。
- 不推进 Market publish / review / governance 管理切片。
- 不推进 Market appeals / restore / projection 切片。
- 不推进 Account remaining 23、Content 或总 P1R completed。
第一轮审批清单
| operation key | Method | Path | 目标状态 | 完成证据边界 |
|---|---|---|---|---|
market:getMarketplaceAsset |
GET |
/app-api/muse/marketplace/assets/{assetId} |
dedicated / completed |
App 资产详情、可见性、missing/invisible asset 拒绝、license/category/governance status DTO |
market:listMarketplaceCategories |
GET |
/app-api/muse/marketplace/categories |
dedicated / completed |
分类聚合、fallback recommendation slot、exposure summary unavailable 明示 |
market:favoriteAsset |
POST |
/app-api/muse/marketplace/assets/{assetId}/favorite |
dedicated / completed |
required X-Command-Id、登录 owner、可见资产、command replay、favorite active、唯一约束和审计事实 |
market:unfavoriteAsset |
DELETE |
/app-api/muse/marketplace/assets/{assetId}/favorite |
dedicated / completed |
required X-Command-Id、登录 owner、可见资产、command replay、favorite inactive、不删除审计事实 |
保持 needs_verification 的 Market operation
以下 28 个 operation 必须保持 dedicated / needs_verification:
market:listMarketplaceAssets
market:listMarketplaceRecommendations
market:adminListAppeals
market:adminGetAppeal
market:adminResolveAppeal
market:adminListMarketAssets
market:adminGetMarketAsset
market:adminDelistAsset
market:adminPreviewGovernanceImpact
market:adminRecallAsset
market:adminListPublishRequests
market:adminApprovePublishRequest
market:adminRejectPublishRequest
market:submitAppeal
market:supplementAppeal
market:withdrawAppeal
market:createBindPrecheck
market:getGovernanceImpact
market:installMarketplaceAsset
market:purchaseAsset
market:createMarketplaceHandoff
market:getHandoffStatus
market:cancelHandoff
market:listMyPublishRecords
market:savePublishDraft
market:runPublishCheck
market:submitPublishRequest
market:withdrawPublishRequest
保留原因:
listMarketplaceAssets当前缺少 pageNo/pageSize 1..100 边界证据;实现层会透传 pageSize,底层PAGE_SIZE_NONE=-1可能变成全量查询,不能在未获业务实现批准前标为 completed。listMarketplaceRecommendations当前 OpenAPI 描述是个性化推荐,实际实现是fallback_popular/fallback_newest排序;合同与实现语义不闭合,不能在本轮作为 completed。- purchase / install / handoff / governanceImpact 缺目标 owner 消费闭环、Account 读侧 E2E 和跨 owner governance 影响闭环。
- publish / review / governance 证据较强,但仍需单独执行版冻结 13 个 operation 的审批范围、Events outbox 边界和 fresh completed 级验证。
- appeals / restore / projection 写入的是申诉审计、治理 action 或 Account projection 子集,不能混成统一 completed 闭环。
证据矩阵
| 证据类型 | 必跑或必查内容 | 目的 |
|---|---|---|
| Market focused tests | AppMuseMarketplaceAssetControllerTest、MarketAssetQueryServiceTest、MarketFavoriteServiceTest、MuseMarketAssetMapperTest |
证明 4 个 operation 的 HTTP contract、版本头、commandId、owner、可见性、幂等和 favorite active/inactive |
Market HTTP+DB _test |
新增 P1rMarketDiscoveryFavoriteCompletedApprovalIT |
证明 4 个 operation 经 HTTP 入口访问真实 PostgreSQL _test 数据,覆盖 detail/category/favorite/unfavorite 的持久化和错误路径 |
| P1R Market gates | P1rMarketRealApiGateTest、P1rMarketRouteOwnershipTest、P1rMarketMigrationSqlTest |
证明 only 4 Market operation completed,28 个继续 needs_verification,路由仍 dedicated |
| P1R mixed gates | Coverage、Market、Events、AI、Knowledge、Account、Content、Meta gates | 防止非目标 domain 被连带推进,并同步 legacy summary / Market 状态断言 |
Flyway _test |
P1rMarketFlywayMigrationIT fresh rerun |
证明 V1-V15 clean migrate、Market V6/V8/V15 表/索引/约束/trigger、favorite unique/command 约束和非法 insert 拒绝 |
| Coverage scanner | python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check |
证明 scanner/report 与 operation-level allowlist、OpenAPI commandId 口径一致 |
| XML 防空跑 | 逐个读取 surefire XML,检查 tests、failures、errors、skipped | 防止 Maven 未跑目标类或旧 XML 假绿 |
| OpenAPI allowed diff | 只允许 market/openapi.yaml 增加 favorite/unfavorite required X-Command-Id |
修正合同与实现不一致,不扩大其它合同 |
| Business protected diff | Market 业务实现 staged/unstaged diff 必须为空 | 证明没有通过改实现掩盖 coverage 缺口 |
| Allowed diff | staged、unstaged、untracked 均必须落在允许清单 | 证明没有顺手扩大 scope |
说明:standalone MockMvc、mock Service、mapper focused tests 只能作为支持证据,不能单独支撑 favoriteAsset / unfavoriteAsset completed。实现阶段必须新增 Market HTTP + 真实 PostgreSQL _test harness;若现有 Spring 测试结构无法稳定做到 WebApplicationContext/MockMvc + real mapper + _test DB,必须停下修订执行版,不能用 mock 组合替代。
TDD 执行步骤
Task 0:实现前现场确认
- 确认 worktree:
pwd
git -c core.quotePath=false status --short --branch
git log --oneline -5
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
预期:
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
233 127 106 0 0 0
- 确认 Market 32 个 operation 仍全部是
dedicated / needs_verification:
jq -r '.operations[] | select(.domain=="market") | [.operationId,.implementationStatus,.completionStatus,.requiresCommandId] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
- 确认实施前只有文档 diff,没有 OpenAPI、scanner、coverage report、业务实现 diff:
git -c core.quotePath=false status --short --branch
git diff -- docs/api-contracts muse-cloud/scripts/p1r-audit-api-coverage.py docs/superpowers/reports
git diff -- muse-cloud/muse-module-market/muse-module-market-server/src/main/java
XML 防空跑通用规则
除 TDD RED 失败验证外,所有 Maven test 验证命令都必须执行以下规则,不能只读取历史 surefire XML:
- 命令前记录
export RUN_START_EPOCH=$(date +%s)。 - 命令前删除本任务要求检查的
target/surefire-reports/TEST-*.xml。 - 命令后逐个确认 XML 存在、
mtime >= RUN_START_EPOCH、tests不低于本执行版最低值、failures=0、errors=0、skipped=0。 - 任一 XML 缺失、mtime 早于运行开始时间、tests 低于最低值或存在失败/跳过,都必须视为验证失败。
TDD RED 失败验证必须同样删除目标 XML 并记录 RUN_START_EPOCH,但 RED 的预期是 Maven 失败;此时只校验失败发生在本次运行窗口内,并人工确认失败点来自本执行版列出的旧 report mismatch,不要求 failures=0。
推荐校验脚本:
python3 - <<'PY'
import os
import sys
import xml.etree.ElementTree as ET
from pathlib import Path
run_start = int(os.environ["RUN_START_EPOCH"])
checks = {
"muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml": 6,
}
failed = False
for path_text, min_tests in checks.items():
path = Path(path_text)
if not path.exists():
print(f"MISSING_XML {path}")
failed = True
continue
if int(path.stat().st_mtime) < run_start:
print(f"STALE_XML {path}")
failed = True
continue
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(path, tests, failures, errors, skipped)
if tests < min_tests or failures or errors or skipped:
failed = True
if failed:
sys.exit(1)
PY
执行具体任务时必须把 checks 替换成该任务表格内列出的 XML 路径和最低 tests。
Task 1:TDD RED,先改 gate 期望
获批后先修改:
P1rApiCoverageReportTest.javaP1rMarketRealApiGateTest.javaP1rEventsRealApiGateTest.javaP1rAiRealApiGateTest.javaP1rKnowledgeRealApiGateTest.java
RED 期望:
- summary 期望
completed=131、needsVerification=102,但旧 report 仍是127/106,必须失败。 - Market 4 个 approved operation 期望
completed,但旧 report 仍是needs_verification,必须失败。 - Market 28 个未批准 operation 继续期望
needs_verification,其中必须包含listMarketplaceAssets与listMarketplaceRecommendations。 favoriteAsset/unfavoriteAsset期望requiresCommandId=true,但旧 report 仍是false,必须失败。
运行:
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rEventsRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rAiRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rKnowledgeRealApiGateTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rMarketRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest \
-Dsurefire.failIfNoSpecifiedTests=false
预期:至少一个失败点来自旧 report 的 127/106、Market 4 个 operation 尚未 completed,或 favorite/unfavorite requiresCommandId=false。若直接通过,必须停下排查假绿。
Task 2:OpenAPI commandId 合同修正
只修改 docs/api-contracts/market/openapi.yaml:
- 在
favoriteAssetparameters 中追加 required headerX-Command-Id。 - 在
unfavoriteAssetparameters 中追加 required headerX-Command-Id。 - 不修改其它 Market operation。
- 不修改其它 OpenAPI 文件。
推荐写法:
- name: X-Command-Id
in: header
required: true
schema:
type: string
description: 幂等命令 ID,收藏和取消收藏必须传入。
修正后用 scanner 验证 report 中:
market:favoriteAsset requiresCommandId=true
market:unfavoriteAsset requiresCommandId=true
Task 3:TDD GREEN,最小 scanner/report 状态推进
只修改 muse-cloud/scripts/p1r-audit-api-coverage.py:
- 不修改
APPROVED_COMPLETED_DOMAINS。 - 只向
APPROVED_COMPLETED_OPERATIONS追加 4 个market:*operation key:market:getMarketplaceAsset、market:listMarketplaceCategories、market:favoriteAsset、market:unfavoriteAsset。 - 保持 completed 必须仍是
dedicated的校验。
生成 report:
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
预期 summary:
total=233
completed=131
needsVerification=102
incomplete=0
genericPersistence=0
ssePlaceholder=0
预期 Market:
completed=4
needsVerification=28
favoriteAsset requiresCommandId=true
unfavoriteAsset requiresCommandId=true
Task 4:Market focused verification
运行 Market 本域 focused tests:
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f \
muse-module-market/muse-module-market-server/target/surefire-reports/TEST-cn.iocoder.muse.module.market.controller.app.muse.AppMuseMarketplaceAssetControllerTest.xml \
muse-module-market/muse-module-market-server/target/surefire-reports/TEST-cn.iocoder.muse.module.market.application.muse.MarketAssetQueryServiceTest.xml \
muse-module-market/muse-module-market-server/target/surefire-reports/TEST-cn.iocoder.muse.module.market.application.muse.MarketFavoriteServiceTest.xml \
muse-module-market/muse-module-market-server/target/surefire-reports/TEST-cn.iocoder.muse.module.market.dal.mysql.muse.MuseMarketAssetMapperTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketMigrationSqlTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketRouteOwnershipTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-module-market/muse-module-market-server,muse-server -am \
-Dtest=AppMuseMarketplaceAssetControllerTest,MarketAssetQueryServiceTest,MarketFavoriteServiceTest,MuseMarketAssetMapperTest,P1rMarketMigrationSqlTest,P1rMarketRouteOwnershipTest,P1rMarketRealApiGateTest,P1rApiCoverageReportTest \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML 并检查 failures=0、errors=0、skipped=0:
| Test class | 最低 tests |
|---|---|
AppMuseMarketplaceAssetControllerTest |
11 |
MarketAssetQueryServiceTest |
6 |
MarketFavoriteServiceTest |
7 |
MuseMarketAssetMapperTest |
2 |
P1rMarketMigrationSqlTest |
9 |
P1rMarketRouteOwnershipTest |
3 |
P1rMarketRealApiGateTest |
6 |
P1rApiCoverageReportTest |
6 |
必须补齐或确认以下断言:
- MockMvc
getMarketplaceAsset覆盖 visible asset、missing asset、invisible asset。 - MockMvc
listMarketplaceCategories覆盖分类聚合、fallback slot、exposure summary unavailable。 - MockMvc 缺少
X-Command-Id的favoriteAsset返回MARKET_COMMAND_ID_REQUIRED。 - MockMvc 缺少
X-Command-Id的unfavoriteAsset返回MARKET_COMMAND_ID_REQUIRED。 - Service 空白 commandId 的
favoriteAsset返回MARKET_COMMAND_ID_REQUIRED。 - Service 空白 commandId 的
unfavoriteAsset返回MARKET_COMMAND_ID_REQUIRED。 unfavoriteAsset只能把 favorite fact 置为 inactive,不允许 delete。listMarketplaceAssets与listMarketplaceRecommendations可保留现有回归测试,但不得作为本轮 completed evidence;P1R gate 必须继续断言它们是needs_verification。
如测试数量因补断言增加,XML 检查的最低 tests 可高于上表,但不能低于上表。
Task 5:Market HTTP + 真实 PostgreSQL _test completed gate
新增 P1rMarketDiscoveryFavoriteCompletedApprovalIT,使用独立 _test 数据库和真实 mapper/service 数据,不能使用生产库或非 _test 库:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_MARKET_COMPLETED_APPROVAL_TEST_DB=muse_p1r_market_discovery_favorite_completed_approval_test
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-tc "SELECT 1 FROM pg_database WHERE datname = '$P1R_MARKET_COMPLETED_APPROVAL_TEST_DB'" | grep -q 1 || \
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-c "CREATE DATABASE $P1R_MARKET_COMPLETED_APPROVAL_TEST_DB"
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketDiscoveryFavoriteCompletedApprovalIT.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rMarketDiscoveryFavoriteCompletedApprovalIT \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="jdbc:postgresql://$MUSE_POSTGRES_HOST:$MUSE_POSTGRES_PORT/$P1R_MARKET_COMPLETED_APPROVAL_TEST_DB" \
-Dp1r.flyway.user="$MUSE_POSTGRES_USERNAME" \
-Djava.net.useSystemProxies=false \
-DsocksProxyHost= -DsocksProxyPort= \
-Dhttp.proxyHost= -Dhttp.proxyPort= \
-Dhttps.proxyHost= -Dhttps.proxyPort= \
-Dsurefire.failIfNoSpecifiedTests=false
该 IT 必须至少覆盖以下 8 个测试,XML 最低 tests 为 8:
| Test class | 最低 tests |
|---|---|
P1rMarketDiscoveryFavoriteCompletedApprovalIT |
8 |
必须证明:
GET /app-api/muse/marketplace/assets/{assetId}对_test库中的 visible listed asset 返回真实详情、版本、license、category、governance status 和 favorite 状态。GET /app-api/muse/marketplace/assets/{assetId}对 missing 或 invisible asset 返回错误,不泄露非公开资产。GET /app-api/muse/marketplace/categories从真实资产/分类数据生成分类聚合,并明确 exposure summary unavailable / fallback slot。POST /favorite缺少X-Command-Id返回MARKET_COMMAND_ID_REQUIRED;带 commandId 时写入 active favorite fact 和 command fact。- 同一 commandId 重放
POST /favorite不产生重复 favorite fact,返回 replay 语义。 DELETE /favorite带 commandId 后把 favorite fact 置为 inactive,不物理删除审计事实;同一 commandId 重放不重复写入。DELETE /favorite缺少X-Command-Id返回MARKET_COMMAND_ID_REQUIRED,且不写 command fact、不改变 favorite fact。POST /favorite和DELETE /favorite对 missing 或 invisible asset 返回错误,并断言不写 command fact、不写或不改变 favorite fact。
该 IT 必须在测试启动时校验库名以 _test 结尾;密码只能从 P1R_MARKET_COMPLETED_PASSWORD、P1R_FLYWAY_PASSWORD 或 MUSE_POSTGRES_PASSWORD 环境变量读取,不能通过 JVM system property 传入;测试必须断言拒绝 p1r.market.completed.password 或任何 password system property;日志和断言不得输出明文数据库密码。
Task 6:真实 PostgreSQL _test Flyway gate
fresh rerun P1rMarketFlywayMigrationIT。使用独立 _test 库,不能使用生产库或非 _test 库:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_MARKET_TEST_DB=muse_p1r_market_completed_approval_test
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-tc "SELECT 1 FROM pg_database WHERE datname = '$P1R_MARKET_TEST_DB'" | grep -q 1 || \
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-c "CREATE DATABASE $P1R_MARKET_TEST_DB"
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketFlywayMigrationIT.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rMarketFlywayMigrationIT \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="jdbc:postgresql://$MUSE_POSTGRES_HOST:$MUSE_POSTGRES_PORT/$P1R_MARKET_TEST_DB" \
-Dp1r.flyway.user="$MUSE_POSTGRES_USERNAME" \
-Djava.net.useSystemProxies=false \
-DsocksProxyHost= -DsocksProxyPort= \
-Dhttp.proxyHost= -Dhttp.proxyPort= \
-Dhttps.proxyHost= -Dhttps.proxyPort= \
-Dsurefire.failIfNoSpecifiedTests=false
必须检查 XML:
| Test class | 最低 tests |
|---|---|
P1rMarketFlywayMigrationIT |
4 |
必须在该 IT 内新增或补齐以下 assertion,但不得新增迁移或修改业务实现:
muse_market_asset、muse_market_asset_version、muse_market_favorite存在。uk_muse_market_favorite_user_asset、uk_muse_market_favorite_command、idx_muse_market_favorite_user存在。trg_muse_market_favorite_updated_at存在。- 同一
(tenant_id, user_id, asset_id)不能重复 active favorite fact。 - 同一
(tenant_id, command_id)不能重复 command fact。 - favorite status 更新为 inactive 后
updated_attrigger 可执行。
Task 7:P1R mixed gate
运行 mixed gates:
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMarketRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rEventsRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rAiRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rKnowledgeRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rAccountRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rContentRealApiGateTest.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rMetaRealApiGateTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rMarketRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rAccountRealApiGateTest,P1rContentRealApiGateTest,P1rMetaRealApiGateTest \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML:
| Test class | 最低 tests |
|---|---|
P1rApiCoverageReportTest |
6 |
P1rMarketRealApiGateTest |
6 |
P1rEventsRealApiGateTest |
6 |
P1rAiRealApiGateTest |
7 |
P1rKnowledgeRealApiGateTest |
8 |
P1rAccountRealApiGateTest |
4 |
P1rContentRealApiGateTest |
5 |
P1rMetaRealApiGateTest |
4 |
每个 XML 均必须 failures=0、errors=0、skipped=0。
这些 gate 必须共同证明:
- summary 只从
127/106推进到131/102。 - Market 只从
0/32推进到4/28。 - Account 仍保持
10 completed / 23 needs_verification。 - Content 仍保持
0 completed / 51 needs_verification。 - Meta、AI、Knowledge、Events 状态不变。
Task 8:报告与 diff gate
检查 summary:
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
预期:
233 131 102 0 0 0
检查 Market 4/28:
python3 - <<'PY'
import json
from collections import Counter
from pathlib import Path
data = json.loads(Path("docs/superpowers/reports/p1r-api-coverage.json").read_text())
counter = Counter(op["completionStatus"] for op in data["operations"] if op["domain"] == "market")
print(counter)
for op in data["operations"]:
if op["domain"] == "market" and op["operationId"] in {"favoriteAsset", "unfavoriteAsset"}:
print(op["operationId"], op["requiresCommandId"], op["completionStatus"])
PY
预期:
Counter({'needs_verification': 28, 'completed': 4})
favoriteAsset True completed
unfavoriteAsset True completed
检查 OpenAPI diff 只限 Market:
git diff --quiet -- 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/meta/openapi.yaml
git diff --cached --quiet -- 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/meta/openapi.yaml
git diff -- docs/api-contracts/market/openapi.yaml
检查 Market 业务实现不被修改:
git diff --quiet -- muse-cloud/muse-module-market/muse-module-market-server/src/main/java
git diff --cached --quiet -- muse-cloud/muse-module-market/muse-module-market-server/src/main/java
检查 whitespace:
git diff --check
检查 allowed diff:
git -c core.quotePath=false status --short
输出只能包含本执行版允许路径。若出现非批准 OpenAPI、业务实现、迁移或非批准 gate 文件,必须停止。
Task 9:memory 与 .agent
实现通过后新增:
docs/memorys/2026-06-11-P1RMarket状态推进.md
内容必须记录:
- 批准的 4 个 Market operation。
- 保持
needs_verification的 28 个 Market operation 及原因,必须点名listMarketplaceAssets与listMarketplaceRecommendations。 - OpenAPI commandId 合同修正范围。
listMarketplaceRecommendations未进入本轮 completed,原因是个性化推荐 OpenAPI 描述与 fallback 排序实现未闭合。listMarketplaceAssets未进入本轮 completed,原因是 pageNo/pageSize 边界证据未闭合。- scanner/report/gate 修改范围。
- 所有验证命令、结果、XML 计数、Market HTTP+DB
_test库名、Flyway_test库名。 - protected diff 与 allowed diff 结果。
- 明确说明不代表 Market 32/32 completed,不代表 Account remaining 23 / Content / 总 P1R completed。
同时更新 docs/agent-specs/.agent,但只能记录事实,不写未验证结论。
Task 10:fresh implementation review
实现、验证和文档留痕后,必须派发两类 fresh reviewer:
- spec/correctness reviewer:检查 4 个 operation 是否严格匹配本执行版,28 个 operation 是否仍 needs_verification,Market domain allowlist 是否未新增,OpenAPI commandId 修正是否只限 favorite/unfavorite。
- quality/data-integrity/testing reviewer:检查 scanner/report/gate、legacy mixed gate 同步、HTTP+DB
_test、XML 防空跑、Flyway_test、allowed/protected diff、rollback 是否可靠。
双 PASS 前不得提交、push 或宣称 Market completed approval 已收口。
回滚策略
如实现后需要撤回:
- 从
APPROVED_COMPLETED_OPERATIONS移除 4 个market:*key。 - 处理
docs/api-contracts/market/openapi.yaml中 favorite/unfavorite 的 requiredX-Command-Idheader:- 如果用户要求完整撤回本轮合同修正,则移除 header。
- 如果用户单独决定保留实现与 OpenAPI 一致的 commandId 合同,则保留 header,只撤回 completed approval。
- 重新运行:
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
- 恢复 gate 期望。完整撤回 OpenAPI header 时:
summary completed=127
summary needsVerification=106
market completed=0
market needsVerification=32
favoriteAsset requiresCommandId=false
unfavoriteAsset requiresCommandId=false
如果保留 OpenAPI commandId 合同,则 gate 必须恢复为:
summary completed=127
summary needsVerification=106
market completed=0
market needsVerification=32
favoriteAsset requiresCommandId=true
unfavoriteAsset requiresCommandId=true
- 修订本轮 memory 并保留失败原因;除非用户明确要求,不直接删除失败留痕。
- 重新运行 Market/P1R focused gates 和
git diff --check。
验收标准
执行版本身可以进入实现前批准点的条件:
- 本文件已写入
docs/agent-specs/2026-06-11-P1RMarketCompletedApproval执行版.md。 .agent记录执行版当前状态。git diff --check通过。- OpenAPI、scanner、coverage report、业务实现当前无新增 diff;
market/openapi.yaml也必须在用户批准前保持无 diff。 - fresh execution spec/scope review PASS。
- fresh execution quality/feasibility review PASS。
实现完成条件必须等用户批准后另行满足,不由本执行版写入自动成立。