test(p1r): 推进 AI 与 Knowledge 完成状态

This commit is contained in:
zizi 2026-06-03 15:56:25 +08:00
parent 48c750bbd7
commit 1f0b18534c
7 changed files with 556 additions and 337 deletions

View File

@ -0,0 +1,178 @@
# P1R-4 / P1R-5 完成状态推进留痕
日期:2026-06-03
## 阶段
- P1R-4 AI / New-API Real API。
- P1R-5 Knowledge / RAGFlow Real API。
## 结论
本次在用户明确批准后,只把 P1R-4 AI 与 P1R-5 Knowledge 的 coverage `completionStatus` 从 `needs_verification` 推进到 `completed`。
本次没有推进 P1R-1 Content、P1R-2 Meta、P1R-3 Account、P1R-6 Market 或 P1R-7 Events。
## 执行位置
```text
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
```
分支:
```text
dev/1.0.0
```
## 已验证事实
开始前已确认:
```text
## dev/1.0.0...origin/dev/1.0.0
Already up to date.
HEAD 48c750b test(p1r): 补齐 AI 与 Knowledge 外部端到端验收
```
用户批准前,coverage 状态为:
```text
AI 41 dedicated / needs_verification
Knowledge 59 dedicated / needs_verification
completedOperations = 0
```
用户批准后,本次生成的 coverage 状态为:
```text
completedOperations 100
needsVerificationOperations 100
incompleteOperations 33
genericPersistenceOperations 32
ssePlaceholderOperations 1
```
按域统计:
```text
account 33 dedicated / needs_verification
ai 41 dedicated / completed
content 51 dedicated / needs_verification
events 1 sse_placeholder / incomplete
knowledge 59 dedicated / completed
market 32 generic_persistence / incomplete
meta 16 dedicated / needs_verification
```
`completed` 只来自:
```text
41 ai dedicated
59 knowledge dedicated
```
本次修改文件:
```text
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/P1rAiRealApiGateTest.java
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/P1rKnowledgeRealApiGateTest.java
muse-cloud/scripts/p1r-audit-api-coverage.py
```
本次未修改:
```text
docs/api-contracts/ai/openapi.yaml
docs/api-contracts/knowledge/openapi.yaml
```
## 验证命令与结果
coverage 生成与校验:
```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
```
preflight jq 统计:
```bash
jq -r '.summary | [.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
```
结果:
```text
100 100 33 32 1
account 33 dedicated/needs_verification:33
ai 41 dedicated/completed:41
content 51 dedicated/needs_verification:51
events 1 sse_placeholder/incomplete:1
knowledge 59 dedicated/completed:59
market 32 generic_persistence/incomplete:32
meta 16 dedicated/needs_verification:16
```
Maven gate:
```bash
cd muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -pl muse-server -Dtest=P1rApiCoverageReportTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest test
```
结果:
```text
P1rKnowledgeRealApiGateTest: Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
P1rAiRealApiGateTest: Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
P1rApiCoverageReportTest: Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
Total: Tests run: 19, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
```
diff 检查:
```bash
git diff --check
```
结果:无输出。
## 关键边界
- 本次 `completed` 推进依赖用户明确批准和前序 P1R-4 / P1R-5 外部端到端验收证据。
- `dedicated gate PASS` 仍不等同于 `completed`;只有本次批准覆盖的 AI / Knowledge 被推进。
- GraphRAG 当前仍只有 `ATTRIBUTION_NOT_CONFIGURED` fail-closed 边界证据,不作为 P1R-5 正向 completed 证据。
- Market 仍停留在 P1R-6 `generic_persistence / incomplete`。
- Events 仍停留在 P1R-7 `sse_placeholder / incomplete`。
## 执行协作规则
后续继续 P1R 主线时,implementation agent 的复用规则如下:
- 同一实现任务内,复用最近一次负责该任务的 implementer,避免同一任务反复 fresh implementer 丢失上下文。
- 只有进入新的实现 Task 时,才启用 fresh implementer。
- 每个实现 Task 完成后的 review gate 不复用 reviewer,仍保持 fresh spec review 和 fresh quality / feasibility review。
- review 结论只能证明对应 gate 的检查结果,不能替代真实运行态验收或 coverage `completed` 批准。
## 后续动作
如需正式收口本轮变更,建议提交前再次执行:
```bash
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
cd muse-cloud && JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -pl muse-server -Dtest=P1rApiCoverageReportTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest test
git diff --check
```

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
# P1R API Coverage Report
- Generated at: `2026-05-25T04:58:59+00:00`
- Generated at: `2026-05-25T02:27:08+00:00`
- Total operations: `233`
- Needs verification: `200`
- Completed: `100`
- Needs verification: `100`
- Incomplete: `33`
- Catch-all: `0`
- Generic persistence: `32`
@ -46,47 +47,47 @@
| account | app | GET | `/app-api/muse/me` | `getCurrentUser` | dedicated | needs_verification | P1R-3 Account Real API |
| account | app | GET | `/app-api/muse/profile` | `getProfile` | dedicated | needs_verification | P1R-3 Account Real API |
| account | app | PATCH | `/app-api/muse/profile` | `updateProfile` | dedicated | needs_verification | P1R-3 Account Real API |
| ai | admin | GET | `/admin-api/muse/ai/agents` | `adminListAgents` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/agents` | `adminCreateAgent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/agents/{agentId}/versions` | `adminCreateAgentVersion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/evaluation-runs` | `adminStartEvaluationRun` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/evaluation-runs/{runId}` | `adminGetEvaluationRun` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/prompts` | `adminListPrompts` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/prompts/{promptKey}/versions` | `adminCreatePromptVersion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/prompts/{promptKey}/versions/{version}/activate` | `adminActivatePromptVersion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/quality-policies` | `adminListQualityPolicies` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/quality-policies/{policyKey}/versions` | `adminCreateQualityPolicyVersion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/tasks` | `adminListAiTasks` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/tool-grants` | `adminListToolGrants` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/tool-grants` | `adminCreateOrAdjustToolGrant` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/api-logs` | `adminListApiAccessLogs` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/api-logs/{logId}` | `adminGetApiAccessLog` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/business-events` | `adminListBusinessAuditEvents` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/business-events/{eventId}` | `adminGetBusinessAuditEvent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/jobs` | `adminListJobs` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/jobs/{jobId}` | `adminGetJob` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/jobs/{jobId}/cancel` | `adminCancelJob` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/jobs/{jobId}/retry` | `adminRetryJob` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/source-events` | `adminListSourceEvents` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/source-events/{eventId}` | `adminGetSourceEvent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/source-events/{eventId}/retry` | `adminRetrySourceEvent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/agents` | `listUserAgents` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents` | `createUserAgent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents/{agentId}/test` | `testAgent` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents/{agentId}/versions` | `createAgentVersion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/ai/tasks` | `createAiTask` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/ai/tasks/{taskId}` | `getAiTask` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/ai/tasks/{taskId}/stream` | `streamAiTask` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/jobs/{jobId}` | `getUserJob` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/jobs/{jobId}/cancel` | `cancelUserJob` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/source-status/query` | `querySourceStatus` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/source-status/recheck` | `recheckSourceStatus` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/suggestions/{suggestionId}` | `getSuggestion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/suggestions/{suggestionId}/reject` | `rejectSuggestion` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/works/{workId}/agent-slots` | `listWorkAgentSlots` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/works/{workId}/agent-slots/{slotKey}/bind` | `bindAgentSlot` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/works/{workId}/agent-slots/{slotKey}/prechecks` | `precheckAgentSlot` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/works/{workId}/suggestions` | `listWorkSuggestions` | dedicated | needs_verification | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/agents` | `adminListAgents` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/agents` | `adminCreateAgent` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/agents/{agentId}/versions` | `adminCreateAgentVersion` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/evaluation-runs` | `adminStartEvaluationRun` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/evaluation-runs/{runId}` | `adminGetEvaluationRun` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/prompts` | `adminListPrompts` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/prompts/{promptKey}/versions` | `adminCreatePromptVersion` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/prompts/{promptKey}/versions/{version}/activate` | `adminActivatePromptVersion` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/quality-policies` | `adminListQualityPolicies` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/quality-policies/{policyKey}/versions` | `adminCreateQualityPolicyVersion` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/tasks` | `adminListAiTasks` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/ai/tool-grants` | `adminListToolGrants` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/ai/tool-grants` | `adminCreateOrAdjustToolGrant` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/api-logs` | `adminListApiAccessLogs` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/api-logs/{logId}` | `adminGetApiAccessLog` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/business-events` | `adminListBusinessAuditEvents` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/audit/business-events/{eventId}` | `adminGetBusinessAuditEvent` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/jobs` | `adminListJobs` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/jobs/{jobId}` | `adminGetJob` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/jobs/{jobId}/cancel` | `adminCancelJob` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/jobs/{jobId}/retry` | `adminRetryJob` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/source-events` | `adminListSourceEvents` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | GET | `/admin-api/muse/source-events/{eventId}` | `adminGetSourceEvent` | dedicated | completed | P1R-4 AI Real API |
| ai | admin | POST | `/admin-api/muse/source-events/{eventId}/retry` | `adminRetrySourceEvent` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/agents` | `listUserAgents` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents` | `createUserAgent` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents/{agentId}/test` | `testAgent` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/agents/{agentId}/versions` | `createAgentVersion` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/ai/tasks` | `createAiTask` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/ai/tasks/{taskId}` | `getAiTask` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/ai/tasks/{taskId}/stream` | `streamAiTask` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/jobs/{jobId}` | `getUserJob` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/jobs/{jobId}/cancel` | `cancelUserJob` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/source-status/query` | `querySourceStatus` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/source-status/recheck` | `recheckSourceStatus` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/suggestions/{suggestionId}` | `getSuggestion` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/suggestions/{suggestionId}/reject` | `rejectSuggestion` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/works/{workId}/agent-slots` | `listWorkAgentSlots` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/works/{workId}/agent-slots/{slotKey}/bind` | `bindAgentSlot` | dedicated | completed | P1R-4 AI Real API |
| ai | app | POST | `/app-api/muse/works/{workId}/agent-slots/{slotKey}/prechecks` | `precheckAgentSlot` | dedicated | completed | P1R-4 AI Real API |
| ai | app | GET | `/app-api/muse/works/{workId}/suggestions` | `listWorkSuggestions` | dedicated | completed | P1R-4 AI Real API |
| content | admin | GET | `/admin-api/muse/content/export-tasks` | `adminListExportTasks` | dedicated | needs_verification | P1R-1 Content Real API |
| content | admin | GET | `/admin-api/muse/content/import-tasks` | `adminListImportTasks` | dedicated | needs_verification | P1R-1 Content Real API |
| content | admin | GET | `/admin-api/muse/content/works` | `adminListWorks` | dedicated | needs_verification | P1R-1 Content Real API |
@ -139,65 +140,65 @@
| content | app | GET | `/app-api/muse/works/{workId}/planning/style-checks/{jobId}` | `getStyleCheckResult` | dedicated | needs_verification | P1R-1 Content Real API |
| content | app | PUT | `/app-api/muse/works/{workId}/planning/{sectionKey}` | `savePlanningItem` | dedicated | needs_verification | P1R-1 Content Real API |
| events | app | GET | `/app-api/muse/events` | `streamEvents` | sse_placeholder | incomplete | P1R-7 End-to-End Acceptance |
| knowledge | admin | GET | `/admin-api/muse/knowledge/drafts` | `listKnowledgeDraftsGovernance` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs` | `listGlobalKnowledgeBases` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs` | `createGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}` | `getGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | PATCH | `/admin-api/muse/knowledge/global-kbs/{kbId}` | `updateGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies` | `listGlobalKBAccessPolicies` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies/drafts` | `saveGlobalKBAccessPolicyDraft` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies/drafts/{draftId}/publish` | `publishGlobalKBAccessPolicy` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/disable` | `disableGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents` | `listGlobalKBDocuments` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents` | `uploadGlobalKBDocument` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | DELETE | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}` | `deleteGlobalKBDocument` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}` | `getGlobalKBDocument` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}/versions` | `createGlobalKBDocumentVersion` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/enable` | `enableGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/impact-preview` | `previewGlobalKBImpact` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/processing-tasks` | `listGlobalKBProcessingTasks` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/reindex` | `reindexGlobalKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/source-events` | `triggerGlobalKBSourceEvent` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/versions` | `listGlobalKBVersions` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/versions/{version}/activate` | `activateGlobalKBVersion` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/projection-tasks` | `listProjectionTasks` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/source-bindings` | `listSourceBindings` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/entities/{entityId}` | `getEntity` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | PUT | `/app-api/muse/entities/{entityId}` | `updateEntity` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/entities/{entityId}/relations` | `listRelations` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/entities/{entityId}/relations` | `createRelation` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/installed-knowledge-bases` | `listInstalledKnowledgeBases` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/installed-knowledge-bases/{installId}` | `deleteInstalledKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/installed-knowledge-bases/{installId}/disable` | `disableInstalledKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/installed-knowledge-bases/{installId}/restore` | `restoreInstalledKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases` | `listKnowledgeBases` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases` | `createKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/knowledge-bases/{kbId}` | `deleteKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}` | `getKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | PATCH | `/app-api/muse/knowledge-bases/{kbId}` | `updateKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/disable` | `disableKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/documents` | `listKBDocuments` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/documents` | `uploadKBDocument` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}` | `deleteKBDocument` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}/versions` | `listKBDocumentVersions` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}/versions` | `createKBDocumentVersion` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/export-tasks` | `createKBExportTask` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/processing-tasks/{taskId}` | `getKBProcessingTask` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-prechecks` | `createKBPublishReadiness` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-readiness` | `createKBMarketPublishReadiness` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-snapshots` | `createKBPublishSnapshot` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/reindex` | `reindexKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/restore` | `restoreKnowledgeBase` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/confirm` | `confirmKnowledgeDraft` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/ignore` | `ignoreKnowledgeDraft` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/recheck` | `recheckKnowledgeDraft` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/entities` | `listEntities` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/graph` | `getKnowledgeGraph` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/works/{workId}/knowledge-bindings` | `createKnowledgeBinding` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/works/{workId}/knowledge-bindings/prechecks` | `createKnowledgeBindingPrecheck` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/works/{workId}/knowledge-bindings/{bindingId}` | `deleteKnowledgeBinding` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/knowledge-drafts` | `listKnowledgeDrafts` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/local-knowledge` | `getLocalKnowledge` | dedicated | needs_verification | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/drafts` | `listKnowledgeDraftsGovernance` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs` | `listGlobalKnowledgeBases` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs` | `createGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}` | `getGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | PATCH | `/admin-api/muse/knowledge/global-kbs/{kbId}` | `updateGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies` | `listGlobalKBAccessPolicies` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies/drafts` | `saveGlobalKBAccessPolicyDraft` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/access-policies/drafts/{draftId}/publish` | `publishGlobalKBAccessPolicy` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/disable` | `disableGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents` | `listGlobalKBDocuments` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents` | `uploadGlobalKBDocument` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | DELETE | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}` | `deleteGlobalKBDocument` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}` | `getGlobalKBDocument` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/documents/{documentId}/versions` | `createGlobalKBDocumentVersion` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/enable` | `enableGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/impact-preview` | `previewGlobalKBImpact` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/processing-tasks` | `listGlobalKBProcessingTasks` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/reindex` | `reindexGlobalKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/source-events` | `triggerGlobalKBSourceEvent` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/global-kbs/{kbId}/versions` | `listGlobalKBVersions` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | POST | `/admin-api/muse/knowledge/global-kbs/{kbId}/versions/{version}/activate` | `activateGlobalKBVersion` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/projection-tasks` | `listProjectionTasks` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | admin | GET | `/admin-api/muse/knowledge/source-bindings` | `listSourceBindings` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/entities/{entityId}` | `getEntity` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | PUT | `/app-api/muse/entities/{entityId}` | `updateEntity` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/entities/{entityId}/relations` | `listRelations` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/entities/{entityId}/relations` | `createRelation` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/installed-knowledge-bases` | `listInstalledKnowledgeBases` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/installed-knowledge-bases/{installId}` | `deleteInstalledKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/installed-knowledge-bases/{installId}/disable` | `disableInstalledKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/installed-knowledge-bases/{installId}/restore` | `restoreInstalledKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases` | `listKnowledgeBases` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases` | `createKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/knowledge-bases/{kbId}` | `deleteKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}` | `getKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | PATCH | `/app-api/muse/knowledge-bases/{kbId}` | `updateKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/disable` | `disableKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/documents` | `listKBDocuments` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/documents` | `uploadKBDocument` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}` | `deleteKBDocument` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}/versions` | `listKBDocumentVersions` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/documents/{documentId}/versions` | `createKBDocumentVersion` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/export-tasks` | `createKBExportTask` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/knowledge-bases/{kbId}/processing-tasks/{taskId}` | `getKBProcessingTask` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-prechecks` | `createKBPublishReadiness` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-readiness` | `createKBMarketPublishReadiness` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/publish-snapshots` | `createKBPublishSnapshot` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/reindex` | `reindexKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-bases/{kbId}/restore` | `restoreKnowledgeBase` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/confirm` | `confirmKnowledgeDraft` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/ignore` | `ignoreKnowledgeDraft` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/knowledge-drafts/{draftId}/recheck` | `recheckKnowledgeDraft` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/entities` | `listEntities` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/graph` | `getKnowledgeGraph` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/works/{workId}/knowledge-bindings` | `createKnowledgeBinding` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | POST | `/app-api/muse/works/{workId}/knowledge-bindings/prechecks` | `createKnowledgeBindingPrecheck` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | DELETE | `/app-api/muse/works/{workId}/knowledge-bindings/{bindingId}` | `deleteKnowledgeBinding` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/knowledge-drafts` | `listKnowledgeDrafts` | dedicated | completed | P1R-5 Knowledge Real API |
| knowledge | app | GET | `/app-api/muse/works/{workId}/local-knowledge` | `getLocalKnowledge` | dedicated | completed | P1R-5 Knowledge Real API |
| market | admin | GET | `/admin-api/muse/market/appeals` | `adminListAppeals` | generic_persistence | incomplete | P1R-6 Market Real API |
| market | admin | GET | `/admin-api/muse/market/appeals/{appealId}` | `adminGetAppeal` | generic_persistence | incomplete | P1R-6 Market Real API |
| market | admin | POST | `/admin-api/muse/market/appeals/{appealId}/resolve` | `adminResolveAppeal` | generic_persistence | incomplete | P1R-6 Market Real API |

