oh-my-muse/docs/archive/2026-06-14-P1RAccountStageA-NewAPIQuotaIntegration解锁执行版.md
lili 0c119d7c6f docs: 归档已完成阶段过程文档至 docs/archive(git mv 保历史)
9 篇工作已完成的过程文档(P1R解锁3篇+agent基建交付+superpowers报告2篇+P1R任务memory+已合并object-storage计划+已折入总览的completion brainstorm)移至 docs/archive/。保留:design-docs(SSOT)、主台账、现状基线、对抗复盘/P0冻结令(知识网根基,被AGENTS/.agents/台账引用)、meta-schema当前2篇、p1r-api-coverage.json(被引数据)、memorys/README。归档非删除,git 可恢复。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 02:50:00 -07:00

28 KiB
Raw Blame History

P1R Account Stage A New-API / Quota / Integration 解锁执行版

日期2026-06-14

结论

本执行版只用于 Stage A 的 implementation plan 审阅,不是 implementation 授权,也不是 completed approval 授权。

Stage A 覆盖 Account 剩余 21 个 operation 中的 9 个 New-API / quota / integration operation。当前仓库已经具备 dedicated Controller、Service、Mapper 和部分单元测试,但仍缺两类关键闭环:

  1. NewApiAccountFacade 的默认 fail-closed Bean 仍以 @Component 注册,真实 facade 与 unavailable facade 并存时存在静默选错或启动歧义风险。
  2. 已验证的 New-API 外部证据只覆盖 OpenAI-compatible chat runtime不覆盖 Account 绑定、重验、额度请求管理端点;不能凭空写 HTTP adapter 并把它当 completed 证据。

推荐路线:

A0 先做 facade 装配硬化和本地 HTTP+DB 闭环准备
A1 查证 New-API Account 管理端点合同
A2/A3 在合同查证后实现 binding runtime 与 quota submit worker
A4 用 Stage A HTTP+DB + opt-in live acceptance 形成 unlock evidence
之后另起 operation-level completed approval

当前事实基线

工作区:

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

本轮 final review 起点基线:

main...origin/main
HEAD=862fe9e docs(p1r): 收敛 Account Stage A 解锁计划
origin/main=862fe9e
origin/dev/1.0.0=862fe9e

当前 coverage summary

total=233
completed=147
needsVerification=86
incomplete=0
genericPersistence=0
ssePlaceholder=0

当前 Account 状态:

total=33
completed=12
needsVerification=21

Stage A 范围

Stage A 只覆盖以下 9 个 operation

operation method path commandId
account:adminListNewApiBindings GET /admin-api/muse/account/new-api-bindings no
account:adminCreateNewApiBinding POST /admin-api/muse/account/users/{userId}/new-api-binding yes
account:getAppNewApiBinding GET /app-api/muse/account/new-api-binding no
account:appRecheckNewApiBinding POST /app-api/muse/account/new-api-binding/recheck yes
account:adminCreateQuotaRequest POST /admin-api/muse/account/users/{userId}/quota-requests yes
account:appCreateQuotaRequest POST /app-api/muse/account/quota-requests yes
account:appGetQuotaRequest GET /app-api/muse/account/quota-requests/{requestId} no
account:adminGetIntegrationCallByCorrelation GET /admin-api/muse/account/integration-calls/by-correlation/{correlationId} no
account:appGetIntegrationCallByCorrelation GET /app-api/muse/account/integration-calls/by-correlation/{correlationId} no

本执行版不覆盖:

  • Account FileService / export / download 3 个 operation。
  • Account usage / attribution 4 个 operation。
  • Market projection 4 个 operation。
  • security ack / session revoke 1 个 operation。
  • Account domain-level completed。
  • scanner、coverage report、OpenAPI 合同变更。

已验证代码事实

当前 Stage A 相关主文件:

  • muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountNewApiBindingServiceImpl.java
  • muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountQuotaServiceImpl.java
  • muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountUsageServiceImpl.java
  • muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/NewApiAccountFacade.java
  • muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/UnavailableNewApiAccountFacade.java

