oh-my-muse/docs/agent-specs/2026-06-12-P1RContentPlanningCompletedApproval审阅版.md
zizi 2692af32e7 test(p1r): 收口 Content Planning completed approval 门禁
将 content:getPlanning 与 content:savePlanningItem 纳入 operation-level completed approval,并保留 Content 其余 operation 的 needs_verification 边界。
2026-06-13 02:24:29 +08:00

13 KiB
Raw Blame History

P1R Content Planning Completed Approval 审阅版

日期2026-06-12

结论

推荐 Content 下一批只推进 formal planning section 两个 operation 的 operation-level completed approval

content:getPlanning
content:savePlanningItem

不推荐把剩余 43 个 Content operation 一次性推进 completed也不推荐把 content 加入 domain-level completed allowlist。

这两个 operation 属于 Content 本域正式规划数据,不依赖 AI candidate / style check 外部 owner不依赖 FileService不依赖 Meta projection 运行时,也不需要修 OpenAPI 合同。它们的 completed approval 应独立成一个小切片,用真实 PostgreSQL _test、MockMvc HTTP 入口、V9 planning schema、CAS / command replay / audit / tenant-owner 隔离证据闭合。

本审阅版只冻结下一批候选范围、证据标准、风险边界和后续执行版要求。不修改 OpenAPI不修改 scanner不修改 coverage report不修改业务实现不推进任何 operation completed。

flowchart TB
    Current["当前 Content<br/>8 completed / 43 needs_verification"] --> Choose["选择下一批 evidence slice"]
    Choose --> Planning["推荐formal planning section<br/>getPlanning + savePlanningItem"]
    Choose --> Wider["不推荐:剩余 Content 43 全量推进"]
    Planning --> Boundary{"是否依赖外部 owner?"}
    Boundary -->|否| Evidence["Content 本域 DB evidence<br/>muse_content_planning_section"]
    Boundary -->|AI/File/Meta| Defer["保持 needs_verification"]
    Evidence --> Review["fresh spec/scope review<br/>fresh quality/feasibility review"]
    Review --> Exec["双 PASS 后写执行版"]
    Exec --> Approval{"用户明确批准后才实现"}
    Approval -->|否| Stay["保持 233/139/94"]
    Approval -->|是| Target["目标 233/141/92<br/>Content 10 completed / 41 needs_verification"]

当前事实状态

工作区:

/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0

当前 HEAD

3ced553 test(p1r): 收口 Content 第一批 completed approval 门禁

当前 coverage summary

total=233
completed=139
needsVerification=94
incomplete=0
genericPersistence=0
ssePlaceholder=0

当前 Content 状态:

content total=51
completed=8
needsVerification=43

已 completed 的 Content 第一批 operation

content:listWorks
content:getWork
content:listChapters
content:getChapter
content:listBlocks
content:getBlock
content:saveBlock
content:getBlockSourceAttribution

本审阅版推荐的下一批目标值只是后续获批后的执行目标:

total=233
completed=141
needsVerification=92
incomplete=0
genericPersistence=0
ssePlaceholder=0

content total=51
completed=10
needsVerification=41

推荐候选

operation key Method Path 推荐原因 必补 completed-grade evidence
content:getPlanning GET /app-api/muse/works/{workId}/planning Content 本域正式 planning section 读模型;只依赖 work owner guard 与 muse_content_planning_section MockMvc HTTP + 真实 PostgreSQL _test,覆盖有 section、空 section、latest source snapshot、missing work、cross owner、cross tenant、纯读 no-write
content:savePlanningItem PUT /app-api/muse/works/{workId}/planning/{sectionKey} Content 本域正式 planning section 写路径OpenAPI / VO required 口径一致;已有 command/audit/CAS 实现 MockMvc HTTP + 真实 PostgreSQL _test,覆盖 create expectedRevision=0、update expectedRevision match、command replay、missing command/content/expectedRevision、revision/schema/projection conflict、unique conflict、cross owner/tenant no-write、command/audit snapshot