View File

@ -19,8 +19,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
/**
* P1R-4 Task 10 AI 真实 API 覆盖门禁。
*
* <p>Task 10 收口时 AI 41 个 operation 必须全部由 dedicated Controller 持有,并且只能推进到
* needs_verification,不能因为覆盖矩阵更新而标记 completed。</p>
* <p>AI 41 个 operation 必须全部由 dedicated Controller 持有。本 gate 只校验用户批准后的 coverage
* 状态推进,不重新证明 P1R-4 live acceptance 证据。</p>
*/
class P1rAiRealApiGateTest {
@ -104,24 +104,24 @@ class P1rAiRealApiGateTest {
}
@Test
void should_keep_all_ai_operations_dedicated_and_needs_verification() throws IOException {
void should_keep_all_ai_operations_dedicated_and_completed_after_approval() throws IOException {
JsonNode aiOperations = readAiOperations();
for (JsonNode operation : aiOperations) {
String operationId = operation.path("operationId").asText("<missing-operationId>");
assertEquals("dedicated", operation.path("implementationStatus").asText(),
operationId + " 当前 P1R-4 Task 10 目标必须是 dedicated");
assertEquals("needs_verification", operation.path("completionStatus").asText(),
operationId + " 当前 P1R-4 Task 10 只能是 needs_verification,不能提前 completed");
operationId + " 当前 P1R-4 目标必须保持 dedicated");
assertEquals("completed", operation.path("completionStatus").asText(),
operationId + " 已按批准从 needs_verification 推进到 completed");
}
}
@Test
void should_keep_completed_operations_zero() throws IOException {
void should_count_ai_and_knowledge_operations_as_completed() throws IOException {
JsonNode report = readReport();
assertEquals(0, report.path("summary").path("completedOperations").asInt(),
"没有真实端到端验收证据时,任何 operation 都不能标 completed");
assertEquals(100, report.path("summary").path("completedOperations").asInt(),
"completedOperations 必须只来自 AI 41 + Knowledge 59");
}
@Test

View File

@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* P1R API 覆盖矩阵门禁测试。
*
* <p>该测试不证明业务 API 已完成,只防止覆盖矩阵缺字段,或把占位实现误标为完成。</p>
* <p>该测试不重新证明业务 API 已完成,只防止覆盖矩阵缺字段,或把未批准域、占位实现误标为完成。</p>
*/
class P1rApiCoverageReportTest {
@ -46,6 +46,12 @@ class P1rApiCoverageReportTest {
"missing"
);
/** 已获用户批准、并有 P1R 外部端到端验收证据支撑的 completed 域。 */
private static final Set<String> APPROVED_COMPLETED_DOMAINS = Set.of(
"ai",
"knowledge"
);
private final ObjectMapper objectMapper = new ObjectMapper();
/**
@ -125,17 +131,23 @@ class P1rApiCoverageReportTest {
}
/**
* 验证 P1R-0 阶段不会把任何 operation 标记为 completed,防止基线报告提前宣称真实 API 完成。
* 验证只有已获批准且仍是 dedicated 的域可以标记 completed,防止其它阶段提前宣称真实 API 完成。
*
* @throws IOException 读取覆盖报告失败时抛出
*/
@Test
void should_not_mark_any_operation_as_completed() throws IOException {
void should_only_mark_approved_dedicated_operations_as_completed() throws IOException {
JsonNode operations = readOperations();
for (JsonNode operation : operations) {
assertFalse("completed".equals(operation.path("completionStatus").asText()),
operation.path("operationId").asText() + " 在 P1R-0 不能标记为 completed");
if (!"completed".equals(operation.path("completionStatus").asText())) {
continue;
}
String operationId = operation.path("operationId").asText("<missing-operationId>");
assertTrue(APPROVED_COMPLETED_DOMAINS.contains(operation.path("domain").asText()),
operationId + " 只有 AI/Knowledge 经批准验收域可以标记为 completed");
assertTrue("dedicated".equals(operation.path("implementationStatus").asText()),
operationId + " 标记 completed 时必须仍是 dedicated 实现");
}
}

View File

@ -20,8 +20,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* P1R-5 Task 10 Knowledge 真实 API 覆盖门禁。
*
* <p>该测试只证明 Knowledge 59 个 operation 已退出合同兜底并进入 dedicated / needs_verification。
* 没有端到端验收证据前,任何 operation 都不能标记 completed。</p>
* <p>该测试只证明 Knowledge 59 个 operation 已退出合同兜底,并在用户批准后从
* needs_verification 推进到 completed。它不重新证明 P1R-5 live acceptance 证据。</p>
*/
class P1rKnowledgeRealApiGateTest {
@ -126,13 +126,13 @@ class P1rKnowledgeRealApiGateTest {
}
@Test
void should_keep_all_knowledge_operations_dedicated_and_needs_verification() throws IOException {
void should_keep_all_knowledge_operations_dedicated_and_completed_after_approval() throws IOException {
for (JsonNode operation : readKnowledgeOperations()) {
String operationId = operation.path("operationId").asText("<missing-operationId>");
assertEquals("dedicated", operation.path("implementationStatus").asText(),
operationId + " 当前 P1R-5 Task 10 必须是 dedicated");
assertEquals("needs_verification", operation.path("completionStatus").asText(),
operationId + " 当前 P1R-5 Task 10 只能是 needs_verification,不能提前 completed");
operationId + " 当前 P1R-5 必须保持 dedicated");
assertEquals("completed", operation.path("completionStatus").asText(),
operationId + " 已按批准从 needs_verification 推进到 completed");
}
}
@ -148,24 +148,24 @@ class P1rKnowledgeRealApiGateTest {
}
@Test
void should_not_mark_any_knowledge_operation_completed() throws IOException {
void should_mark_all_knowledge_operations_completed() throws IOException {
for (JsonNode operation : readKnowledgeOperations()) {
assertFalse("completed".equals(operation.path("completionStatus").asText()),
operation.path("operationId").asText() + " 没有端到端证据前不能标记 completed");
assertEquals("completed", operation.path("completionStatus").asText(),
operation.path("operationId").asText() + " 已获批准后必须标记 completed");
}
}
@Test
void should_keep_completed_operations_zero() throws IOException {
void should_count_ai_and_knowledge_operations_as_completed() throws IOException {
JsonNode report = readReport();
assertEquals(0, report.path("summary").path("completedOperations").asInt(),
"P1R-5 Task 10 不能把任何 operation 推进到 completed");
assertEquals(100, report.path("summary").path("completedOperations").asInt(),
"completedOperations 必须只来自 AI 41 + Knowledge 59");
}
@Test
void should_keep_existing_dedicated_domains_unchanged() throws IOException {
assertDomainStatusCount("ai", 41);
assertDomainStatusCount("ai", 41, "completed");
assertDomainStatusCount("content", 51);
assertDomainStatusCount("meta", 16);
assertDomainStatusCount("account", 33);
@ -192,6 +192,10 @@ class P1rKnowledgeRealApiGateTest {
}
private void assertDomainStatusCount(String domain, int expectedCount) throws IOException {
assertDomainStatusCount(domain, expectedCount, "needs_verification");
}
private void assertDomainStatusCount(String domain, int expectedCount, String expectedCompletionStatus) throws IOException {
int actualCount = 0;
for (JsonNode operation : readOperations()) {
if (!domain.equals(operation.path("domain").asText())) {
@ -201,8 +205,8 @@ class P1rKnowledgeRealApiGateTest {
String operationId = operation.path("operationId").asText("<missing-operationId>");
assertEquals("dedicated", operation.path("implementationStatus").asText(),
domain + "/" + operationId + " 必须保持 dedicated");
assertEquals("needs_verification", operation.path("completionStatus").asText(),
domain + "/" + operationId + " 必须保持 needs_verification");
assertEquals(expectedCompletionStatus, operation.path("completionStatus").asText(),
domain + "/" + operationId + " 必须保持 " + expectedCompletionStatus);
}
assertEquals(expectedCount, actualCount, domain + " operation 数量必须保持不变");
}

View File

@ -43,6 +43,7 @@ SSE_PLACEHOLDER_READY_MARKERS = {
"muse ai task stream ready",
"muse event stream ready",
}
APPROVED_COMPLETED_DOMAINS = {"ai", "knowledge"}
@dataclass(frozen=True)
@ -204,12 +205,13 @@ def classify_implementation(path: str, side: str, method: str, operation_id: str
"SSE endpoint returns placeholder events and needs P1R real task stream implementation.",
)
if matching_dedicated:
dedicated_completion, dedicated_notes = dedicated_status_for(domain)
return status(
"dedicated",
"needs_verification",
dedicated_completion,
matching_dedicated,
matching_services,
"Dedicated entry exists; later P1R stage must verify DTO, state machine, persistence, and real external closure.",
dedicated_notes,
)
if matching_catch_all:
return status(
@ -240,6 +242,19 @@ def status(implementation: str, completion: str, controllers: list[str], service
}
def dedicated_status_for(domain: str) -> tuple[str, str]:
# AI 与 Knowledge 已取得用户批准的端到端验收证据,可以把 coverage 从 needs_verification 推进到 completed。
if domain in APPROVED_COMPLETED_DOMAINS:
return (
"completed",
"Dedicated entry exists; user-approved P1R live external acceptance evidence allows this domain to advance to completed coverage.",
)
return (
"needs_verification",
"Dedicated entry exists; later P1R stage must verify DTO, state machine, persistence, and real external closure.",
)
def files_containing_route_or_operation(
files: list[str],
text_by_file: dict[str, str],
@ -583,6 +598,7 @@ def render_markdown(report: dict[str, Any]) -> str:
"",
f"- Generated at: `{report['generatedAt']}`",
f"- Total operations: `{report['summary']['totalOperations']}`",
f"- Completed: `{report['summary']['completedOperations']}`",
f"- Needs verification: `{report['summary']['needsVerificationOperations']}`",
f"- Incomplete: `{report['summary']['incompleteOperations']}`",
f"- Catch-all: `{report['summary']['catchAllOperations']}`",
@ -642,11 +658,19 @@ def validate_report(report: dict[str, Any]) -> None:
raise SystemExit(
f"{operation['operationId']} non-real implementation must be incomplete or blocked"
)
if operation["completionStatus"] == "completed":
if operation["completionStatus"] == "completed" and not approved_completed_operation(operation):
raise SystemExit(f"{operation['operationId']} is incorrectly marked completed")
if "message" in json.dumps(operation, ensure_ascii=False):
raise SystemExit(f"{operation['operationId']} contains forbidden response evidence field: message")
def approved_completed_operation(operation: dict[str, Any]) -> bool:
# completed 只能来自已批准推进的 dedicated 域,避免 Market、Events 或旧兜底入口被误计完成。
return (
operation["domain"] in APPROVED_COMPLETED_DOMAINS
and operation["implementationStatus"] == "dedicated"
)
if __name__ == "__main__":
raise SystemExit(main())