当前行为事实:

  • AccountNewApiBindingServiceImpl.adminCreateNewApiBinding 已通过 NewApiAccountFacade.createOrRefreshBinding 写入 MemberNewApiBindingDOAccountIntegrationCallDO;外部不可用时通过 REQUIRES_NEW 写入 failed/unavailable integration call 后抛错。
  • AccountNewApiBindingServiceImpl.appRecheckNewApiBinding 已通过 NewApiAccountFacade.createRecheckJob 创建 recheck job并要求 job status 只能是 queuedprocessing
  • UnavailableNewApiAccountFacade 当前有 @Component,会作为默认 Bean 进入容器;这与已有 AccountFileServiceFacadeAutoConfigurationMarketAccountProjectionFacadeAutoConfiguration@ConditionalOnMissingBean 模式不一致。
  • NewApiAccountFacade 当前只有 binding sync 与 recheck job 两组方法,没有 quota submit 方法。
  • AccountQuotaServiceImpl.adminCreateQuotaRequestappCreateQuotaRequest 当前只创建本地 AccountIntegrationCallDO(status=pending_attribution)AccountQuotaRequestDO(status=queued),没有提交真实 New-API runtime。
  • AccountUsageServiceImpl 当前直接读取 AccountIntegrationCallDOadmin/detail 不做 owner guardapp/detail 做 owner guard状态映射包含 pending -> pending_attributionunavailable -> failed、未知状态归一为 failed
  • OpenAPI 中 QuotaRequestResult.status 只允许 queuedprocessingidempotent_hitQuotaRequestStatus.status 允许 queuedprocessingcompletedfailedidempotent_hit
  • 现有外部验收留痕只证明 New-API /v1/chat/completions live acceptance不证明 Account binding / quota management endpoint 可用。

架构边界

Stage A 必须保持以下边界:

flowchart LR
    Admin["Admin/App Account API"] --> Account["Account Service<br/>command / audit / local facts"]
    Account --> Binding["muse_member_new_api_binding"]
    Account --> Quota["muse_account_quota_request"]
    Account --> Call["muse_account_integration_call"]
    Account --> Facade["NewApiAccountFacade"]
    Facade --> Runtime["Verified New-API Account Runtime"]
    Runtime -. "callback or worker result" .-> Account

规则:

  • Account 子域持有 Account API、本地 command、audit、binding、quota request、integration call 事实。
  • New-API 只能通过 NewApiAccountFacade 或其明确拆分后的同 owner facade 接入,不能由 Account service 直接散落 HTTP 调用。
  • 没有查证的 New-API Account 管理端点不得被写进真实 adapter。
  • unavailable facade 必须 fail closed不能返回伪造成功。
  • quota request 推荐采用 Account 接收、审计、入队,再由 worker/submitter 提交 New-API不要在 HTTP 请求事务中直接等待外部调用完成。
  • Stage A 默认不新增 Events outboxcommand、audit、quota request、integration call 是本阶段审计边界。

执行切片

A0facade 装配硬化

目标:先消除 UnavailableNewApiAccountFacade @Component 带来的真实 facade 装配风险。

允许在用户批准 implementation 后修改:

  • Modify: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/UnavailableNewApiAccountFacade.java
  • Create: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/autoconfigure/member/account/NewApiAccountFacadeAutoConfiguration.java
  • Modify: muse-cloud/muse-module-member/muse-module-member-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  • Create: muse-cloud/muse-module-member/muse-module-member-server/src/test/java/cn/iocoder/muse/module/member/application/account/facade/NewApiAccountFacadeConfigurationTest.java

必须实现的测试事实:

  • 无真实 NewApiAccountFacade Bean 时,容器只有 1 个 facade类型为 UnavailableNewApiAccountFacade
  • 有真实 NewApiAccountFacade Bean 时unavailable fallback 不注册,context.getBean(NewApiAccountFacade.class) 返回真实 Bean。
  • AutoConfiguration.imports 包含 NewApiAccountFacadeAutoConfiguration
  • fallback 调用 createOrRefreshBindingcreateRecheckJob 时均 fail closed若 A3 扩展 quota 方法quota fallback 也必须 fail closed。

A1New-API Account 管理端点合同查证

目标:在实现真实 HTTP adapter 前,查证 Account 绑定、重验、额度请求的真实 New-API 管理端点。

查证来源优先级:

  1. 本机或远端 new-api 代码、OpenAPI、README、路由表。
  2. 当前部署 http://100.64.0.8:3000 的只读管理接口或健康接口。
  3. 用户提供的系统管理令牌与端点说明。

必须形成的证据:

  • binding create/refresh 端点method、path、auth、request、response、错误码。
  • binding recheck 端点method、path、auth、request、response、job status 枚举、错误码。
  • quota submit 端点method、path、auth、request、response、request/job id、状态枚举、错误码。
  • timeout、5xx、401/403、409、业务错误的失败分类。
  • 哪些字段允许写入 requestSummary / responseSummary,哪些必须脱敏。

