将 content:getPlanning 与 content:savePlanningItem 纳入 operation-level completed approval,并保留 Content 其余 operation 的 needs_verification 边界。
370 lines
14 KiB
Markdown
370 lines
14 KiB
Markdown
# P1R Content Planning 状态推进
|
||
|
||
日期:2026-06-13
|
||
|
||
## 结论
|
||
|
||
本轮只推进 Content Planning 2 个 operation-level completed approval:
|
||
|
||
- `content:getPlanning`
|
||
- `content:savePlanningItem`
|
||
|
||
Content 仍不是整域 completed。其余 41 个 Content operation 继续 `dedicated/needs_verification`。
|
||
|
||
本轮未修改 OpenAPI,未修改 Content 业务实现,未修改 SQL migration,未把 `content` 加入 domain-level completed allowlist。
|
||
|
||
## 工作区与基线
|
||
|
||
工作区:
|
||
|
||
```text
|
||
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
|
||
```
|
||
|
||
基线 HEAD:
|
||
|
||
```text
|
||
3ced553 test(p1r): 收口 Content 第一批 completed approval 门禁
|
||
```
|
||
|
||
实施前 coverage summary:
|
||
|
||
```text
|
||
233 139 94 0 0 0
|
||
```
|
||
|
||
实施后 coverage summary:
|
||
|
||
```text
|
||
233 141 92 0 0 0
|
||
```
|
||
|
||
实施后 Content 状态:
|
||
|
||
```text
|
||
completed=10
|
||
needs_verification=41
|
||
```
|
||
|
||
目标 operation 状态:
|
||
|
||
```text
|
||
getPlanning dedicated completed false
|
||
savePlanningItem dedicated completed true
|
||
```
|
||
|
||
## 继续 needs_verification 的 Content operation
|
||
|
||
```text
|
||
content:adminListExportTasks
|
||
content:adminListImportTasks
|
||
content:adminListWorks
|
||
content:adminGetWork
|
||
content:adminListChapters
|
||
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
|
||
```
|
||
|
||
## 修改范围
|
||
|
||
本轮修改:
|
||
|
||
- `muse-cloud/scripts/p1r-audit-api-coverage.py`
|
||
- `docs/superpowers/reports/p1r-api-coverage.json`
|
||
- `docs/superpowers/reports/p1r-api-coverage.md`
|
||
- `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/P1rContentRealApiGateTest.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`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountRealApiGateTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMetaRealApiGateTest.java`
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rContentPlanningCompletedApprovalIT.java`
|
||
- `docs/agent-specs/.agent`
|
||
- `docs/agent-specs/2026-06-12-P1RContentPlanningCompletedApproval审阅版.md`
|
||
- `docs/agent-specs/2026-06-12-P1RContentPlanningCompletedApproval执行版.md`
|
||
- `docs/memorys/2026-06-13-P1RContentPlanning状态推进.md`
|
||
|
||
未修改:
|
||
|
||
- 7 个 OpenAPI。
|
||
- Content 业务实现。
|
||
- SQL migration。
|
||
- Content domain-level completed allowlist。
|
||
|
||
## TDD evidence
|
||
|
||
RED 阶段先修改 P1R gate 期望值和 Content Planning 2 个 operation 断言,在旧 scanner/report 下运行 focused P1R gates,预期失败已出现:
|
||
|
||
- 失败点来自旧 report 仍为 `completed=139 / needsVerification=94`。
|
||
- 失败点来自 `content/getPlanning` 仍为 `needs_verification`。
|
||
- 失败点包含 summary 断言 `expected 141 but was 139`。
|
||
|
||
GREEN 阶段完成 scanner operation-level allowlist、report 重新生成、Planning HTTP+DB `_test` evidence 和 focused gates 后,目标验证通过。
|
||
|
||
## MockMvc HTTP 入口 + DB 证据
|
||
|
||
新增:
|
||
|
||
- `muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rContentPlanningCompletedApprovalIT.java`
|
||
|
||
验证方式:
|
||
|
||
- 使用 Spring Mock web context + `MockMvc`。
|
||
- 使用真实 mapper / service。
|
||
- 使用真实 PostgreSQL `_test` 数据库。
|
||
- 使用 Flyway clean/migrate V1-V21。
|
||
- 密码只从环境变量读取,禁止通过 JVM system property 或 JDBC query 传入。
|
||
|
||
说明:这里的 HTTP 入口证据是执行版要求的 WebApplicationContext + MockMvc 请求路径证据,不是启动真实 socket 端口的 live servlet container 证据。
|
||
|
||
单类验证数据库:
|
||
|
||
```text
|
||
muse_p1r_content_planning_completed_approval_test
|
||
```
|
||
|
||
通过结果:
|
||
|
||
```text
|
||
P1rContentPlanningCompletedApprovalIT: tests=11, failures=0, errors=0, skipped=0
|
||
```
|
||
|
||
覆盖内容:
|
||
|
||
- 拒绝 JVM password system property、JDBC credential query 和非 `_test` 数据库。
|
||
- V9 planning schema 门禁:JSONB 类型、nullable/default、`tenant_id` BIGINT NOT NULL DEFAULT 0、`schema_version/projection_version/revision` NOT NULL + default、unique、index、trigger。
|
||
- 直接 JDBC 行为门禁:默认 revision/schema/projection、JSONB 存储、duplicate `(tenant_id, work_id, section_key)` 被 PostgreSQL 以 `23505` 拒绝、不同 tenant 可并存、CAS update 后 revision+1 且 `update_time` 推进。
|
||
- `getPlanning` happy、empty、missing work、cross owner、cross tenant,查询路径不写 command/outbox。
|
||
- `savePlanningItem` create,断言 planning section、sourceSnapshot、command audit snapshot 与 outbox no-write。
|
||
- command/audit snapshot 明细断言覆盖 `tenantId`、`requestHash` 长度、`result.newRevision`、`result.sectionKey`、audit `side/operationId/reason/status/resultSummary`,以及 `requestSummary.operationId/sectionKey/expectedRevision/saveMode`。
|
||
- `savePlanningItem` update,断言 CAS revision、schemaVersion、projectionVersion、sourceSnapshot。
|
||
- `savePlanningItem` replay,不重复推进 revision、不重复写 command。
|
||
- 三类 command conflict no-write:同 `commandId` 不同 content、不同 `sectionKey`、不同 `workId` 均返回 `CONTENT_COMMAND_ID_CONFLICT`,首次 planning row 与 command audit/result snapshot 不变,目标 section/work 不产生脏 row。
|
||
- 缺 `commandId`、缺 `content`、缺 `expectedRevision`、revision conflict、schemaVersion conflict、projectionVersion conflict 均断言 no-write;其中缺 `commandId` 与缺 `content` 已补全租户 command/outbox no-write。
|
||
- missing work、cross owner、cross tenant 均断言事务回滚后无残留 command,并补充全租户 command/outbox 污染断言。
|
||
- missing work、cross owner、cross tenant 均补充目标 planning row no-write:不存在的 work 不创建 row,其他 owner work 不在当前 tenant 创建 row,cross tenant 不污染当前 tenant 或目标 tenant planning row。
|
||
|
||
## 组合验证
|
||
|
||
组合验证使用真实 PostgreSQL `_test` 库:
|
||
|
||
```text
|
||
muse_p1r_content_planning_combined_test
|
||
```
|
||
|
||
首次组合运行失败原因:
|
||
|
||
```text
|
||
P1rContentEventsPublishFlywayMigrationIT.should_migrateV1ToV21OnRealPostgresqlAndVerifyContentPublishOutboxSchema
|
||
缺少必需环境变量: P1R_FLYWAY_PASSWORD 或 MUSE_POSTGRES_PASSWORD
|
||
```
|
||
|
||
根因:
|
||
|
||
- 新增 Planning IT 与 Core IT 接受 `P1R_CONTENT_COMPLETED_PASSWORD`。
|
||
- 既有 Content Events Flyway IT 接受 `P1R_FLYWAY_PASSWORD` 或 `MUSE_POSTGRES_PASSWORD`。
|
||
- 首次组合命令只设置了 `P1R_CONTENT_COMPLETED_PASSWORD`。
|
||
|
||
修正:
|
||
|
||
- 仅调整运行环境,同时设置 `P1R_CONTENT_COMPLETED_PASSWORD` 与 `P1R_FLYWAY_PASSWORD`。
|
||
- 未修改代码。
|
||
|
||
通过结果:
|
||
|
||
```text
|
||
P1rContentPlanningCompletedApprovalIT: tests=11, failures=0, errors=0, skipped=0
|
||
P1rContentCoreCompletedApprovalIT: tests=12, failures=0, errors=0, skipped=0
|
||
P1rContentEventsPublishFlywayMigrationIT: tests=4, failures=0, errors=0, skipped=0
|
||
combined: tests=27, failures=0, errors=0, skipped=0
|
||
```
|
||
|
||
## focused Content tests
|
||
|
||
执行版 Task 3 focused tests 已单独运行,并确认 XML 为本轮 fresh 产物:
|
||
|
||
```text
|
||
ContentPlanningServiceTest: tests=15, failures=0, errors=0, skipped=0, fresh_xml=yes
|
||
AppContentPlanningControllerTest: tests=7, failures=0, errors=0, skipped=0, fresh_xml=yes
|
||
combined focused tests: 22/22 pass
|
||
```
|
||
|
||
## focused gates
|
||
|
||
P1R mixed gates 通过,并已做 XML 防空跑:
|
||
|
||
```text
|
||
P1rApiCoverageReportTest: tests=6, failures=0, errors=0, skipped=0
|
||
P1rContentRealApiGateTest: tests=5, failures=0, errors=0, skipped=0
|
||
P1rEventsRealApiGateTest: tests=7, failures=0, errors=0, skipped=0
|
||
P1rAiRealApiGateTest: tests=7, failures=0, errors=0, skipped=0
|
||
P1rKnowledgeRealApiGateTest: tests=8, failures=0, errors=0, skipped=0
|
||
P1rMarketRealApiGateTest: tests=6, failures=0, errors=0, skipped=0
|
||
P1rAccountRealApiGateTest: tests=5, failures=0, errors=0, skipped=0
|
||
P1rMetaRealApiGateTest: tests=5, failures=0, errors=0, skipped=0
|
||
```
|
||
|
||
合计:
|
||
|
||
```text
|
||
P1R mixed gates: 49/49 pass
|
||
```
|
||
|
||
## scanner 与 diff 证据
|
||
|
||
scanner:
|
||
|
||
```bash
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
Generated docs/superpowers/reports/p1r-api-coverage.json
|
||
Generated docs/superpowers/reports/p1r-api-coverage.md
|
||
233 141 92 0 0 0
|
||
```
|
||
|
||
Content operation 状态确认:
|
||
|
||
```text
|
||
completed=10
|
||
needs_verification=41
|
||
```
|
||
|
||
本轮新增 completed 清单:
|
||
|
||
```text
|
||
getPlanning
|
||
savePlanningItem
|
||
```
|
||
|
||
diff check:
|
||
|
||
```text
|
||
git diff --check: pass
|
||
```
|
||
|
||
protected OpenAPI diff:
|
||
|
||
```text
|
||
empty
|
||
```
|
||
|
||
## fresh review 状态
|
||
|
||
历史 review:
|
||
|
||
- Curie testing/data-integrity review PASS,无 blocker;该结论发生在 Ohm 后续修复之前,当前只作为历史记录。
|
||
- Kepler correctness reviewer 超时后关闭,无可用结论。
|
||
|
||
Ohm fresh correctness/spec review FAIL,3 个 P1 有效:
|
||
|
||
- 缺 `commandId` 与缺 `content` validation 路径未做全租户 command/outbox no-write。
|
||
- command/audit snapshot 断言不足,缺 tenant_id、request_hash、result_snapshot、audit requestSummary/operationId/status/reason 等关键事实。
|
||
- 执行版 Task 3 mandatory focused `ContentPlanningServiceTest` 与 `AppContentPlanningControllerTest` 未运行,XML 证据缺失。
|
||
|
||
已修复并验证:
|
||
|
||
- 缺 `commandId` 与缺 `content` validation 改为全租户 command/outbox no-write。
|
||
- command/audit snapshot 增加 `tenantId`、`requestHash`、`result.newRevision/sectionKey`、audit `side/operationId/reason/status/resultSummary`、`requestSummary.operationId/sectionKey/expectedRevision/saveMode` 断言。
|
||
- Task 3 focused tests fresh 运行,`ContentPlanningServiceTest 15/15` 与 `AppContentPlanningControllerTest 7/7`,XML mtime 均在运行窗口内。
|
||
|
||
本轮 fresh implementation review:
|
||
|
||
- Locke correctness/spec review PASS,确认 scope、scanner、coverage、非目标 operation、Planning IT 和 Ohm 3 个 P1 修复均符合执行版。
|
||
- Locke 残余风险:执行版 allowed diff memory 文件日期写成 `2026-06-12`,实际为 `2026-06-13`;已修订执行版 allowed diff。
|
||
- Hilbert testing/data-integrity review FAIL,2 个 P2 有效:V9 schema gate 未显式断言 `schema_version/projection_version/revision` NOT NULL;missing/cross-owner/cross-tenant no-write 未逐一断言目标 planning row 未创建。
|
||
|
||
Hilbert P2 已修复并验证:
|
||
|
||
- 补 `schema_version`、`projection_version`、`revision` 三列 `columnNullable(...)=NO` 断言。
|
||
- 补 missing work、cross-owner、cross-tenant 当前 tenant 与目标 tenant planning row count 为 0 的断言。
|
||
- 修复后 fresh 重跑 `P1rContentPlanningCompletedApprovalIT`,tests=11、failures=0、errors=0、skipped=0,XML mtime 为 `2026-06-13 01:53:08 +0800`。
|
||
|
||
当前仍需重新派发 fresh implementation spec/correctness re-review + fresh quality/data-integrity/testing re-review;双 PASS 前不得提交或 push。
|
||
|
||
Fresh re-review 已双 PASS:
|
||
|
||
- Epicurus correctness/spec re-review PASS,确认 protected diff 为空、scope 未扩大、scanner 仍只追加 `content:getPlanning` / `content:savePlanningItem`、执行版 allowed diff 已改为实际 memory 路径、Hilbert 两个 P2 已关闭、coverage report 为 `233/141/92/0/0/0` 且 Content 为 `10 completed / 41 needs_verification`。Epicurus 未运行 Maven 测试,只做只读 diff/source/docs/report 复核。
|
||
- Nietzsche testing/data-integrity re-review PASS,确认 schema NOT NULL、missing/cross-owner/cross-tenant 目标 row no-write、缺 `commandId` / 缺 `content` 全租户 command/outbox no-write、command/audit snapshot 解析断言、fresh XML `P1rContentPlanningCompletedApprovalIT 11/11`、`.agent` / memory 留痕和 `git diff --check` 均无新 blocker。Nietzsche 未运行 Maven 测试,只解析现有 XML 并运行只读 diff check。
|
||
|
||
残余风险:
|
||
|
||
- Surefire XML 含本地 classpath、`user.dir`、测试 DB URL 等本机信息,外发前需清洗。
|
||
- 新增 IT 与 memory 当前仍未提交,提交前必须确认纳入正确 commit。
|
||
- 双 PASS 只代表 `content:getPlanning` 与 `content:savePlanningItem` 两个 operation-level completed approval 具备收口条件,不代表 Content 51/51、Account remaining、Market remaining 或总 P1R completed。
|
||
|
||
## final verification
|
||
|
||
Fresh 双 PASS 后已重跑:
|
||
|
||
```text
|
||
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check: pass
|
||
ContentPlanningServiceTest + AppContentPlanningControllerTest: 22/22 pass, fresh XML yes
|
||
P1R mixed gates: 49/49 pass
|
||
Content combined DB gate: 27/27 pass
|
||
git diff --check: pass
|
||
protected OpenAPI / Content main/java / SQL diff: empty
|
||
```
|
||
|
||
正确 jq 验证:
|
||
|
||
```text
|
||
summary: 233 141 92 0 0 0
|
||
Content completed: 10
|
||
Content needs_verification: 41
|
||
getPlanning dedicated completed false
|
||
savePlanningItem dedicated completed true
|
||
listPlanningCandidates dedicated needs_verification false
|
||
createStyleCheck dedicated needs_verification true
|
||
getStyleCheckResult dedicated needs_verification false
|
||
```
|
||
|
||
## 当前边界
|
||
|
||
- 本轮只代表 Content Planning 2 个 operation-level completed approval。
|
||
- 不代表 Content 51/51 completed。
|
||
- 不代表 Account remaining completed。
|
||
- 不代表 Market remaining completed。
|
||
- 不代表总 P1R completed。
|
||
- raw Surefire XML 可能包含 DB host/user;外发前需清洗。
|
||
- 当前具备提交候选条件;提交或 push 仍需用户明确指令。
|