推荐理由:

  • 两个 operation 只处理正式 planning section所有事实落在 Content owner 自有表 muse_content_planning_section 与 Content command/audit 事实内。
  • OpenAPI SavePlanningItemRequest 已要求 commandIdcontentexpectedRevision,与 SavePlanningItemReqVO@NotBlank / @NotNull 一致;本切片不需要修改 OpenAPI。
  • sourceSnapshot 在 OpenAPI 与 VO 中都是 optional执行版不得把 optional 改成 required也不得借此夹带合同修正。
  • getPlanning / savePlanningItem 可与 AI planning candidate / style check 完全切开,避免把 AI owner runtime closure 混进本轮 completed approval。
  • V9 SQL 已提供 muse_content_planning_section、唯一键 (tenant_id, work_id, section_key)、work 索引和 update_time trigger执行版可以用真实 _test 证明 schema 仍随 V1-V21 clean migrate 生效。

不纳入本批的 operation

以下 41 个 Content operation 必须继续 dedicated / needs_verification

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

排除原因:

  • createWorkupdateWorkdeleteWorkcreateChapterupdateChapterdeleteChaptercreateBlockreorderChapterssplitBlockmergeBlocksdeleteBlock 等结构写命令仍有独立 OpenAPI / commandId / revision 合同闭合风险,应作为后续写命令合同一致性切片。
  • mergeBlockSuggestioncreatePlanningCandidatelistPlanningCandidatesgetPlanningCandidateconfirmPlanningCandidatediscardPlanningCandidatecreateStyleCheckgetStyleCheckResult 依赖 AI owner projection、quality result、candidate state 或 style-check runtime不应借 formal planning section 证据推进。
  • validateDynamicFieldslistMetaProjectionsgetMetaProjection 依赖 Meta owner schema / projection 解释与动态字段校验,不应夹带。
  • createImportTaskgetImportTaskcreateParseJobgetParseJoblistParseJobChaptersconfirmChapterParseResultrejectChapterParseResultbatchConfirmChaptersretryParseJobexportWorkcreateExportTaskgetExportTaskdownloadExportPackage 依赖 FileService、文件产物、解析任务和真实下载闭环。
  • admin read 与 adminRiskAction 需要独立覆盖 admin RBAC、治理摘要、risk flag 聚合、治理动作幂等和审计,不应混入用户端 planning section。

已有实现证据

OpenAPI / VO 口径

OpenAPI 当前路径:

  • GET /app-api/muse/works/{workId}/planningoperationId 为 getPlanning
  • PUT /app-api/muse/works/{workId}/planning/{sectionKey}operationId 为 savePlanningItem

SavePlanningItemRequest 当前 required

commandId
content
expectedRevision

服务端 SavePlanningItemReqVO 当前 required

commandId: @NotBlank
content: @NotNull
expectedRevision: @NotNull

因此本切片不需要修改 docs/api-contracts/content/openapi.yaml

服务实现

ContentPlanningServiceImpl.getPlanning

  • 调用 requireOwnedWork(userId, workId)
  • 查询 PlanningSectionMapper.selectListByWorkId(workId)
  • 返回 sections、最大 revision 和 latest sourceSnapshot

ContentPlanningServiceImpl.savePlanningItem

  • 强校验 commandIdexpectedRevision
  • request hash 绑定 workIdsectionKey
  • 通过 ContentCommandService.reserveCommand 支持幂等 replay。
  • requireOwnedWork(userId, workId) 后读写 muse_content_planning_section
  • 新建 section 要求 expectedRevision=0
  • 更新 section 走 revision CAS并校验 optional expectedSchemaVersion / expectedProjectionVersion
  • 成功后通过 ContentAuditService.recordSucceededWithAudit 写 command/audit result snapshot。

SQL schema

V9 muse_content_planning_section 当前包含:

  • tenant_id
  • work_id
  • section_key
  • content_payload JSONB
  • schema_version
  • projection_version
  • source_snapshot JSONB
  • revision
  • unique (tenant_id, work_id, section_key)
  • index (tenant_id, work_id)
  • trg_muse_content_planning_section_updated_at

执行版必须证明 V1-V21 clean migrate 后 V9 planning schema 仍存在且约束有效。

既有测试

已有单元 / controller 测试覆盖了部分行为:

  • ContentPlanningServiceTest 覆盖 getPlanning 读 sections、owner mismatch、missing command、expectedRevision 冲突、新建、更新、unique conflict、command replay、command/audit result snapshot。
  • AppContentPlanningControllerTest 覆盖 X-API-VersionsavePlanningItem 缺 commandId、owner guard 错误响应、getPlanning / savePlanningItem CommonResult route。