如果 A1 无法查证上述端点Stage A implementation 只能完成 A0 和本地闭环测试准备,不能实现 HttpNewApiAccountFacade,不能把 9 个 operation 推进 completed。

A2binding runtime adapter

只有 A1 查证通过后,才允许实现真实 binding adapter。

候选文件:

  • Create: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/framework/config/MuseAccountNewApiProperties.java
  • Create: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/framework/config/MuseAccountNewApiConfiguration.java
  • Create: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/HttpNewApiAccountFacade.java
  • Modify: muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/NewApiAccountFacade.java

属性命名建议:

muse.account.new-api.enabled
muse.account.new-api.base-url
muse.account.new-api.token
muse.account.new-api.connect-timeout-seconds
muse.account.new-api.read-timeout-seconds
muse.account.new-api.max-attempts
muse.account.new-api.retry-backoff-seconds

合同要求:

  • 关闭 enabled 时不注册真实 facade回落 A0 fallback。
  • token 不写日志、不写测试报告、不进入 requestSummary / responseSummary
  • adapter 必须带 correlationId、commandId、accountUserId、bindingId。
  • createOrRefreshBinding 只有在 New-API 返回非空 newApiUserId 后才能写本地 bound
  • createRecheckJob 只有在 New-API 返回非空 jobId 且 status 属于 queued / processing 后才能成功。
  • timeout、认证失败、不可用、未知 response 均映射为 fail closed不伪造 job 或 binding。

A3quota submit worker

目标:补齐 adminCreateQuotaRequestappCreateQuotaRequestappGetQuotaRequest 和 integration detail 的 runtime 闭环。

推荐设计:

  • AccountQuotaServiceImpl 继续负责 HTTP create校验 user、requestType、command 幂等,创建 AccountQuotaRequestDO(status=queued)AccountIntegrationCallDO(status=pending_attribution)
  • 新增 AccountQuotaRequestWorkerAccountQuotaRequestSubmitter 负责把 queued request 提交给 NewApiAccountFacade
  • NewApiAccountFacade 增加 quota submit 合同,而不是在 AccountQuotaServiceImpl 内直接写 HTTP。

候选接口扩展:

NewApiAccountFacade.submitQuotaRequest(QuotaSubmitCommand)
NewApiAccountFacade.QuotaSubmitResult

QuotaSubmitCommand 必须包含:

  • accountUserId
  • requestId
  • commandId
  • correlationId
  • requestType
  • requestedAmount
  • side

QuotaSubmitResult 必须包含:

  • externalCallId
  • status
  • responseSummary
  • failureCode
  • failureMessage

状态规则:

  • create API 初始只返回 OpenAPI 允许的 queuedprocessing,不能返回 completed
  • worker claim 后可把 quota request 更新为 processing
  • New-API 接受成功但异步执行时,appGetQuotaRequest 返回 processing
  • New-API 明确终态成功时,appGetQuotaRequest 返回 completed
  • New-API 明确失败或不可恢复错误时,appGetQuotaRequest 返回 failed,并写 failureReason
  • integration call 对应更新 statusexternalCallIdresponseSummaryerrorCodeerrorMessagefinishedAt

并发与幂等要求:

  • 不新增 SQL migration 时worker 必须复用现有字段承载重试:muse_account_integration_call.retry_countnext_retry_atstatuserrorCodeerrorMessage
  • worker claim 必须使用 tenant 范围内的条件更新,并冻结为单一路径:初次 claim 只允许 quota_request.status=queuedretry / lease 恢复 claim 只允许 quota_request.status=processing 且对应 integration_call.next_retry_at <= now 且 integration call 未 terminal。claim 成功后 quota request 统一保持或进入 processing,并同步把 integration call 改为 retrying 或等价运行态。
  • lease 超时恢复必须由 integration_call.next_retry_at 表达crash 后只扫描 next_retry_at <= now 且未 terminal 的记录。
  • retry budget 必须由 stage implementation 固定,默认 maxAttempts=3;达到上限后 quota request 必须进入 failedintegration call 必须进入 failed 并写失败原因。
  • tenant context 必须在 claim、submit、terminal update 前显式设置,推荐使用 TenantContextHolder.setTenantId(...) 并在 finally 中 clear。
  • terminal update 必须带状态条件,只允许 queued/processing 进入 completed/failed,不得覆盖已 terminal 的 request。
  • command replay 不能重复创建 quota request 或 integration call。
  • 同 commandId 不同 request hash 必须冲突并 no-write。
  • worker 重试不得覆盖已 terminal 的 request。
  • 如果上述状态机需要新增字段或索引,必须先退出当前 Stage A unlock另起 SQL migration 审批并把 V22 schema、mapper、rollback 写入新的 allowed diff。

