36 KiB
P1R Content Admin Read Completed Approval 执行版
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:subagent-driven-developmentto implement this plan task-by-task only after fresh execution review double PASS and explicit user approval. Steps use checkbox syntax for tracking.
日期:2026-06-13
结论
本执行版只锁定 Content 管理后台只读模型 3 个 operation-level completed approval:
content:adminListWorks
content:adminGetWork
content:adminListChapters
本轮不把 content 加入 domain-level completed allowlist,不推进 Content 51/51 completed,不修改 OpenAPI,不修改 Content 业务实现,不修改 SQL migration。
获批后目标 coverage summary 为:
total=233
completed=144
needsVerification=89
incomplete=0
genericPersistence=0
ssePlaceholder=0
Content 域目标状态为:
content total=51
completed=13
needsVerification=38
当前阶段只允许写执行方案并进入 fresh execution review。执行版 review 双 PASS 后,仍必须由用户再次明确批准审批清单、operation-level 边界、allowed diff 和 mixed gate 同步范围,才允许实施。
flowchart TB
Current["当前 Content<br/>10 completed / 41 needs_verification"] --> Exec["执行版<br/>锁定 Admin Read 3 ops"]
Exec --> Review["fresh execution spec/scope review<br/>fresh execution quality/testing review"]
Review --> Approval{"用户明确批准<br/>3 ops / operation-level / allowed diff / mixed gates"}
Approval -->|否| Stay["保持当前 coverage<br/>233/141/92"]
Approval -->|是| Red["TDD RED<br/>先改 gate 期望<br/>旧 report 必须失败"]
Red --> Green["TDD GREEN<br/>scanner operation allowlist<br/>regenerate report"]
Green --> Runtime["Admin Read HTTP + real DB _test<br/>RBAC + tenant + no body leak + no-write"]
Runtime --> Verify["focused tests + P1R mixed gates<br/>XML 防空跑 + protected diff"]
Verify --> FreshReview["fresh implementation review"]
当前事实
正确 worktree:
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
当前 HEAD:
2692af3 test(p1r): 收口 Content Planning completed approval 门禁
当前分支:
dev/1.0.0...origin/dev/1.0.0
当前 coverage summary:
233 141 92 0 0 0
当前 domain 状态:
account completed=10 needsVerification=23
content completed=10 needsVerification=41
market completed=4 needsVerification=28
meta completed=16 needsVerification=0
当前 Content 状态:
- Content total 为 51。
- 已有 10 个 operation 为
dedicated / completed:listWorks、getWork、listChapters、getChapter、listBlocks、getBlock、saveBlock、getBlockSourceAttribution、getPlanning、savePlanningItem。 - 本执行版目标 3 个 operation 当前为
dedicated / needs_verification / requiresCommandId=false。 content:adminRiskAction当前为dedicated / needs_verification / requiresCommandId=true,不属于本执行版。APPROVED_COMPLETED_DOMAINS当前只允许ai、knowledge。APPROVED_COMPLETED_OPERATIONS当前包含 Events streamEvents、Meta 16、Account 第一批 10、Market 第一批 4、Content 第一批 8、Content Planning 2。
已验证的只读实现事实:
AdminContentController三个 admin read method 均使用@PreAuthorize("@ss.hasPermission('muse:content:query')")。AdminContentController三个 admin read method 均调用requireApiVersion()读取X-API-Version。- Controller-local mapping 为
/muse/...;对外 OpenAPI 路径为/admin-api/muse/...,执行版必须用当前 Web 测试上下文证明最终 admin API 路径。 ContentAdminServiceImpl.listWorks通过riskFlag读取 governance action work ids,再按 status / keyword / riskWorkIds 分页读取 work,并聚合 risk flags。ContentAdminServiceImpl.getWork读取 work、章节摘要、exception summary 和 governance history,不返回 block 正文。ContentAdminServiceImpl.listChapters读取章节列表,聚合blockCount与wordCount,不返回正文。requireWork(workId)当前调用workMapper.selectById(workId),不是 app owner guard;admin read 的正确安全边界是 admin RBAC + tenant SQL interceptor + 正文不泄露。- 现有 OpenAPI 明确 admin read 默认不返回用户私有正文全文。
- 现有
AdminContentControllerTest/ContentAdminServiceTest只可作为辅助证据,不能替代 completed-grade HTTP + real PostgreSQL_test。
执行边界
必须先获用户明确批准
实现前必须同时获得以下 4 项批准:
- 批准本轮只审批
content:adminListWorks、content:adminGetWork、content:adminListChapters三个 operation。 - 批准继续使用 operation-level approval,不把
content加入 domain-level completed allowlist。 - 批准按本执行版修改 scanner、coverage report、P1R gates、新增 Admin Read HTTP+DB
_test、memory 和.agent。 - 批准同步 mixed gate 的 summary / Content / 非目标域防回退断言,目标为
233/144/89/0/0/0与 Content13 completed / 38 needs_verification。
未获上述批准前,不得实施本执行版。
本轮允许变更
获批后只允许修改以下路径:
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/P1rContentRealApiGateTest.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/P1rMarketRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMetaRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rContentAdminReadCompletedApprovalIT.javamuse-cloud/muse-module-content/muse-module-content-server/src/test/java/cn/iocoder/muse/module/content/application/ContentAdminServiceTest.java,仅限补充本执行版缺失的 focused behavior 证据。muse-cloud/muse-module-content/muse-module-content-server/src/test/java/cn/iocoder/muse/module/content/controller/admin/AdminContentControllerTest.java,仅限补充本执行版缺失的 controller contract 证据。docs/agent-specs/.agentdocs/agent-specs/2026-06-13-P1RContentAdminReadCompletedApproval审阅版.mddocs/agent-specs/2026-06-13-P1RContentAdminReadCompletedApproval执行版.mddocs/memorys/2026-06-13-P1RContentAdminRead状态推进.md
如 implementation 发现必须修改 Content 业务实现、OpenAPI、SQL migration、非批准 gate 或其它文件,必须停下说明原因并重新取得用户批准。
本轮禁止变更
- 不修改 7 个 OpenAPI。
- 不修改 Content main/java 业务实现来掩盖 coverage 缺口。
- 不新增或修改 SQL migration。
- 不把
content加入 domain-level completed allowlist。 - 不推进 Content 51/51 completed。
- 不推进 Account remaining 23、Market remaining 28、Content remaining 38 或总 P1R completed。
- 不推进
content:adminRiskAction、admin import/export task、Content 写命令、AI planning candidate、style check、Meta projection、dynamic fields、FileService、import/export/parse operation。 - 不把 dedicated gate PASS、review PASS、文档结论或已有 Mockito 单测直接等同 completed。
审批清单
| operation key | Method | Path | 目标状态 | 完成证据边界 |
|---|---|---|---|---|
content:adminListWorks |
GET |
/admin-api/muse/content/works |
dedicated / completed |
MockMvc HTTP + 真实 PostgreSQL _test,覆盖 API version、method security RBAC、分页、status / keyword / riskFlag true/false、riskFlag 空结果、治理摘要、tenant 隔离、正文不泄露、纯读 no-write |
content:adminGetWork |
GET |
/admin-api/muse/content/works/{workId} |
dedicated / completed |
MockMvc HTTP + 真实 PostgreSQL _test,覆盖存在、missing、cross tenant、章节摘要、异常摘要、治理历史、正文不泄露、纯读 no-write |
content:adminListChapters |
GET |
/admin-api/muse/content/works/{workId}/chapters |
dedicated / completed |
MockMvc HTTP + 真实 PostgreSQL _test,覆盖章节排序、blockCount、wordCount 聚合、空章节 / NULL wordCount、governance target scope、missing、cross tenant、正文不泄露、纯读 no-write |
保持 needs_verification 的 Content operation
以下 38 个 operation 必须保持 dedicated / needs_verification:
content:adminListExportTasks
content:adminListImportTasks
content:adminRiskAction
content:confirmChapterParseResult
content:rejectChapterParseResult
content:downloadExportPackage
content:getExportTask
content:getImportTask
content:getParseJob
content:listParseJobChapters
content:batchConfirmChapters
content:retryParseJob
content:createWork
content:deleteWork
content:updateWork
content:deleteBlock
content:mergeBlocks
content:splitBlock
content:mergeBlockSuggestion
content:createChapter
content:deleteChapter
content:updateChapter
content:createBlock
content:reorderChapters
content:validateDynamicFields
content:exportWork
content:createExportTask
content:createImportTask
content:listMetaProjections
content:getMetaProjection
content:createParseJob
content:listPlanningCandidates
content:createPlanningCandidate
content:getPlanningCandidate
content:confirmPlanningCandidate
content:discardPlanningCandidate
content:createStyleCheck
content:getStyleCheckResult
证据分层
| Evidence | 文件 / 测试 | 目的 |
|---|---|---|
| Operation inventory / coverage gate | P1rApiCoverageReportTest、P1rContentRealApiGateTest 和 mixed gates |
证明只推进获批 3 个 operation,非目标 domain 不回退 |
Admin HTTP+DB _test |
新增 P1rContentAdminReadCompletedApprovalIT |
证明 3 个 operation 经 MockMvc HTTP 入口访问真实 PostgreSQL _test 数据 |
| Tenant / schema gate | P1rContentAdminReadCompletedApprovalIT 内验证 V1-V21 clean migrate 与 admin read 依赖表 |
证明 Work / Chapter / Block / GovernanceAction schema 和 tenant interceptor 真实可用 |
| Method security gate | P1rContentAdminReadCompletedApprovalIT 内启用 method security 与 ss bean |
证明 admin RBAC 缺权限拒绝不是注解反射假证据 |
| Focused unit/controller tests | ContentAdminServiceTest、AdminContentControllerTest |
支撑 service/controller contract,不替代 HTTP+DB _test |
共同验证规则
每个 Maven 验证任务必须:
- 先
rm -f目标 surefire XML,避免读旧 XML。 - 设置
RUN_START_EPOCH=$(date +%s)。 - Maven 完成后读取目标 XML,检查
mtime >= RUN_START_EPOCH。 - 检查
tests >= 最低 tests、failures=0、errors=0、skipped=0。 - 如果命令失败,保留失败输出和 XML,不得通过跳过测试或降低最低 tests 继续。
XML 防空跑脚本模板:
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 = [
# ("path/to/TEST-Example.xml", min_tests),
]
failed = False
for path, min_tests in checks:
p = Path(path)
if not p.exists():
print(f"missing_xml={path}")
failed = True
continue
mtime = int(p.stat().st_mtime)
if mtime < run_start:
print(f"stale_xml={path} mtime={mtime} run_start={run_start}")
failed = True
root = ET.parse(p).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 期望
获批后先修改:
muse-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/P1rContentRealApiGateTest.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/P1rMarketRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMetaRealApiGateTest.java
RED 期望:
- summary 期望
completed=144、needsVerification=89,但旧 report 仍是141/92,必须失败。 - Content 13 个 approved operation 期望
completed,但adminListWorks、adminGetWork、adminListChapters在旧 report 仍是needs_verification,必须失败。 - Content 38 个未批准 operation 继续期望
needs_verification,其中必须包含adminRiskAction、adminListImportTasks、adminListExportTasks、createWork、updateWork、createChapter、mergeBlockSuggestion、exportWork、listPlanningCandidates、createStyleCheck。 - Account 仍为
10 completed / 23 needs_verification,Market 仍为4 completed / 28 needs_verification,Meta 仍为16 completed / 0 needs_verification,AI/Knowledge/Events 不回退。
运行:
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.P1rContentRealApiGateTest.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.P1rMarketRealApiGateTest.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.P1rMetaRealApiGateTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rContentRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rMarketRealApiGateTest,P1rAccountRealApiGateTest,P1rMetaRealApiGateTest \
-DfailIfNoTests=false \
-Dsurefire.failIfNoSpecifiedTests=false
预期:至少一个失败点来自旧 report 的 141/92 或目标 3 个 admin read operation 尚未 completed。若直接通过,必须停止并排查假绿。
Task 2:TDD GREEN,最小 scanner/report 状态推进
只修改 muse-cloud/scripts/p1r-audit-api-coverage.py:
- 不修改
APPROVED_COMPLETED_DOMAINS。 - 只向
APPROVED_COMPLETED_OPERATIONS追加三个content:*operation key。 - 保持 completed 必须仍是
dedicated的校验。
生成 report:
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
预期 summary:
total=233
completed=144
needsVerification=89
incomplete=0
genericPersistence=0
ssePlaceholder=0
预期 Content:
completed=13
needsVerification=38
预期 scanner 仍不包含 content domain-level allowlist:
python3 - <<'PY'
from pathlib import Path
source = Path("muse-cloud/scripts/p1r-audit-api-coverage.py").read_text()
assert 'APPROVED_COMPLETED_DOMAINS = {"ai", "knowledge"}' in source
for key in ["content:adminListWorks", "content:adminGetWork", "content:adminListChapters"]:
assert key in source
print("content_admin_read_operation_level_allowlist=PASS")
PY
Task 3:Focused Admin unit/controller verification
运行 Content admin focused tests:
cd muse-cloud
export RUN_START_EPOCH=$(date +%s)
rm -f \
muse-module-content/muse-module-content-server/target/surefire-reports/TEST-cn.iocoder.muse.module.content.application.ContentAdminServiceTest.xml \
muse-module-content/muse-module-content-server/target/surefire-reports/TEST-cn.iocoder.muse.module.content.controller.admin.AdminContentControllerTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-module-content/muse-module-content-server -am \
-Dtest=ContentAdminServiceTest,AdminContentControllerTest \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML 并检查 mtime >= RUN_START_EPOCH、failures=0、errors=0、skipped=0:
| Test class | 最低 tests |
|---|---|
ContentAdminServiceTest |
10 |
AdminContentControllerTest |
6 |
Focused tests 必须至少支撑:
listWorksstatus / keyword / governance summary。getWork不返回正文。listChapters不返回正文,且 blockCount / wordCount 聚合正确。- Controller 层
X-API-Version、CommonResult route、@PreAuthorize注解合同。
Focused tests 只作为补充证据,不替代 Task 4 的 HTTP + real DB _test;尤其缺权限拒绝不能只靠 @PreAuthorize 反射断言。
Task 4:Admin Read HTTP + 真实 PostgreSQL _test completed gate
新增 P1rContentAdminReadCompletedApprovalIT,使用独立 _test 数据库、MockMvc HTTP 入口、真实 mapper/service、真实 PostgreSQL 数据。
测试上下文要求:
- 只导入 admin read 必需 controller/service/mapper 与基础 Web/MyBatis/DataSource 自动配置,不做 Content 全包扫描。注意
ContentAdminServiceImpl字段注入还包含ImportTaskMapper、ExportTaskMapper、ContentCommandService、ContentAuditService;即使本切片不调用 import/export/risk 写路径,测试上下文也必须保证这些@Resource依赖可启动,避免 Spring 启动失败。 - 最小 Spring 配置必须复用
P1rContentCoreCompletedApprovalIT/P1rContentPlanningCompletedApprovalIT的 Web/MyBatis/DataSource 模式:JacksonAutoConfiguration、HttpMessageConvertersAutoConfiguration、DataSourceAutoConfiguration、DataSourceTransactionManagerAutoConfiguration、JdbcTemplateAutoConfiguration、TransactionAutoConfiguration、RestTemplateAutoConfiguration、WebMvcAutoConfiguration、MuseDataSourceAutoConfiguration、MuseMybatisAutoConfiguration、MybatisPlusAutoConfiguration、MybatisPlusJoinAutoConfiguration、MuseWebAutoConfiguration。 - 导入
AdminContentController、ContentAdminServiceImpl。 ContentAdminServiceImpl字段依赖中包含ContentCommandService与ContentAuditService。本切片只走读路径,不应调用它们;测试上下文必须提供真实 bean 或 fail-fast test stub 使 Spring 可启动,并在所有 admin read 用例后断言 fail-fast stub 未被调用。- 提供 test-local
ApiErrorLogCommonApistub,返回CommonResult.success(true),满足MuseWebAutoConfiguration/GlobalExceptionHandler依赖。 - 注册
TenantLineInnerInterceptor,通过MyBatisUtils.addInterceptor(interceptor, new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(new TenantProperties())), 0)接入 MyBatis Plus interceptor,确保 cross tenant 断言是真实 SQL tenant 隔离,不只是 seed 数据碰巧不可见。 - 启用 method security。可选方案是导入
MuseWebSecurityConfigurerAdapter并提供最小安全依赖,或在 test configuration 上使用@EnableMethodSecurity(securedEnabled = true)。 - 提供
@Bean("ss")的SecurityFrameworkServicetest double,按测试用例可控返回true/false,并记录收到的 permission;授权成功用例必须断言调用了muse:content:query。缺权限用例必须返回拒绝响应、不泄露 seed 数据,并保持 command/outbox/governance/work/chapter/block no-write;如要证明 service 未执行,可使用 spy bean 或 fail-fast wrapper,但不得把该证明建立在@PreAuthorize反射断言上。 - 使用
WebApplicationContext + MockMvc访问/admin-api/muse/content/works、/admin-api/muse/content/works/{workId}、/admin-api/muse/content/works/{workId}/chapters。 - 同时断言 controller-local
/muse/...不是 completed evidence 的唯一入口;最终证据必须来自/admin-api/muse/...。 - 每个测试启动时设置 admin login user、tenant context,并在测试结束清理
SecurityContextHolder与TenantContextHolder。 - 每个测试前
TRUNCATE muse_content_governance_action, muse_content_block, muse_content_chapter, muse_content_work, muse_content_command_log, muse_content_event_publish_outbox RESTART IDENTITY CASCADE,再 seed 必需数据。Content audit snapshot 当前保存在muse_content_command_log.result_snapshot内,不存在独立 Content audit 表,执行版不得新增该表或把它作为 no-write 断言目标。
建库与运行:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_CONTENT_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_CONTENT_ADMIN_READ_COMPLETED_APPROVAL_TEST_DB=muse_p1r_content_admin_read_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_CONTENT_ADMIN_READ_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_CONTENT_ADMIN_READ_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.P1rContentAdminReadCompletedApprovalIT.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rContentAdminReadCompletedApprovalIT \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="jdbc:postgresql://$MUSE_POSTGRES_HOST:$MUSE_POSTGRES_PORT/$P1R_CONTENT_ADMIN_READ_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
必须检查 XML:
| Test class | 最低 tests |
|---|---|
P1rContentAdminReadCompletedApprovalIT |
10 |
该 IT 必须覆盖以下 10 个测试:
- 拒绝 JVM password system property 和 JDBC credential query,库名必须以
_test结尾。 - V1-V21 clean migrate 后验证 admin read 依赖 schema:
muse_content_work、muse_content_chapter、muse_content_block、muse_content_governance_action表、tenant_id、deleted、work/chapter/block 关联列、基础索引或查询所需列存在。 - Method security 成功路径:
ss.hasPermission("muse:content:query")返回 true 时,GET /admin-api/muse/content/works成功,并记录 permission 调用。 - Method security 拒绝路径:
ss.hasPermission("muse:content:query")返回 false 时,admin read 请求被拒绝,不泄露 seed 数据,并保持 command/outbox/governance/work/chapter/block no-write;该证据必须来自启用 method security 的 HTTP 请求,不能只靠@PreAuthorize反射断言。 adminListWorkshappy path:status、keyword、riskFlag=false返回当前 tenant 普通分页、ownerId、wordCount、chapterCount、risk flags 和 lastGovernanceActionAt,且不泄露正文。adminListWorksrisk path:riskFlag=true只返回当前 tenant 有 governance action 的 work;当前 tenant 无治理动作时返回空页;cross tenant governance action 不影响当前 tenant。adminGetWorkhappy path:返回作品元信息、章节摘要、exception summary、governance history;不返回contentText、content、body等正文字段。adminGetWorkmissing / cross tenant:返回统一错误或 not found 语义,不泄露其它 tenant 数据,且 no-write。adminListChaptershappy path:按orderNo升序返回章节摘要,blockCount 与真实 block 行数一致,wordCount 聚合当前 tenant 数据,空章节或 NULL wordCount 返回 0,governance target scope 对章节 risk flags 生效。adminListChaptersmissing / cross tenant / missing API version:缺X-API-Version返回 CommonResult 错误;missing/cross tenant 不泄露数据;三类负路径均 no-write。
No-write assertion 必须至少覆盖:
muse_content_command_log
muse_content_event_publish_outbox
muse_content_governance_action
muse_content_work
muse_content_chapter
muse_content_block
正文不泄露 assertion 必须至少覆盖 JSON 字符串或 JSON path 中不存在:
contentText
content
body
正文全文
数据库与安全要求:
- 密码只能从
P1R_CONTENT_ADMIN_READ_COMPLETED_PASSWORD、P1R_CONTENT_COMPLETED_PASSWORD、P1R_FLYWAY_PASSWORD或MUSE_POSTGRES_PASSWORD环境变量读取,不能通过 JVM system property 传入。 - JDBC URL 不能携带
user、username、password、pass、pwd、token、secret、api_key、bearer、access_token、refresh_token等凭据 query。 - 如果测试读取并脱敏
p1r.flyway.url/user,必须保存原始 system property 并在@AfterAll恢复。 - 测试输出和断言不得打印明文数据库密码;raw Surefire XML 只能作为本地证据,外发前需清洗 DB host/user。
Task 5:Admin Read + existing Content DB gates 组合验证
运行新增 Admin Read IT 与既有 Content DB gates,防止 Flyway system property、tenant interceptor 或 data source 配置互相污染:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_CONTENT_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_CONTENT_ADMIN_READ_COMPLETED_APPROVAL_TEST_DB=muse_p1r_content_admin_read_combined_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_CONTENT_ADMIN_READ_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_CONTENT_ADMIN_READ_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.P1rContentAdminReadCompletedApprovalIT.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rContentCoreCompletedApprovalIT.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rContentPlanningCompletedApprovalIT.xml \
muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rContentEventsPublishFlywayMigrationIT.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rContentAdminReadCompletedApprovalIT,P1rContentCoreCompletedApprovalIT,P1rContentPlanningCompletedApprovalIT,P1rContentEventsPublishFlywayMigrationIT \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="jdbc:postgresql://$MUSE_POSTGRES_HOST:$MUSE_POSTGRES_PORT/$P1R_CONTENT_ADMIN_READ_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
必须读取以下 XML:
| Test class | 最低 tests |
|---|---|
P1rContentAdminReadCompletedApprovalIT |
10 |
P1rContentCoreCompletedApprovalIT |
12 |
P1rContentPlanningCompletedApprovalIT |
11 |
P1rContentEventsPublishFlywayMigrationIT |
4 |
总计最低 tests 为 37。
Task 6:P1R mixed gates
重新运行并 XML 防空跑:
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.P1rContentRealApiGateTest.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.P1rMarketRealApiGateTest.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.P1rMetaRealApiGateTest.xml
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rContentRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rMarketRealApiGateTest,P1rAccountRealApiGateTest,P1rMetaRealApiGateTest \
-DfailIfNoTests=false \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML:
| Test class | 最低 tests |
|---|---|
P1rApiCoverageReportTest |
6 |
P1rContentRealApiGateTest |
5 |
P1rEventsRealApiGateTest |
7 |
P1rAiRealApiGateTest |
7 |
P1rKnowledgeRealApiGateTest |
8 |
P1rMarketRealApiGateTest |
6 |
P1rAccountRealApiGateTest |
5 |
P1rMetaRealApiGateTest |
5 |
总计最低 tests 为 49;如新增断言导致 tests 增加,XML 最低值可同步提高,但不能低于上表。
Gate 更新要求:
P1rApiCoverageReportTest:expected summary 改为completed=144、needsVerification=89;approved Content completed set 改为 13;断言adminListWorks、adminGetWork、adminListChapterscompleted;仍断言adminRiskAction、adminListImportTasks、adminListExportTasks、createWork、updateWork、createChapter、mergeBlockSuggestion、exportWork、listPlanningCandidates、createStyleCheck为needs_verification。P1rContentRealApiGateTest:approved Content completed set 改为 13;Content count 改为13 completed / 38 needs_verification;代表性未批准 operation 必须包含adminRiskAction、admin import/export task、AI planning candidate / style check 相关 operation。P1rEventsRealApiGateTest、P1rAiRealApiGateTest、P1rKnowledgeRealApiGateTest、P1rMarketRealApiGateTest、P1rAccountRealApiGateTest、P1rMetaRealApiGateTest:同步 summary 文案和 Content count 到13/38,并继续校验 Account10/23、Market4/28、Meta16/0、AI/Knowledge/Events 不回退。
Task 7:Coverage scanner final check
运行:
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[] | select(.domain=="content") | [.operationId,.implementationStatus,.completionStatus,.requiresCommandId] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
预期:
233 144 89 0 0 0
Content 必须精确为 13 completed / 38 needs_verification,且 APPROVED_COMPLETED_DOMAINS 仍不包含 content。
Task 8:Diff gate 与文档留痕
- 更新
.agent,记录 implementation evidence、测试命令、XML 计数、protected diff、review 状态和 remaining boundary。 - 新增或更新
docs/memorys/2026-06-13-P1RContentAdminRead状态推进.md,只记录已验证事实,不把 review PASS 或 gate PASS 写成 Content 51/51 completed。 - 运行 whitespace gate:
git diff --check
- 检查 OpenAPI protected diff 为空:
git -c core.quotePath=false diff -- docs/api-contracts
- 检查 Content main/java 与 SQL migration diff 为空:
git -c core.quotePath=false diff -- muse-cloud/muse-module-content/muse-module-content-server/src/main/java muse-cloud/sql/muse
- 检查 scanner/report/gate/test/doc diff 只落在 allowed list:
git -c core.quotePath=false diff --name-only
git -c core.quotePath=false ls-files --others --exclude-standard
允许路径必须是本执行版“本轮允许变更”列出的路径。出现其它路径时必须停止并说明。
Task 9:Fresh implementation review gate
实现与验证完成后,必须重新派发两个 fresh reviewer:
- fresh implementation spec/correctness reviewer。
- fresh implementation quality/data-integrity/testing reviewer。
两个 reviewer 都必须只读复核:
- 正确 worktree 与 HEAD。
- coverage summary
233/144/89/0/0/0。 - Content 精确为
13 completed / 38 needs_verification。 APPROVED_COMPLETED_DOMAINS未加入content。- scanner 只追加
content:adminListWorks、content:adminGetWork、content:adminListChapters三个 operation-level allowlist。 adminRiskAction、admin import/export task、Content 写命令、AI planning candidate / style check 仍为needs_verification。- OpenAPI、Content main/java、SQL migration diff 为空。
P1rContentAdminReadCompletedApprovalITHTTP + real DB_test证据覆盖 admin RBAC、tenant interceptor、正文不泄露、riskFlag 聚合、missing/cross tenant、no-write。- P1R mixed gates XML 防空跑成立。
fresh implementation review 双 PASS 前,不得提交、push 或宣称 adminListWorks、adminGetWork、adminListChapters completed approval 已收口。
回滚策略
如任一 gate 失败:
- 保留失败输出和 XML 事实,先定位是否是执行版遗漏、测试假设错误、实现缺口或环境问题。
- 不通过修改 OpenAPI、Content main/java 或 SQL migration 来绕过本轮 coverage 缺口。
- 如缺口证明当前实现不足以支撑 completed approval,回退本轮 scanner/report/gate 状态推进,只保留审阅版和执行版文档事实,向用户汇报阻塞。
如需要回退已实施的 operation-level approval:
- 从
APPROVED_COMPLETED_OPERATIONS移除content:adminListWorks、content:adminGetWork、content:adminListChapters。 - 重新运行
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check,恢复 summary233/141/92/0/0/0。 - 恢复 P1R gate 对 Content
10 completed / 41 needs_verification的断言。 - 保留 memory 中的失败事实和回退原因,避免后续重复推进。
自检清单
- 本执行版只覆盖
content:adminListWorks、content:adminGetWork、content:adminListChapters。 - 本执行版未要求把
content加入 domain-level completed allowlist。 - 本执行版未要求修改 OpenAPI、Content main/java 或 SQL migration。
- 38 个保留
needs_verificationoperation 与审阅版一致。 - TDD RED 在 scanner/report 修改前发生。
- HTTP+DB
_test覆盖 admin RBAC、tenant interceptor、API version、admin list/detail/chapter read、riskFlag、正文不泄露和 no-write。 - Method security 缺权限拒绝不只靠
@PreAuthorize反射断言。 - Mixed gates 明确包含 8 个类名,并覆盖 Account、Market、Meta 防回退。
- XML 防空跑有明确 mtime、tests、failures、errors、skipped 规则。
- 实现完成后仍需 fresh implementation review 双 PASS,才允许请求提交/push。