这些是候选证据,不等同 completed。执行版仍必须补 HTTP + real mapper/service + PostgreSQL _test 的 completed-grade evidence。

后续执行版必须包含的验证

执行版至少要定义以下验证,不得只依赖已有 Mockito 单测:

  1. 新增或独立扩展 P1rContentPlanningCompletedApprovalIT,使用 MockMvc HTTP 入口、真实 mapper/service、真实 PostgreSQL _test,只导入 planning section 必需 controller/service/mapper。
  2. Flyway target 使用当前 V1-V21验证 migrations_executed=21,并 mandatory 断言 V9 planning schema
    • muse_content_planning_section 表存在。
    • tenant_id 非空且具备默认值,真实写入后能按 tenant 隔离。
    • content_payload 为 JSONB、非空、默认 '{}'::jsonbsource_snapshot 为 JSONB 且允许为空。
    • schema_versionprojection_versionrevision 非空且默认值为 1
    • unique (tenant_id, work_id, section_key)、index (tenant_id, work_id)trg_muse_content_planning_section_updated_at 存在。
    • 真实 _test 写入必须验证 JSONB 存储、默认 revision/schema/projection、duplicate (tenant_id, work_id, section_key) 被拒绝、CAS 更新后 revision+1 且 update_time 推进。
  3. getPlanning matrix
    • 有 sections返回 sections、revision、latest sourceSnapshot。
    • 空 sections返回空数组、revision=0、sourceSnapshot=null。
    • missing work、cross owner、cross tenant。
    • 纯读路径不写 Content command / planning section / event outbox。
  4. savePlanningItem matrix
    • 新建 sectionexpectedRevision=0,写入 content/sourceSnapshot/schemaVersion/projectionVersion、tenant_id、command/audit snapshot。
    • 更新 sectionexpectedRevision 匹配revision+1CAS 更新生效。
    • command replay同 commandId / 同 request hash 返回首次 result不重复 insert/update。
    • command conflict同 commandId 但不同 request hash 必须返回 CONTENT_COMMAND_ID_CONFLICT,并分别覆盖三个独立 HTTP+real DB 子用例:同 commandId 不同 content、同 commandId 不同 sectionKey、同 commandId 不同 workId三者都必须断言 planning row count/content/revision、command count、audit/result snapshot 均保持首次成功状态。
    • commandId、缺 content、缺 expectedRevision
    • expectedRevision 冲突、schemaVersion 冲突、projectionVersion 冲突。
    • duplicate (tenant_id, work_id, section_key) 转为 revision conflict。
    • missing work、cross owner、cross tenant no-write。
  5. P1R gates
    • P1rApiCoverageReportTest
    • P1rContentRealApiGateTest
    • P1rEventsRealApiGateTest
    • P1rAiRealApiGateTest
    • P1rKnowledgeRealApiGateTest
    • P1rMarketRealApiGateTest
    • P1rAccountRealApiGateTest
    • P1rMetaRealApiGateTest
  6. XML 防空跑必须逐个读取 Surefire XML检查 tests、mtime、failures、errors、skipped不能只看 Maven BUILD SUCCESS。
  7. protected diff
    • OpenAPI diff 必须为空。
    • Content main/java 业务实现 diff 必须为空。
    • SQL migration diff 必须为空。

用户批准点

本审阅版通过 fresh review 后,只能进入执行版编写。

执行版通过 fresh review 后,真正实现前仍必须由用户明确批准:

  1. 只审批 content:getPlanningcontent:savePlanningItem 两个 operation。
  2. 继续 operation-level approval不把 content 加入 domain-level allowlist。
  3. 允许按执行版修改 scanner、coverage report、P1R gates、新增 planning HTTP+DB _test、memory 和 .agent
  4. 允许同步 mixed gate 的 summary / Content / 非目标域防回退断言,目标为 233/141/92/0/0/0 与 Content 10 completed / 41 needs_verification

未获得上述批准前,不得修改 scanner/report/gate不得实现不得提交不得 push不得宣称 Content 10/51 或 51/51 completed。