worker 事务边界必须冻结为短事务模型:

  • claimNext 独立事务:用 tenant + request/call status + next_retry_at 条件原子 claim 一条 quota request初次 claim 匹配 queued,重试和 crash 恢复只匹配 processing + next_retry_at <= now,并同步把 quota request 置为 processing、integration call 置为运行态,同时递增或记录本轮 attempt。该事务提交后才能调用外部 New-API。
  • 外部 New-API submit 不得包在数据库事务内;调用前后必须保留可审计日志,日志只能包含 requestId/correlationId/tenantId/attempt/status/errorCode不得写 token、secret 或完整外部响应。
  • finalizeSuccess 独立事务:仅在 quota request 仍为 processing 且 integration call 仍为本轮运行态时写 completedexternalCallIdresponseSummaryfinishedAt,并清空 next_retry_at;若条件更新为 0必须记录 conflict 日志并停止覆盖。
  • finalizeFailure 独立事务:不可恢复失败或 maxAttempts 用状态条件写 quota request failed、integration call failederrorCodeerrorMessagefinishedAt,并清空 next_retry_at
  • finalizeRetryable 独立事务runtime unavailable、timeout 或外部 5xx 等可重试错误只更新 integration call errorCode/errorMessage/retry_count/next_retry_atquota request 必须保持 processing,不得回写 queued;下一轮 claim 必须由 processing + next_retry_at <= now 驱动;达到 maxAttempts=3 后必须走 finalizeFailure
  • 外部 submit 成功但 finalize 失败时,不得二次提交同一外部请求;后续恢复只能先查 integration call / externalCallId / correlationId 的已有结果,再决定 finalize 或 fail closed。
  • Stage A HTTP+DB / focused tests 必须按 queued -> processing -> completed/failed 唯一路径覆盖double-claim 只有一个 worker 成功、runtime unavailable 只产生 allowed-delta 且 request 保持 processing、finalize conflict 不覆盖 terminal fact、processing + next_retry_at <= now 可恢复、maxAttempts 后 terminal failed。

A4HTTP+DB unlock gate

Stage A implementation 必须新增 HTTP+DB _test 主证据,但该证据只证明 Muse Account 侧真实 HTTP 入口、真实服务、真实 mapper、真实 PostgreSQL 和 facade 合同可闭合;如果使用 test-local facade不得把它写成外部 New-API completed 证据。

推荐新增:

  • Create: muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountStageANewApiQuotaIntegrationUnlockIT.java

必须覆盖:

  • V1-V21 clean migrate数据库名包含 _test
  • adminCreateNewApiBinding success、replay、command conflict、New-API unavailable failed integration call。
  • adminListNewApiBindings 能读取真实 member_user + muse_member_new_api_binding
  • getAppNewApiBinding owner summary不暴露 token、provider authority 或 supplier route。
  • appRecheckNewApiBinding success、invalid job status fail closed、missing binding、replay、command conflict。
  • adminCreateQuotaRequestappCreateQuotaRequest success、replay、command conflict、invalid requestType、missing user。
  • quota worker success / failure / unavailable验证 quota request 与 integration call 状态转移。
  • appGetQuotaRequest owner guard、missing、terminal completed/failed、createdAt/completedAt。
  • adminGetIntegrationCallByCorrelationappGetIntegrationCallByCorrelation no-write、owner guard、敏感字段 allowlist、status/requestType/retryGroup 映射。
  • 参数校验、幂等冲突、越权、cross tenant、missing resource 必须使用全表 no-write snapshot至少覆盖 muse_member_new_api_bindingmuse_account_quota_requestmuse_account_integration_callmuse_account_commandmuse_account_auditmuse_account_event_publish_outbox
  • runtime unavailable 不属于全表 no-write只允许新增或更新一条 failed/unavailable integration call必须用 allowed-delta snapshot 证明 binding/quota request、command succeeded fact、audit succeeded fact 和 outbox 均未产生成功事实。

可选 live acceptance

  • Create: muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountStageANewApiLiveAcceptanceIT.java
  • 默认跳过,仅在显式环境变量开启并提供真实 New-API Account 管理端点配置时运行。
  • 只有该类使用已查证的外部 New-API Account runtime它不能依赖 test-local facade。

验证命令

Maven root

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

A0 facade wiring

JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -pl muse-module-member/muse-module-member-server -am -Dtest=NewApiAccountFacadeConfigurationTest \
  -Dsurefire.failIfNoSpecifiedTests=false test

Stage A focused member tests

JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -pl muse-module-member/muse-module-member-server -am \
  -Dtest=AccountNewApiBindingServiceTest,AccountQuotaServiceTest,AccountUsageServiceTest \
  -Dsurefire.failIfNoSpecifiedTests=false test

Stage A HTTP+DB _test

cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0/muse-cloud
export P1R_ACCOUNT_STAGE_A_DB_NAME="muse_p1r_account_stage_a_test"
export P1R_ACCOUNT_STAGE_A_JDBC_URL="jdbc:postgresql://127.0.0.1:5432/${P1R_ACCOUNT_STAGE_A_DB_NAME}"
export P1R_ACCOUNT_STAGE_A_DB_USER="${P1R_ACCOUNT_STAGE_A_DB_USER:?set test db user}"
export P1R_ACCOUNT_STAGE_A_DB_PASSWORD="${P1R_ACCOUNT_STAGE_A_DB_PASSWORD:?set test db password}"
export P1R_FLYWAY_PASSWORD="${P1R_FLYWAY_PASSWORD:-${P1R_ACCOUNT_STAGE_A_DB_PASSWORD}}"

JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -pl muse-server -am -Dtest=P1rAccountStageANewApiQuotaIntegrationUnlockIT \
  -Dsurefire.failIfNoSpecifiedTests=false test \
  -Dp1r.flyway.locations=filesystem:sql/muse \
  -Dp1r.flyway.url="${P1R_ACCOUNT_STAGE_A_JDBC_URL}" \
  -Dp1r.flyway.user="${P1R_ACCOUNT_STAGE_A_DB_USER}" \
  -Dp1r.account.stage-a.jdbc-url="${P1R_ACCOUNT_STAGE_A_JDBC_URL}" \
  -Dp1r.account.stage-a.jdbc-user="${P1R_ACCOUNT_STAGE_A_DB_USER}"

Stage A HTTP+DB IT 必须只从环境变量读取密码,禁止读取或传递 p1r.*password JVM system property。IT 内必须包含:

  • assertNoPasswordSystemProperties():拒绝 p1r.flyway.passwordp1r.account.stage-a.jdbc-password 等 password system property。
  • assertNoCredentialQuery():拒绝 JDBC URL query、日志或 evidence summary 中出现 password。
  • _test URL 断言:数据库名必须包含 _test

P1R mixed gates 仍不得推进 completed

cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0/muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -pl muse-server -am \
  -Dtest=P1rApiCoverageReportTest,P1rAccountRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rMarketRealApiGateTest,P1rContentRealApiGateTest,P1rMetaRealApiGateTest \
  -Dsurefire.failIfNoSpecifiedTests=false test

coverage check 仍应保持当前值,并且必须在 repo root 运行:

cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
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

期望仍为:

233	147	86	0	0	0

XML 防空跑

Stage A implementation 后必须检查这些 XML具体文件名以实际类名为准

muse-cloud/muse-module-member/muse-module-member-server/target/surefire-reports/TEST-cn.iocoder.muse.module.member.application.account.facade.NewApiAccountFacadeConfigurationTest.xml
muse-cloud/muse-module-member/muse-module-member-server/target/surefire-reports/TEST-cn.iocoder.muse.module.member.application.account.AccountNewApiBindingServiceTest.xml
muse-cloud/muse-module-member/muse-module-member-server/target/surefire-reports/TEST-cn.iocoder.muse.module.member.application.account.AccountQuotaServiceTest.xml
muse-cloud/muse-module-member/muse-module-member-server/target/surefire-reports/TEST-cn.iocoder.muse.module.member.application.account.AccountUsageServiceTest.xml
muse-cloud/muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rAccountStageANewApiQuotaIntegrationUnlockIT.xml
muse-cloud/muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rAccountRealApiGateTest.xml
muse-cloud/muse-server/target/surefire-reports/TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml

所有目标 XML 必须满足:

tests > 0
failures = 0
errors = 0
skipped = 0

allowed diff

当前文档阶段只允许 Account Remaining21 与 Stage A 文档变更:

docs/agent-specs/.agent
docs/agent-specs/2026-06-14-P1RAccountRemaining21解锁审阅版.md
docs/agent-specs/2026-06-14-P1RAccountRemaining21解锁执行版.md
docs/agent-specs/2026-06-14-P1RAccountStageA-NewAPIQuotaIntegration解锁执行版.md

后续用户明确批准 Stage A implementation 后,默认只允许以下类别:

muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/autoconfigure/member/account/NewApiAccountFacadeAutoConfiguration.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/facade/**
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/framework/config/MuseAccountNewApi*.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountQuotaServiceImpl.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountQuotaRequestWorker.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/AccountQuotaRequestSubmitter.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/dal/mysql/account/AccountQuotaRequestMapper.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/dal/mysql/account/AccountIntegrationCallMapper.java
muse-cloud/muse-module-member/muse-module-member-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
muse-cloud/muse-module-member/muse-module-member-server/src/test/java/cn/iocoder/muse/module/member/application/account/**
muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountStageANewApiQuotaIntegrationUnlockIT.java
docs/agent-specs/.agent
docs/memorys/**

始终禁止:

docs/api-contracts/**
muse-cloud/scripts/p1r-audit-api-coverage.py
docs/superpowers/reports/**
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/P1rAccountRealApiGateTest.java

如 implementation 必须修改禁止路径,必须停止 Stage A unlock另起 OpenAPI 合同变更审批或 completed approval 审批。

Stage A diff gate 必须覆盖 tracked、cached 和 untracked 文件,不能只用 git diff --name-only

cd /Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
{
  git -c core.quotePath=false diff --name-only
  git -c core.quotePath=false diff --cached --name-only
  git -c core.quotePath=false ls-files --others --exclude-standard
} | sort -u > /tmp/p1r-account-stage-a.diff-files

python3 - <<'PY'
from pathlib import Path

allowed = (
    "docs/agent-specs/",
    "docs/memorys/",
    "muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/autoconfigure/member/account/NewApiAccountFacadeAutoConfiguration.java",
    "muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/application/account/",
    "muse-cloud/muse-module-member/muse-module-member-server/src/main/java/cn/iocoder/muse/module/member/framework/config/MuseAccountNewApi",
    "muse-cloud/muse-module-member/muse-module-member-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports",
    "muse-cloud/muse-module-member/muse-module-member-server/src/test/java/cn/iocoder/muse/module/member/application/account/",
    "muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountStageANewApiQuotaIntegrationUnlockIT.java",
)
protected = (
    "docs/api-contracts/",
    "muse-cloud/scripts/p1r-audit-api-coverage.py",
    "docs/superpowers/reports/",
    "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/P1rAccountRealApiGateTest.java",
)
files = [line.strip() for line in Path("/tmp/p1r-account-stage-a.diff-files").read_text().splitlines() if line.strip()]
violations = [path for path in files if path.startswith(protected) or not path.startswith(allowed)]
if violations:
    raise SystemExit("diff gate violation:\n" + "\n".join(violations))
print("diff_gate=pass")
PY

回滚策略

  • A0 可通过恢复 NewApiAccountFacadeAutoConfiguration / AutoConfiguration.imports / UnavailableNewApiAccountFacade 的最小 diff 回滚。
  • A2/A3 必须保留 muse.account.new-api.enabled=false runtime switch关闭后回到 fail-closed 或 queued-only。
  • 已写入的 command、quota request、integration call 不做物理删除;通过状态和失败原因表达补偿。
  • scanner/report 回滚只属于后续 completed approval不属于 Stage A unlock。

当前完成条件

本 Stage A 执行版自身完成条件:

  • 文档写入本文件。
  • .agent 记录 Stage A 计划状态。
  • 不修改 OpenAPI、scanner、coverage report、Account 业务实现、SQL migration 或测试代码。
  • git diff --check 通过。
  • protected diff 为空。
  • fresh spec/scope review PASS。
  • fresh quality/feasibility/testing review PASS。

通过后的下一步:

  1. 用户明确批准 Stage A implementation。
  2. implementation 先做 A0 RED/GREEN再进入 A1 合同查证。
  3. A1 查证失败则停止在 A0不实现伪造 HTTP adapter。
  4. A1 查证成功后继续 A2/A3/A4。
  5. Stage A implementation fresh 双 review PASS 后,再决定是否另起 9 个 operation 的 completed approval。