Files
junhong_cmp_fiber/docs/verification/context-reset/requirement-evidence.json
break c7f9e005af
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 1h43m42s
feat(业务用户组): AUG26-003 业务用户组与店铺负责人分组导入
- 迁移 000221:新增 tb_business_user_group、tb_business_user_group_member、tb_shop_business_owner_import_task,成员一账号一行由部分唯一索引保证,店铺所属组按当前负责人实时推导,不回填历史分组。
- 用户组 CRUD、成员改组/清空归属、店铺批量交接(原子失败不部分写入)。
- 店铺负责人 CSV 导入任务:逐行独立事务、逐行明细、任务级与行级失败分离。
- 读侧推导与筛选:未分组、业务线、停用组可筛出并带停用标记。
- 补齐操作审计动作与资源、openapi 清单、发布门禁巡检表清单。
- 归档 add-shop-salesperson-groups 变更并同步 openspec/specs/business-user-group,补齐 AUG26-003 验证证据链。
2026-09-14 16:51:44 +08:00

3571 lines
189 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[
{
"capability": "agent-funds-commission",
"requirement": "代理钱包与提现状态门禁",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/shops/{shop_id}/withdrawal-requests"
],
"handler_consumer_job": [
"internal/routes/commission.go"
],
"application_service_query": [
"internal/application/wallet/debit.go"
],
"domain_state_amount": [
"internal/domain/wallet/wallet.go",
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/agent_wallet_store.go",
"internal/store/postgres/commission_withdrawal_request_store.go"
],
"verification": {
"command": "代码中检索 当前钱包状态不允许资金操作",
"literal_output": [
"internal/domain/wallet/wallet.go:122:return appErrors.New(appErrors.CodeInvalidStatus, \"当前钱包状态不允许资金操作\")"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "佣金异常状态可见",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/commission-records/{id}/resolve"
],
"handler_consumer_job": [
"internal/routes/commission.go"
],
"application_service_query": [
"internal/service/commission_calculation"
],
"domain_state_amount": [
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/commission_record_store.go"
],
"verification": {
"command": "代码中检索 CommissionStatusPendingReview",
"literal_output": [
"internal/service/commission_calculation/service.go:90:if order.CommissionStatus == model.CommissionStatusCompleted || order.CommissionStatus == model.CommissionStatusPendingReview {"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "代理在线充值本地支付状态",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/agent-recharges/{id}/payment-status"
],
"handler_consumer_job": [
"internal/handler/admin/agent_recharge.go"
],
"application_service_query": [
"internal/query/agentrecharge"
],
"domain_state_amount": [
"pkg/constants/payment.go"
],
"store_migration_config": [
"internal/store/postgres/payment_store.go"
],
"verification": {
"command": "代码中检索 PaymentRecordStatusPending",
"literal_output": [
"pkg/constants/payment.go:4:// PaymentRecordStatusPending 表示支付单待支付。"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "充值边界",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/agent-recharges",
"/api/c/v1/wallet/recharge"
],
"handler_consumer_job": [
"internal/handler/admin/agent_recharge.go",
"internal/handler/app/client_wallet.go"
],
"application_service_query": [
"internal/application/agentrecharge",
"internal/service/recharge"
],
"domain_state_amount": [
"pkg/constants/wallet.go"
],
"store_migration_config": [
"internal/store/postgres/agent_recharge_store.go",
"internal/store/postgres/asset_recharge_store.go"
],
"verification": {
"command": "代码中检索 AgentRechargeMinAmount = 1, AgentOnlineRechargeMinAmount = 10000, AgentRechargeMaxAmount = 100000000, AssetRechargeMinAmount = 100, AssetRechargeMaxAmount = 10000000",
"literal_output": [
"pkg/constants/wallet.go:83:AgentRechargeMinAmount = 1 // 线下最小充值金额1分",
"pkg/constants/wallet.go:84:AgentOnlineRechargeMinAmount = 10000 // 在线扫码最小充值金额100元",
"pkg/constants/wallet.go:85:AgentRechargeMaxAmount = 100000000 // 最大充值金额1000000元",
"pkg/constants/wallet.go:118:AssetRechargeMinAmount = 100 // 最小充值金额1元",
"pkg/constants/wallet.go:119:AssetRechargeMaxAmount = 10000000 // 最大充值金额100000元"
],
"exit_status": 0
}
},
{
"capability": "agent-open-api",
"requirement": "开放接口认证",
"spec": "openspec/specs/agent-open-api/spec.md",
"entries": [
"/api/open/v1/"
],
"handler_consumer_job": [
"internal/routes/open.go",
"internal/handler/openapi"
],
"application_service_query": [
"internal/service/agent_open_api"
],
"domain_state_amount": [
"pkg/middleware"
],
"store_migration_config": [
"internal/store/postgres/account_store.go"
],
"verification": {
"command": "代码中检索 X-Agent-Sign",
"literal_output": [
"internal/routes/open.go:15:1. 每个请求必须携带 HeaderX-Agent-Account、X-Agent-Password、X-Agent-Timestamp、X-Agent-Nonce、X-Agent-Sign。"
],
"exit_status": 0
}
},
{
"capability": "agent-open-api",
"requirement": "开放接口数据范围",
"spec": "openspec/specs/agent-open-api/spec.md",
"entries": [
"/api/open/v1/"
],
"handler_consumer_job": [
"internal/handler/openapi"
],
"application_service_query": [
"internal/service/agent_open_api"
],
"domain_state_amount": [
"pkg/middleware"
],
"store_migration_config": [
"internal/store/postgres/shop_store.go"
],
"verification": {
"command": "代码中检索 shop",
"literal_output": [
"internal/service/agent_open_api/service.go:20:shopCommissionSvc \"github.com/break/junhong_cmp_fiber/internal/service/shop_commission\""
],
"exit_status": 0
}
},
{
"capability": "asset-device",
"requirement": "资产业务状态",
"spec": "openspec/specs/asset-device/spec.md",
"entries": [
"/api/admin/assets",
"/api/admin/iot-cards"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go"
],
"application_service_query": [
"internal/service/asset",
"internal/service/iot_card"
],
"domain_state_amount": [
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/iot_card_store.go"
],
"verification": {
"command": "代码中检索 IotCardStatusInStock",
"literal_output": [
"internal/service/iot_card/service.go:562:if isPlatform && card.Status != constants.IotCardStatusInStock {"
],
"exit_status": 0
}
},
{
"capability": "asset-device",
"requirement": "设备多卡关系",
"spec": "openspec/specs/asset-device/spec.md",
"entries": [
"/api/admin/devices"
],
"handler_consumer_job": [
"internal/handler/admin/device.go"
],
"application_service_query": [
"internal/service/device"
],
"domain_state_amount": [
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/device_sim_binding_store.go"
],
"verification": {
"command": "代码中检索 BindStatusBound",
"literal_output": [
"internal/service/device/binding_audit.go:136:query := db.WithContext(ctx).Where(\"device_id = ? AND bind_status = ?\", deviceID, constants.BindStatusBound).Order(\"slot_position ASC\")"
],
"exit_status": 0
}
},
{
"capability": "asset-device",
"requirement": "ICCID 按原始长度精确唯一",
"spec": "openspec/specs/asset-device/spec.md",
"entries": [
"/api/admin/iot-cards/import"
],
"handler_consumer_job": [
"internal/handler/admin/iot_card.go"
],
"application_service_query": [
"internal/service/iot_card"
],
"domain_state_amount": [
"internal/model/iot_card.go"
],
"store_migration_config": [
"internal/store/postgres/iot_card_store.go",
"migrations/000178_make_iot_card_iccid_exact_unique.up.sql"
],
"verification": {
"command": "rg -n 'CREATE UNIQUE INDEX idx_iot_card_iccid_(19|20)' migrations/000178_make_iot_card_iccid_exact_unique.up.sql",
"literal_output": [
"59:CREATE UNIQUE INDEX idx_iot_card_iccid_19",
"63:CREATE UNIQUE INDEX idx_iot_card_iccid_20"
],
"exit_status": 0
}
},
{
"capability": "export-task",
"requirement": "导出任务终态",
"spec": "openspec/specs/export-task/spec.md",
"entries": [
"/api/admin/export-tasks",
"constants.TaskTypeExportDispatch"
],
"handler_consumer_job": [
"internal/handler/admin/export_task.go",
"internal/task/export_dispatch.go"
],
"application_service_query": [
"internal/service/export_task"
],
"domain_state_amount": [
"pkg/constants/constants.go"
],
"store_migration_config": [
"internal/store/postgres/export_task_store.go"
],
"verification": {
"command": "代码中检索 ExportTaskStatusCompleted",
"literal_output": [
"internal/task/export_dispatch.go:77:if exportTask.Status == constants.ExportTaskStatusCompleted || exportTask.Status == constants.ExportTaskStatusFailed || exportTask.Status == constants.ExportTaskStatusCancelled {"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "企微审批状态",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"/api/admin/wecom/",
"constants.TaskTypeWeComApprovalSync"
],
"handler_consumer_job": [
"internal/handler/admin/wecom.go"
],
"application_service_query": [
"internal/application/approval"
],
"domain_state_amount": [
"pkg/constants/approval.go"
],
"store_migration_config": [
"internal/infrastructure/wecom/application_repository.go"
],
"verification": {
"command": "代码中检索 ApprovalStatusSubmissionUnknown",
"literal_output": [
"pkg/constants/approval.go:81:// ApprovalStatusSubmissionUnknown 表示审批提交请求已发出但结果未知。"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "企微回调与补偿",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"/api/callback/wecom",
"constants.TaskTypeWeComApprovalRecovery"
],
"handler_consumer_job": [
"internal/routes/wecom_callback.go"
],
"application_service_query": [
"internal/infrastructure/wecom/callback_service.go"
],
"domain_state_amount": [
"internal/domain/approval/instance.go"
],
"store_migration_config": [
"internal/infrastructure/wecom/approval_context_repository.go"
],
"verification": {
"command": "代码中检索 ApplyDecision",
"literal_output": [
"internal/domain/approval/instance.go:95:// ApplyDecision 校验标准决策状态迁移并冻结首次到达该终态的决策快照。"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "外部失败边界",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"/api/admin/wecom/",
"/api/admin/iot-cards"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/gateway/client.go",
"internal/infrastructure/wecom"
],
"domain_state_amount": [
"pkg/errors/codes.go"
],
"store_migration_config": [
"internal/infrastructure/integrationlog/repository.go"
],
"verification": {
"command": "代码中检索 CodeGatewayTimeout",
"literal_output": [
"internal/gateway/client.go:217:return nil, true, errors.Wrap(errors.CodeGatewayTimeout, err, \"Gateway 请求超时\")"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "外部调用重试边界",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"constants.TaskTypeWeComApprovalRecovery"
],
"handler_consumer_job": [
"cmd/worker/main.go"
],
"application_service_query": [
"internal/gateway/client.go",
"internal/infrastructure/wecom/approval_submission_client.go"
],
"domain_state_amount": [
"pkg/constants/wecom.go"
],
"store_migration_config": [
"internal/infrastructure/wecom/approval_context_repository.go"
],
"verification": {
"command": "代码中检索 SafeToRetry",
"literal_output": [
"internal/infrastructure/wecom/approval_submission_client.go:41:SafeToRetry bool"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "富友调用超时兼容行为",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"POST /api/c/v1/orders/{id}/pay",
"POST /api/c/v1/wallet/recharge",
"POST /api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/handler/callback/payment.go"
],
"application_service_query": [
"pkg/fuiou/client.go"
],
"domain_state_amount": [
"pkg/fuiou/types.go"
],
"store_migration_config": [
"internal/store/postgres/payment_store.go"
],
"verification": {
"command": "代码中检索 http.Post",
"literal_output": [
"pkg/fuiou/client.go:164:httpResp, err := http.Post(reqURL, \"application/x-www-form-urlencoded\", strings.NewReader(body))"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "运营商回调幂等",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"/api/callback/carriers/ctcc/realname",
"/api/callback/carriers/cmcc/realname",
"/api/callback/carriers/cucc/realname",
"/api/callback/carriers/cucc/realname/remove"
],
"handler_consumer_job": [
"internal/handler/callback"
],
"application_service_query": [
"internal/infrastructure/carriercallback"
],
"domain_state_amount": [
"pkg/constants/integration_log.go"
],
"store_migration_config": [
"internal/infrastructure/integrationlog/repository.go"
],
"verification": {
"command": "代码中检索 ctccIdempotencyKey, cmccIdempotencyKey, cuccRealnameIdempotencyKey, cuccRemovalIdempotencyKey",
"literal_output": [
"internal/handler/callback/ctcc_realname.go:87:idempotencyKey := ctccIdempotencyKey(body, translated)",
"internal/handler/callback/cmcc_realname.go:65:idempotencyKey := cmccIdempotencyKey(body, translated)",
"internal/handler/callback/cucc_realname.go:66:key := cuccRealnameIdempotencyKey(body, translated, translateErr == nil)",
"internal/handler/callback/cucc_realname_removal.go:62:key := cuccRemovalIdempotencyKey(body, translated, translateErr == nil)"
],
"exit_status": 0
}
},
{
"capability": "identity-access",
"requirement": "令牌生命周期",
"spec": "openspec/specs/identity-access/spec.md",
"entries": [
"/api/admin/auth",
"/api/c/v1/auth"
],
"handler_consumer_job": [
"internal/handler/auth",
"internal/handler/app/client_auth.go"
],
"application_service_query": [
"internal/service/auth",
"internal/service/client_auth"
],
"domain_state_amount": [
"pkg/constants"
],
"store_migration_config": [
"internal/store/postgres/account_store.go"
],
"verification": {
"command": "代码中检索 Refresh",
"literal_output": [
"internal/handler/auth/handler.go:67:// 尝试从请求体获取 refresh_token可选"
],
"exit_status": 0
}
},
{
"capability": "identity-access",
"requirement": "数据范围拒绝",
"spec": "openspec/specs/identity-access/spec.md",
"entries": [
"/api/admin/"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/service/permission"
],
"domain_state_amount": [
"pkg/middleware"
],
"store_migration_config": [
"internal/store/postgres/permission_store.go"
],
"verification": {
"command": "代码中检索 CodeForbidden",
"literal_output": [
"internal/handler/admin/asset.go:162:return errors.New(errors.CodeForbidden)"
],
"exit_status": 0
}
},
{
"capability": "notification-delivery",
"requirement": "通知接收人隔离",
"spec": "openspec/specs/notification-delivery/spec.md",
"entries": [
"/api/admin/notifications",
"/api/c/v1/notifications"
],
"handler_consumer_job": [
"internal/handler/admin/notification.go",
"internal/handler/app/client_notification.go"
],
"application_service_query": [
"internal/query/notification"
],
"domain_state_amount": [
"pkg/constants/notification.go"
],
"store_migration_config": [
"internal/model/notification.go"
],
"verification": {
"command": "代码中检索 recipient_id",
"literal_output": [
"internal/query/notification/query.go:37:Where(\"recipient_kind = ? AND recipient_id = ? AND is_read = ? AND (expires_at IS NULL OR expires_at > ?)\","
],
"exit_status": 0
}
},
{
"capability": "notification-delivery",
"requirement": "通知已读幂等",
"spec": "openspec/specs/notification-delivery/spec.md",
"entries": [
"/api/admin/notifications/{id}/read",
"/api/c/v1/notifications/{id}/read"
],
"handler_consumer_job": [
"internal/handler/admin/notification.go",
"internal/handler/app/client_notification.go"
],
"application_service_query": [
"internal/application/notification/read.go"
],
"domain_state_amount": [
"pkg/constants/audit.go"
],
"store_migration_config": [
"internal/model/notification.go"
],
"verification": {
"command": "代码中检索 is_read = ?",
"literal_output": [
"internal/application/notification/read.go:95:Where(\"id = ? AND is_read = ?\", notificationID, false).Take(&notification)"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "审计时间线",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"/api/admin/audit/"
],
"handler_consumer_job": [
"internal/handler/admin/audit.go"
],
"application_service_query": [
"internal/query/audit"
],
"domain_state_amount": [
"pkg/constants/audit.go"
],
"store_migration_config": [
"internal/infrastructure/audit"
],
"verification": {
"command": "代码中检索 CorrelationID",
"literal_output": [
"internal/handler/admin/audit.go:42:RequestID: request.RequestID, CorrelationID: request.CorrelationID,"
],
"exit_status": 0
}
},
{
"capability": "order-payment-wallet",
"requirement": "金额单位",
"spec": "openspec/specs/order-payment-wallet/spec.md",
"entries": [
"/api/c/v1/wallet",
"/api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/handler/app/client_wallet.go"
],
"application_service_query": [
"internal/application/wallet"
],
"domain_state_amount": [
"pkg/constants/wallet.go"
],
"store_migration_config": [
"internal/store/postgres/agent_wallet_transaction_store.go"
],
"verification": {
"command": "代码中检索 Amount",
"literal_output": [
"internal/handler/app/client_wallet.go:230:Amount: tx.Amount,"
],
"exit_status": 0
}
},
{
"capability": "order-payment-wallet",
"requirement": "支付回调幂等",
"spec": "openspec/specs/order-payment-wallet/spec.md",
"entries": [
"/api/callback/alipay",
"/api/callback/wechat-pay",
"/api/callback/fuiou-pay"
],
"handler_consumer_job": [
"internal/handler/callback/payment.go"
],
"application_service_query": [
"internal/service/client_order"
],
"domain_state_amount": [
"pkg/constants/payment.go"
],
"store_migration_config": [
"internal/store/postgres/payment_store.go"
],
"verification": {
"command": "代码中检索 IdempotencyKey",
"literal_output": [
"internal/handler/callback/payment.go:234:idempotencyKey := callback.TransactionID"
],
"exit_status": 0
}
},
{
"capability": "order-payment-wallet",
"requirement": "钱包并发",
"spec": "openspec/specs/order-payment-wallet/spec.md",
"entries": [
"/api/c/v1/wallet/recharge",
"/api/c/v1/orders/{id}/pay"
],
"handler_consumer_job": [
"internal/handler/app/client_wallet.go"
],
"application_service_query": [
"internal/application/wallet"
],
"domain_state_amount": [
"internal/domain/wallet/wallet.go"
],
"store_migration_config": [
"internal/store/postgres/asset_wallet_store.go"
],
"verification": {
"command": "代码中检索 Version",
"literal_output": [
"internal/handler/app/client_wallet.go:683:Version: 0,"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "订单、退款与换货状态门禁",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/orders",
"/api/admin/refunds",
"/api/admin/exchanges"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/service/order",
"internal/service/refund",
"internal/service/exchange"
],
"domain_state_amount": [
"pkg/constants/constants.go",
"internal/model/refund.go"
],
"store_migration_config": [
"internal/store/postgres/order_store.go",
"internal/store/postgres/refund_store.go",
"internal/store/postgres/exchange_order_store.go"
],
"verification": {
"command": "代码中检索 ExchangeStatusPendingInfo",
"literal_output": [
"internal/service/exchange/service.go:99:Status: constants.ExchangeStatusPendingInfo,"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "套餐状态流转",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"/api/admin/packages",
"constants.TaskTypePackageFirstActivation"
],
"handler_consumer_job": [
"internal/handler/admin/package.go",
"internal/polling/package_activation_handler.go"
],
"application_service_query": [
"internal/service/package",
"internal/domain/package"
],
"domain_state_amount": [
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/package_usage_store.go"
],
"verification": {
"command": "代码中检索 PackageUsageStatusActive",
"literal_output": [
"internal/polling/package_activation_handler.go:211:constants.PackageUsageStatusActive,"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "批量操作可追踪",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"/api/admin/asset-package-batch-orders"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/service/asset_package_batch_order"
],
"domain_state_amount": [
"pkg/constants/constants.go"
],
"store_migration_config": [
"internal/store/postgres/asset_package_batch_order_task_store.go"
],
"verification": {
"command": "代码中检索 Task",
"literal_output": [
"internal/handler/admin/asset.go:62:return client.EnqueueTask("
],
"exit_status": 0
}
},
{
"capability": "personal-customer",
"requirement": "个人客户身份",
"spec": "openspec/specs/personal-customer/spec.md",
"entries": [
"/api/c/v1/auth"
],
"handler_consumer_job": [
"internal/handler/app/client_auth.go"
],
"application_service_query": [
"internal/service/client_auth"
],
"domain_state_amount": [
"pkg/constants"
],
"store_migration_config": [
"internal/store/postgres/personal_customer_store.go"
],
"verification": {
"command": "代码中检索 RefreshToken",
"literal_output": [
"pkg/constants/auth.go:14:// DefaultRefreshTokenTTL 刷新令牌默认有效期7 天)"
],
"exit_status": 0
}
},
{
"capability": "personal-customer",
"requirement": "资产归属查询",
"spec": "openspec/specs/personal-customer/spec.md",
"entries": [
"/api/c/v1/asset",
"/api/c/v1/device"
],
"handler_consumer_job": [
"internal/handler/app/client_asset.go",
"internal/handler/app/client_device.go"
],
"application_service_query": [
"internal/service/personal_customer"
],
"domain_state_amount": [
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/personal_customer_device_store.go",
"internal/store/postgres/personal_customer_iccid_store.go"
],
"verification": {
"command": "代码中检索 CustomerID",
"literal_output": [
"internal/handler/app/client_asset.go:104:CustomerID uint"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "异步任务可观察",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"/api/admin/polling-stats",
"/api/admin/data-cleanup"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/service/polling"
],
"domain_state_amount": [
"pkg/constants/polling.go"
],
"store_migration_config": [
"internal/store/postgres/polling_manual_trigger_store.go"
],
"verification": {
"command": "代码中检索 StatusProcessing",
"literal_output": [
"internal/handler/admin/polling_manual_trigger.go:298:case constants.PollingManualTriggerStatusProcessing:"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "手工轮询任务状态",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"/api/admin/polling-manual-trigger",
"constants.TaskTypePolling"
],
"handler_consumer_job": [
"internal/handler/admin"
],
"application_service_query": [
"internal/service/polling/manual_trigger_service.go"
],
"domain_state_amount": [
"pkg/constants/polling.go"
],
"store_migration_config": [
"internal/store/postgres/polling_manual_trigger_store.go"
],
"verification": {
"command": "代码中检索 PollingManualTriggerStatusCancelled",
"literal_output": [
"internal/handler/admin/polling_manual_trigger.go:302:case constants.PollingManualTriggerStatusCancelled:"
],
"exit_status": 0
}
},
{
"capability": "system-operations",
"requirement": "健康检查响应语义",
"spec": "openspec/specs/system-operations/spec.md",
"entries": [
"/health",
"/ready"
],
"handler_consumer_job": [
"internal/routes/health.go"
],
"application_service_query": [
"internal/routes/health.go"
],
"domain_state_amount": [
"internal/routes/health.go"
],
"store_migration_config": [
"pkg/response/response.go"
],
"verification": {
"command": "代码中检索 \"status\": \"healthy\", \"status\": \"ready\"",
"literal_output": [
"internal/routes/health.go:18:\"status\": \"healthy\",",
"internal/routes/health.go:31:\"status\": \"ready\","
],
"exit_status": 0
}
},
{
"capability": "system-operations",
"requirement": "受控系统配置更新",
"spec": "openspec/specs/system-operations/spec.md",
"entries": [
"/api/admin/system-configs/{key}"
],
"handler_consumer_job": [
"internal/handler/admin/system_config.go"
],
"application_service_query": [
"internal/application/systemconfig/update.go"
],
"domain_state_amount": [
"internal/infrastructure/systemconfig/registry.go"
],
"store_migration_config": [
"internal/model/system_config.go"
],
"verification": {
"command": "代码中检索 pg_advisory_xact_lock",
"literal_output": [
"internal/application/systemconfig/update.go:108:if err := tx.Exec(\"SELECT pg_advisory_xact_lock(hashtext(?))\", key).Error; err != nil {"
],
"exit_status": 0
}
},
{
"capability": "system-operations",
"requirement": "上下文健康检查证据链完整",
"spec": "openspec/specs/system-operations/spec.md",
"entries": [
"scripts/context-health.sh"
],
"handler_consumer_job": [
"scripts/context-health.sh"
],
"application_service_query": [
"docs/verification/context-reset/requirement-evidence.json"
],
"domain_state_amount": [
"docs/verification/context-reset/entry-capability-requirement-matrix.json"
],
"store_migration_config": [
"openspec/specs"
],
"verification": {
"command": "./scripts/context-health.sh",
"literal_output": [
"Context 健康检查通过"
],
"exit_status": 0
}
},
{
"capability": "merchant-payment-routing",
"requirement": "商户与微信授权配置管理",
"spec": "openspec/specs/merchant-payment-routing/spec.md",
"entries": [
"GET /api/admin/payment-merchants",
"POST /api/admin/payment-merchants",
"GET /api/admin/payment-merchants/{id}",
"PUT /api/admin/payment-merchants/{id}",
"DELETE /api/admin/payment-merchants/{id}",
"GET /api/admin/wechat-authorizations",
"PUT /api/admin/wechat-authorizations/current"
],
"handler_consumer_job": [
"internal/handler/admin/payment_merchant.go"
],
"application_service_query": [
"internal/application/merchantpayment/management.go"
],
"domain_state_amount": [
"internal/model/payment_merchant.go"
],
"store_migration_config": [
"migrations/000210_add_payment_merchant_pools.up.sql"
],
"verification": {
"command": "代码中检索 requirePaymentMerchantAccess 与 无权限访问支付商户配置",
"literal_output": [
"internal/routes/payment_merchant.go:16:func requirePaymentMerchantAccess(handler fiber.Handler) fiber.Handler {",
"internal/routes/payment_merchant.go:20:return errors.New(errors.CodeForbidden, \"无权限访问支付商户配置\")"
],
"exit_status": 0
}
},
{
"capability": "merchant-payment-routing",
"requirement": "商户池唯一性与轮询配置",
"spec": "openspec/specs/merchant-payment-routing/spec.md",
"entries": [
"GET /api/admin/payment-merchant-pools",
"POST /api/admin/payment-merchant-pools",
"GET /api/admin/payment-merchant-pools/{id}",
"PUT /api/admin/payment-merchant-pools/{id}",
"POST /api/admin/payment-merchant-pools/{id}/enable",
"POST /api/admin/payment-merchant-pools/{id}/disable"
],
"handler_consumer_job": [
"internal/handler/admin/payment_merchant.go"
],
"application_service_query": [
"internal/application/merchantpayment/management.go"
],
"domain_state_amount": [
"internal/application/merchantpayment/routing.go"
],
"store_migration_config": [
"migrations/000210_add_payment_merchant_pools.up.sql"
],
"verification": {
"command": "代码中检索 暂无可用商户",
"literal_output": [
"internal/application/merchantpayment/routing.go:210:return nil, errors.New(errors.CodeNoPaymentConfig, \"暂无可用商户\")",
"internal/application/merchantpayment/routing.go:219:return nil, errors.New(errors.CodeNoPaymentConfig, \"暂无可用商户\")",
"internal/application/merchantpayment/routing.go:254:return nil, errors.New(errors.CodeNoPaymentConfig, \"暂无可用商户\")"
],
"exit_status": 0
}
},
{
"capability": "merchant-payment-routing",
"requirement": "新支付商户快照与历史兼容",
"spec": "openspec/specs/merchant-payment-routing/spec.md",
"entries": [
"POST /api/c/v1/orders/{id}/pay",
"POST /api/c/v1/wallet/recharge",
"POST /api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/service/client_order/service.go",
"internal/service/recharge_order/service.go",
"internal/application/agentrecharge/online_creation.go"
],
"application_service_query": [
"internal/application/merchantpayment/routing.go"
],
"domain_state_amount": [
"internal/model/payment.go"
],
"store_migration_config": [
"migrations/000210_add_payment_merchant_pools.up.sql"
],
"verification": {
"command": "代码中检索 SelectForNewPaymentWithTx 与 FreezeRoute",
"literal_output": [
"internal/service/client_order/service.go:388:route, err := s.merchantRuntime.SelectForNewPaymentWithTx(ctx, tx, paymentMethod, time.Now())",
"internal/service/client_order/service.go:400:merchantpayment.FreezeRoute(payment, route)"
],
"exit_status": 0
}
},
{
"capability": "agent-series-package-options",
"requirement": "查询系列授权套餐候选项",
"spec": "openspec/specs/agent-series-package-options/spec.md",
"entries": [
"/api/admin/shop-series-grants/package-options"
],
"handler_consumer_job": [
"internal/handler/admin/shop_series_grant.go"
],
"application_service_query": [
"internal/service/shop_series_grant"
],
"domain_state_amount": [
"internal/model/dto/package_dto.go"
],
"store_migration_config": [
"internal/store/postgres/shop_package_allocation_store.go"
],
"verification": {
"command": "代码中检索 ListPackageOptions",
"literal_output": [
"internal/service/shop_series_grant/service.go:656:func (s *Service) ListPackageOptions"
],
"exit_status": 0
}
},
{
"capability": "notification-delivery",
"requirement": "主钱包低余额跨阈值提醒",
"spec": "openspec/specs/notification-delivery/spec.md",
"entries": [
"constants.OutboxEventTypeAgentMainWalletDebited",
"constants.OutboxEventTypeAdminDirectNotification"
],
"handler_consumer_job": [
"internal/infrastructure/wallet/debit_event.go"
],
"application_service_query": [
"internal/application/wallet/debit.go",
"internal/application/wallet/reservation.go"
],
"domain_state_amount": [
"pkg/constants/wallet.go"
],
"store_migration_config": [
"internal/infrastructure/messaging/outbox/repository.go"
],
"verification": {
"command": "代码中检索 AgentMainWalletLowBalanceThreshold",
"literal_output": [
"internal/infrastructure/wallet/debit_event.go:47:if event.BalanceBefore < constants.AgentMainWalletLowBalanceThreshold || event.BalanceAfter >= constants.AgentMainWalletLowBalanceThreshold {"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "授权页面禁止重复选择套餐",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"/api/admin/shop-series-grants/package-options"
],
"handler_consumer_job": [
"internal/handler/admin/shop_series_grant.go"
],
"application_service_query": [
"internal/service/shop_series_grant"
],
"domain_state_amount": [
"internal/model/dto/shop_series_grant_dto.go"
],
"store_migration_config": [
"internal/store/postgres/shop_package_allocation_store.go"
],
"verification": {
"command": "代码中检索 authorized",
"literal_output": [
"internal/model/dto/shop_series_grant_dto.go:105:Authorized bool `json:\"authorized\" description:\"目标店铺是否已启用授权\"`"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "轮询并发计数可观测",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"GET /api/admin/polling-concurrency",
"POST /api/admin/polling-concurrency/reset"
],
"handler_consumer_job": [
"internal/handler/admin/polling_concurrency.go"
],
"application_service_query": [
"internal/service/polling/concurrency_service.go"
],
"domain_state_amount": [
"pkg/constants/redis.go",
"internal/task/polling_base.go"
],
"store_migration_config": [
"internal/store/postgres/polling_concurrency_config_store.go"
],
"verification": {
"command": "rg -n 'current < 0|Available < 0|ResetConcurrency' internal/service/polling/concurrency_service.go",
"literal_output": [
"internal/service/polling/concurrency_service.go:70: if current < 0 {",
"internal/service/polling/concurrency_service.go:227:func (s *ConcurrencyService) ResetConcurrency"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "轮询并发配置覆盖实际任务",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"GET /api/admin/polling-concurrency",
"PUT /api/admin/polling-concurrency/{task_type}"
],
"handler_consumer_job": [
"internal/handler/admin/polling_concurrency.go",
"pkg/queue/handler.go"
],
"application_service_query": [
"internal/service/polling/concurrency_service.go"
],
"domain_state_amount": [
"pkg/constants/polling.go"
],
"store_migration_config": [
"internal/store/postgres/polling_concurrency_config_store.go",
"migrations/000206_fix_polling_concurrency_task_configs.up.sql"
],
"verification": {
"command": "rg -n 'TaskTypePolling(Realname|Carddata|Package|Protect|CardStatus)' pkg/queue/handler.go",
"literal_output": [
"pkg/queue/handler.go:261: h.mux.HandleFunc(constants.TaskTypePollingRealname, realnameHandler.Handle)",
"pkg/queue/handler.go:265: h.mux.HandleFunc(constants.TaskTypePollingCardStatus, cardStatusHandler.Handle)"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "轮询任务类型名称可读",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"GET /api/admin/polling-concurrency",
"GET /api/admin/polling-concurrency/{task_type}"
],
"handler_consumer_job": [
"internal/handler/admin/polling_concurrency.go"
],
"application_service_query": [
"internal/service/polling/concurrency_service.go"
],
"domain_state_amount": [
"internal/model/dto/polling_concurrency_dto.go"
],
"store_migration_config": [
"internal/store/postgres/polling_concurrency_config_store.go"
],
"verification": {
"command": "rg -n 'card_status.*卡状态检查' internal/service/polling/concurrency_service.go",
"literal_output": [
"internal/service/polling/concurrency_service.go:287: case \"card_status\": return \"卡状态检查\""
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "历史待审批线下代理充值可主动接入企业微信审批",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/agent-recharges/{id}/trigger-approval"
],
"handler_consumer_job": [
"internal/routes/agent_recharge.go",
"internal/handler/admin/agent_recharge.go"
],
"application_service_query": [
"internal/application/agentrecharge/offline_creation.go",
"internal/service/agent_recharge/service.go"
],
"domain_state_amount": [],
"store_migration_config": [
"internal/model/agent_wallet.go",
"migrations/000190_add_agent_recharge_approval_instance.up.sql",
"migrations/000170_create_approval_core.up.sql"
],
"verification": {
"command": "rg -n \"TriggerHistorical|trigger-approval\" internal/application internal/handler/admin internal/routes",
"literal_output": [
"internal/application/agentrecharge/offline_creation.go:51:func (s *OfflineCreationService) TriggerHistorical(ctx context.Context, recordID uint) (*CreateOfflineResult, error) {",
"internal/routes/agent_recharge.go:64: Register(group, doc, groupPath, \"POST\", \"/:id/trigger-approval\", handler.TriggerApproval, RouteSpec{"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "历史待审批退款可主动接入企业微信审批",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds/{id}/trigger-approval"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/handler/admin/refund.go"
],
"application_service_query": [
"internal/application/refundapproval/creation.go",
"internal/service/refund/service.go"
],
"domain_state_amount": [],
"store_migration_config": [
"internal/model/refund.go",
"migrations/000191_add_refund_approval_instance.up.sql",
"migrations/000170_create_approval_core.up.sql"
],
"verification": {
"command": "rg -n \"TriggerHistorical|trigger-approval\" internal/application internal/handler/admin internal/routes",
"literal_output": [
"internal/application/refundapproval/creation.go:60:func (s *CreationService) TriggerHistorical(ctx context.Context, refundID uint) (*CreateResult, error) {",
"internal/routes/refund.go:52: Register(refund, doc, groupPath, \"POST\", \"/:id/trigger-approval\", handler.TriggerApproval, RouteSpec{"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "佣金待计算状态可恢复",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"cmd/worker/main.go"
],
"application_service_query": [
"pkg/queue/handler.go",
"cmd/worker/main.go"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "退款佣金回扣可靠完成",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"internal/infrastructure/commissiondelivery",
"pkg/queue/handler.go"
],
"application_service_query": [
"internal/infrastructure/commissiondelivery",
"pkg/queue/handler.go"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "退款后处理可补偿",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"internal/service/refund",
"pkg/queue/handler.go"
],
"application_service_query": [
"internal/service/refund",
"pkg/queue/handler.go"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "代理商资金概况按店铺 ID 检索",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/shops/fund-summary"
],
"handler_consumer_job": [
"internal/routes/commission.go",
"internal/service/shop_commission"
],
"application_service_query": [
"internal/routes/commission.go",
"internal/service/shop_commission"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "asset-device",
"requirement": "临期颜色等级仅用于展示",
"spec": "openspec/specs/asset-device/spec.md",
"entries": [
"/api/admin/expiring-assets",
"constants.TaskTypePackageExpiryReminder"
],
"handler_consumer_job": [
"internal/routes/asset.go",
"pkg/queue/handler.go"
],
"application_service_query": [
"internal/routes/asset.go",
"pkg/queue/handler.go"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "asset-device",
"requirement": "卡业务观测可靠事件标识",
"spec": "openspec/specs/asset-device/spec.md",
"entries": [
"constants.TaskTypeCardObservationSeries"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"internal/application/cardobservation"
],
"application_service_query": [
"pkg/queue/handler.go",
"internal/application/cardobservation"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "notification-delivery",
"requirement": "套餐临期每日站内提醒",
"spec": "openspec/specs/notification-delivery/spec.md",
"entries": [
"constants.TaskTypePackageExpiryReminder"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"internal/service/notification"
],
"application_service_query": [
"pkg/queue/handler.go",
"internal/service/notification"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "order-commission-delivery",
"requirement": "佣金计算重复投递幂等",
"spec": "openspec/specs/order-commission-delivery/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"application_service_query": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "order-commission-delivery",
"requirement": "已支付订单佣金计算可靠投递",
"spec": "openspec/specs/order-commission-delivery/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"application_service_query": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "order-commission-delivery",
"requirement": "待计算订单可补偿",
"spec": "openspec/specs/order-commission-delivery/spec.md",
"entries": [
"constants.TaskTypeCommission"
],
"handler_consumer_job": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"application_service_query": [
"pkg/queue/handler.go",
"internal/infrastructure/commissiondelivery"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "代理退款查询按所属店铺隔离",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds",
"/api/admin/refunds/{id}"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/store/postgres/refund_store.go"
],
"application_service_query": [
"internal/routes/refund.go",
"internal/store/postgres/refund_store.go"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "套餐使用记录价格快照",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"/api/admin/orders"
],
"handler_consumer_job": [
"internal/routes/order.go",
"internal/service/order"
],
"application_service_query": [
"internal/routes/order.go",
"internal/service/order"
],
"domain_state_amount": [],
"store_migration_config": [],
"verification": {
"command": "openspec validate --specs",
"literal_output": [
"Totals: 16 passed, 0 failed (16 items)"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "代理在线充值可用支付方式按允许范围与可用商户池判定",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"GET /api/admin/agent-recharges/payment-methods",
"GET /api/admin/agent-self-recharge-payment-methods",
"POST /api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/handler/admin/agent_recharge.go:AgentRechargeHandler.PaymentMethods"
],
"application_service_query": [
"internal/application/agentrecharge/online_creation.go:OnlineCreationService.AvailablePaymentMethods",
"internal/application/agentrecharge/online_payment_policy.go:OnlinePaymentMethodPolicy.AllowedMethods"
],
"domain_state_amount": [
"internal/model/agent_wallet.go:AgentRechargeRecord.PaymentMethod/PaymentChannel"
],
"store_migration_config": [
"internal/application/agentrecharge/online_creation.go:adapter.Available"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/application/agentrecharge/online_creation.go\", \"allowed, err := s.policy.AllowedMethods(ctx)\"), (\"internal/application/agentrecharge/online_creation.go\", \"adapter.Available(config)\"), (\"internal/application/agentrecharge/online_payment_policy.go\", \"func (p *OnlinePaymentMethodPolicy) AllowedMethods(\"), (\"internal/application/agentrecharge/online_payment_policy.go\", \"func (p *OnlinePaymentMethodPolicy) IsAllowed(\"), (\"internal/handler/admin/agent_recharge.go\", \"func (h *AgentRechargeHandler) SelfRechargePaymentMethods(\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: agent-funds-commission::代理在线充值可用支付方式按允许范围与可用商户池判定\")'",
"literal_output": [
"OK: agent-funds-commission::代理在线充值可用支付方式按允许范围与可用商户池判定"
],
"exit_status": 0
}
},
{
"capability": "agent-open-api",
"requirement": "代理开放接口查询不触发可靠卡观测",
"spec": "openspec/specs/agent-open-api/spec.md",
"entries": [
"GET /api/open/v1/cards/traffic",
"GET /api/open/v1/cards/status",
"GET /api/open/v1/cards/realname-status",
"GET /api/open/v1/devices/traffic"
],
"handler_consumer_job": [
"internal/handler/openapi/handler.go:GetCardTraffic -> service.GetCardTraffic",
"internal/handler/openapi/handler.go:GetCardStatus -> service.GetCardStatus",
"internal/handler/openapi/handler.go:GetRealnameStatus -> service.GetRealnameStatus",
"internal/handler/openapi/handler.go:GetDeviceTraffic -> service.GetDeviceTraffic"
],
"application_service_query": [
"internal/service/agent_open_api/service.go:GetCardTraffic",
"internal/service/agent_open_api/service.go:GetCardStatus",
"internal/service/agent_open_api/service.go:GetRealnameStatus",
"internal/service/agent_open_api/service.go:GetDeviceTraffic"
],
"domain_state_amount": [
"仅静态证明上述四个 GET handler 直接调用对应查询服务方法;不对全闭包的观测可达性作断言"
],
"store_migration_config": [
"internal/service/agent_open_api/service.go:packageUsageStore/deviceSimBindingStore/deviceStore"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'func (h *Handler) GetCardTraffic'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'h.service.GetCardTraffic(c.UserContext(), &req)'\"'\"'), ('\"'\"'internal/service/agent_open_api/service.go'\"'\"', '\"'\"'func (s *Service) GetCardTraffic'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'func (h *Handler) GetCardStatus'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'h.service.GetCardStatus(c.UserContext(), &req)'\"'\"'), ('\"'\"'internal/service/agent_open_api/service.go'\"'\"', '\"'\"'func (s *Service) GetCardStatus'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'func (h *Handler) GetRealnameStatus'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'h.service.GetRealnameStatus(c.UserContext(), &req)'\"'\"'), ('\"'\"'internal/service/agent_open_api/service.go'\"'\"', '\"'\"'func (s *Service) GetRealnameStatus'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'func (h *Handler) GetDeviceTraffic'\"'\"'), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', '\"'\"'h.service.GetDeviceTraffic(c.UserContext(), &req)'\"'\"'), ('\"'\"'internal/service/agent_open_api/service.go'\"'\"', '\"'\"'func (s *Service) GetDeviceTraffic'\"'\"')]; ordered=[('\"'\"'internal/handler/openapi/handler.go'\"'\"', ['\"'\"'func (h *Handler) GetCardTraffic'\"'\"', '\"'\"'h.service.GetCardTraffic(c.UserContext(), &req)'\"'\"']), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', ['\"'\"'func (h *Handler) GetCardStatus'\"'\"', '\"'\"'h.service.GetCardStatus(c.UserContext(), &req)'\"'\"']), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', ['\"'\"'func (h *Handler) GetRealnameStatus'\"'\"', '\"'\"'h.service.GetRealnameStatus(c.UserContext(), &req)'\"'\"']), ('\"'\"'internal/handler/openapi/handler.go'\"'\"', ['\"'\"'func (h *Handler) GetDeviceTraffic'\"'\"', '\"'\"'h.service.GetDeviceTraffic(c.UserContext(), &req)'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: agent-open-api::代理开放接口查询不触发可靠卡观测'\"'\"')'",
"literal_output": [
"OK: agent-open-api::代理开放接口查询不触发可靠卡观测"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "富友主扫统一下单与订单查询",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"POST /api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/infrastructure/payment/fuiou_scan.go:FuiouScanAdapter.CreatePaymentURL/Query"
],
"application_service_query": [
"pkg/fuiou/scan.go:Client.PreCreate/CommonQuery"
],
"domain_state_amount": [
"pkg/fuiou/types.go:CommonQueryResponse.TransStat"
],
"store_migration_config": [
"internal/infrastructure/integrationlog"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/infrastructure/payment/fuiou_scan.go'\"'\"', '\"'\"'client.PreCreate('\"'\"'), ('\"'\"'internal/infrastructure/payment/fuiou_scan.go'\"'\"', '\"'\"'client.CommonQuery('\"'\"'), ('\"'\"'pkg/fuiou/scan.go'\"'\"', '\"'\"'func (c *Client) PreCreate'\"'\"'), ('\"'\"'pkg/fuiou/scan.go'\"'\"', '\"'\"'func (c *Client) CommonQuery'\"'\"'), ('\"'\"'pkg/fuiou/types.go'\"'\"', '\"'\"'xml:\"trans_stat\"'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: external-integration::富友主扫统一下单与订单查询'\"'\"')'",
"literal_output": [
"OK: external-integration::富友主扫统一下单与订单查询"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "高频轮询外部交互日志保留边界",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"constants.TaskTypePollingCarddata",
"constants.TaskTypePollingCardStatus",
"constants.TaskTypePollingRealname"
],
"handler_consumer_job": [
"internal/task/polling_integration_log.go:newGatewayAttempt/recordGatewayAttempt"
],
"application_service_query": [
"internal/application/cardobservation/traffic.go:ApplyTrafficObservation"
],
"domain_state_amount": [
"internal/infrastructure/integrationlog.Repository:Attempt.StateChanged"
],
"store_migration_config": [
"internal/query/retention/retention.go:Info.OnlineFrom/ArchivedBefore"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/polling_integration_log.go'\"'\"', '\"'\"'成功无变化的轮询不落库'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'recordGatewayAttempt'\"'\"'), ('\"'\"'internal/query/retention/retention.go'\"'\"', '\"'\"'ArchivedBefore'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: external-integration::高频轮询外部交互日志保留边界'\"'\"')'",
"literal_output": [
"OK: external-integration::高频轮询外部交互日志保留边界"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "外部交互日志归档与留存受控执行",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"constants.TaskTypeIntegrationDailyArchive",
"constants.TaskTypeAuditDailyRetention"
],
"handler_consumer_job": [
"internal/task/integration_archive.go:IntegrationArchiveHandler.HandleDaily",
"internal/task/audit_monthly_retention.go:AuditRetentionHandler.Handle"
],
"application_service_query": [
"internal/application/auditarchive/integration.go:ArchivePreviousIntegrationDay",
"internal/application/auditarchive/retention.go:RetainPendingDays"
],
"domain_state_amount": [
"internal/application/auditarchive/retention.go:RetentionBlockedError"
],
"store_migration_config": [
"pkg/constants/audit_archive.go:IntegrationArchiveSource"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/integration_archive.go'\"'\"', '\"'\"'func (h *IntegrationArchiveHandler) HandleDaily'\"'\"'), ('\"'\"'internal/task/audit_monthly_retention.go'\"'\"', '\"'\"'cleanupEnabled'\"'\"'), ('\"'\"'internal/application/auditarchive/retention.go'\"'\"', '\"'\"'RetentionBlockedError'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: external-integration::外部交互日志归档与留存受控执行'\"'\"')'",
"literal_output": [
"OK: external-integration::外部交互日志归档与留存受控执行"
],
"exit_status": 0
}
},
{
"capability": "external-integration",
"requirement": "外部交互日志逐日物理留存",
"spec": "openspec/specs/external-integration/spec.md",
"entries": [
"constants.TaskTypeIntegrationDailyArchive",
"constants.TaskTypeAuditDailyRetention"
],
"handler_consumer_job": [
"internal/task/integration_archive.go:IntegrationArchiveHandler.HandleDaily",
"internal/task/audit_monthly_retention.go:AuditRetentionHandler.Handle"
],
"application_service_query": [
"internal/application/auditarchive/integration.go:ArchivePreviousIntegrationDay",
"internal/application/auditarchive/retention.go:RetainPendingDays"
],
"domain_state_amount": [
"internal/application/auditarchive/retention.go:RetentionResult.IntegrationCount"
],
"store_migration_config": [
"internal/query/retention/retention.go:SourceIntegration/tb_integration_log"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/application/auditarchive/integration.go'\"'\"', '\"'\"'ArchivePreviousIntegrationDay'\"'\"'), ('\"'\"'internal/application/auditarchive/retention.go'\"'\"', '\"'\"'retainIntegrationDate'\"'\"'), ('\"'\"'internal/query/retention/retention.go'\"'\"', '\"'\"'tb_integration_log'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: external-integration::外部交互日志逐日物理留存'\"'\"')'",
"literal_output": [
"OK: external-integration::外部交互日志逐日物理留存"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "轮询审计事实保留边界",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"constants.TaskTypePollingCarddata",
"constants.TaskTypePollingCardStatus",
"constants.TaskTypePollingRealname"
],
"handler_consumer_job": [
"internal/task/polling_carddata_handler.go:Handle",
"internal/task/polling_cardstatus_handler.go:Handle",
"internal/task/polling_realname_handler.go:Handle"
],
"application_service_query": [
"internal/application/cardobservation/apply.go:ApplyCardObservation",
"internal/application/cardobservation/network.go:ApplyNetworkObservation",
"internal/application/cardobservation/traffic.go:ApplyTrafficObservation"
],
"domain_state_amount": [
"internal/application/cardobservation:workerObservationAudited"
],
"store_migration_config": [
"internal/query/audit/events.go:EventPage.Retention"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/application/cardobservation/network.go'\"'\"', '\"'\"'workerObservationAudited(ctx) && stateChanged'\"'\"'), ('\"'\"'internal/application/cardobservation/traffic.go'\"'\"', '\"'\"'workerObservationAudited(ctx) && stateChanged'\"'\"'), ('\"'\"'internal/query/audit/events.go'\"'\"', '\"'\"'在线查询留存边界'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: operations-audit::轮询审计事实保留边界'\"'\"')'",
"literal_output": [
"OK: operations-audit::轮询审计事实保留边界"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "审计归档与日留存受控执行",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"constants.TaskTypeAuditDailyArchive",
"constants.TaskTypeAuditDailyRetention"
],
"handler_consumer_job": [
"cmd/worker/main.go:registerAsynqScheduleTasks",
"internal/task/audit_monthly_retention.go:AuditRetentionHandler.Handle"
],
"application_service_query": [
"internal/application/auditarchive/service.go:ArchivePreviousDay",
"internal/application/auditarchive/retention.go:RetainPendingDays"
],
"domain_state_amount": [
"internal/application/auditarchive/retention.go:RetentionBlockedError"
],
"store_migration_config": [
"pkg/constants/audit_archive.go:TaskTypeAuditDailyArchive/TaskTypeAuditDailyRetention"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'cmd/worker/main.go'\"'\"', '\"'\"'constants.TaskTypeAuditDailyArchive'\"'\"'), ('\"'\"'cmd/worker/main.go'\"'\"', '\"'\"'constants.TaskTypeAuditDailyRetention'\"'\"'), ('\"'\"'internal/task/audit_monthly_retention.go'\"'\"', '\"'\"'cleanupEnabled'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: operations-audit::审计归档与日留存受控执行'\"'\"')'",
"literal_output": [
"OK: operations-audit::审计归档与日留存受控执行"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "审计在线数据逐日物理留存",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"constants.TaskTypeAuditDailyRetention"
],
"handler_consumer_job": [
"internal/task/audit_monthly_retention.go:AuditRetentionHandler.Handle"
],
"application_service_query": [
"internal/application/auditarchive/retention.go:RetainPendingDays/retainDate"
],
"domain_state_amount": [
"internal/application/auditarchive/retention.go:RetentionResult.EventCount/ResourceCount"
],
"store_migration_config": [
"internal/query/retention/retention.go:tb_audit_event/LogArchiveRun"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/application/auditarchive/retention.go'\"'\"', '\"'\"'RetainPendingDays'\"'\"'), ('\"'\"'internal/application/auditarchive/retention.go'\"'\"', '\"'\"'retainAuditDate'\"'\"'), ('\"'\"'internal/query/retention/retention.go'\"'\"', '\"'\"'tb_audit_event'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: operations-audit::审计在线数据逐日物理留存'\"'\"')'",
"literal_output": [
"OK: operations-audit::审计在线数据逐日物理留存"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "日留存独立运行日志",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"constants.TaskTypeAuditDailyRetention"
],
"handler_consumer_job": [
"cmd/worker/main.go:NewRetentionLogger",
"internal/task/audit_monthly_retention.go:AuditRetentionHandler.Handle"
],
"application_service_query": [
"internal/application/auditarchive/retention.go:RetainPendingDays"
],
"domain_state_amount": [
"internal/application/auditarchive/retention.go:RetentionResult.Duration"
],
"store_migration_config": [
"cmd/worker/main.go:cfg.Logging.RetentionLog"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'cmd/worker/main.go'\"'\"', '\"'\"'logger.NewRetentionLogger'\"'\"'), ('\"'\"'cmd/worker/main.go'\"'\"', '\"'\"'cfg.Logging.RetentionLog'\"'\"'), ('\"'\"'internal/task/audit_monthly_retention.go'\"'\"', '\"'\"'日志日留存处理完成'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: operations-audit::日留存独立运行日志'\"'\"')'",
"literal_output": [
"OK: operations-audit::日留存独立运行日志"
],
"exit_status": 0
}
},
{
"capability": "operations-audit",
"requirement": "审计调查留存边界连续",
"spec": "openspec/specs/operations-audit/spec.md",
"entries": [
"GET /api/admin/audit/events",
"GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline"
],
"handler_consumer_job": [
"internal/handler/admin/audit.go",
"internal/query/audit/timeline.go:LinkTimeline"
],
"application_service_query": [
"internal/query/audit/events.go:List",
"internal/query/audit/timeline.go:LinkTimeline"
],
"domain_state_amount": [
"internal/query/retention/retention.go:NormalizeRange"
],
"store_migration_config": [
"internal/query/retention/retention.go:sourceBoundary"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/query/audit/timeline.go'\"'\"', '\"'\"'Audit与Integration共同在线留存边界'\"'\"'), ('\"'\"'internal/query/retention/retention.go'\"'\"', '\"'\"'func NormalizeRange'\"'\"'), ('\"'\"'internal/query/retention/retention.go'\"'\"', '\"'\"'for _, row := range rows'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: operations-audit::审计调查留存边界连续'\"'\"')'",
"literal_output": [
"OK: operations-audit::审计调查留存边界连续"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "资产套餐层级投影",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"GET /api/admin/assets/{identifier}/packages",
"GET /api/c/v1/asset/package-history"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go:AssetHandler.Packages -> asset.Service.GetPackages",
"internal/handler/app/client_asset.go:ClientAssetHandler.GetPackageHistory -> assetquery.NewPackageHistoryQuery.List"
],
"application_service_query": [
"internal/service/asset/service.go:Service.GetPackages -> assetquery.NewPackageHistoryQuery.List",
"internal/query/asset/package_history.go:PackageHistoryQuery.List"
],
"domain_state_amount": [
"internal/query/asset/package_history.go:PackageHistoryNode.Children/RelationshipStatus",
"internal/model/package.go:PackageUsage.MasterUsageID"
],
"store_migration_config": [
"internal/query/asset/package_history.go:baseUsageQuery"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'func (h *AssetHandler) Packages'\"'\"'), ('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'func (s *Service) GetPackages'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'func (q *PackageHistoryQuery) List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'Children []*PackageHistoryNode'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'RelationshipStatus'\"'\"'), ('\"'\"'internal/model/package.go'\"'\"', '\"'\"'MasterUsageID'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/asset.go'\"'\"', ['\"'\"'func (h *AssetHandler) Packages'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"']), ('\"'\"'internal/service/asset/service.go'\"'\"', ['\"'\"'func (s *Service) GetPackages'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"']), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', ['\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-lifecycle::资产套餐层级投影'\"'\"')'",
"literal_output": [
"OK: package-lifecycle::资产套餐层级投影"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "套餐历史整组筛选与分页",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"GET /api/admin/assets/{identifier}/packages",
"GET /api/c/v1/asset/package-history"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go:AssetHandler.Packages -> asset.Service.GetPackages",
"internal/handler/app/client_asset.go:ClientAssetHandler.GetPackageHistory -> assetquery.NewPackageHistoryQuery.List"
],
"application_service_query": [
"internal/service/asset/service.go:Service.GetPackages -> assetquery.NewPackageHistoryQuery.List",
"internal/query/asset/package_history.go:PackageHistoryQuery.List"
],
"domain_state_amount": [
"internal/query/asset/package_history.go:filterPackageHistoryGroups/paginatePackageHistoryGroups"
],
"store_migration_config": [
"internal/query/asset/package_history.go:baseUsageQuery"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'func (h *AssetHandler) Packages'\"'\"'), ('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'func (s *Service) GetPackages'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'func (q *PackageHistoryQuery) List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'filterPackageHistoryGroups'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'paginatePackageHistoryGroups'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'PageSize'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/asset.go'\"'\"', ['\"'\"'func (h *AssetHandler) Packages'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"']), ('\"'\"'internal/service/asset/service.go'\"'\"', ['\"'\"'func (s *Service) GetPackages'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"']), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', ['\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-lifecycle::套餐历史整组筛选与分页'\"'\"')'",
"literal_output": [
"OK: package-lifecycle::套餐历史整组筛选与分页"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "套餐历史稳定排序",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"GET /api/admin/assets/{identifier}/packages",
"GET /api/c/v1/asset/package-history"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go:AssetHandler.Packages -> asset.Service.GetPackages",
"internal/handler/app/client_asset.go:ClientAssetHandler.GetPackageHistory -> assetquery.NewPackageHistoryQuery.List"
],
"application_service_query": [
"internal/service/asset/service.go:Service.GetPackages -> assetquery.NewPackageHistoryQuery.List",
"internal/query/asset/package_history.go:PackageHistoryQuery.List"
],
"domain_state_amount": [
"internal/query/asset/package_history.go:sortPackageHistoryGroups/packageHistoryChildLess"
],
"store_migration_config": [
"internal/query/asset/package_history.go:baseUsageQuery"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'func (h *AssetHandler) Packages'\"'\"'), ('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'func (s *Service) GetPackages'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'func (q *PackageHistoryQuery) List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'sort.Slice(item.Children'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'sort.Slice(items'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'left.ID < right.ID'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/asset.go'\"'\"', ['\"'\"'func (h *AssetHandler) Packages'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"']), ('\"'\"'internal/service/asset/service.go'\"'\"', ['\"'\"'func (s *Service) GetPackages'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"']), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', ['\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-lifecycle::套餐历史稳定排序'\"'\"')'",
"literal_output": [
"OK: package-lifecycle::套餐历史稳定排序"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "物理缺失与不可展示关系区分",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"GET /api/admin/assets/{identifier}/packages",
"GET /api/c/v1/asset/package-history"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go:AssetHandler.Packages -> asset.Service.GetPackages",
"internal/handler/app/client_asset.go:ClientAssetHandler.GetPackageHistory -> assetquery.NewPackageHistoryQuery.List"
],
"application_service_query": [
"internal/service/asset/service.go:Service.GetPackages -> assetquery.NewPackageHistoryQuery.List",
"internal/query/asset/package_history.go:PackageHistoryQuery.List"
],
"domain_state_amount": [
"internal/query/asset/package_history.go:inRange/presentMasters/relationshipStatusMasterMissing"
],
"store_migration_config": [
"internal/query/asset/package_history.go:baseUsageQuery"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'func (h *AssetHandler) Packages'\"'\"'), ('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'func (s *Service) GetPackages'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'func (q *PackageHistoryQuery) List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'if inRange'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'presentMasters'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'relationshipStatusMasterMissing'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/asset.go'\"'\"', ['\"'\"'func (h *AssetHandler) Packages'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"']), ('\"'\"'internal/service/asset/service.go'\"'\"', ['\"'\"'func (s *Service) GetPackages'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"']), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', ['\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-lifecycle::物理缺失与不可展示关系区分'\"'\"')'",
"literal_output": [
"OK: package-lifecycle::物理缺失与不可展示关系区分"
],
"exit_status": 0
}
},
{
"capability": "package-lifecycle",
"requirement": "套餐历史读取范围与兼容边界",
"spec": "openspec/specs/package-lifecycle/spec.md",
"entries": [
"GET /api/admin/assets/{identifier}/packages",
"GET /api/c/v1/asset/package-history"
],
"handler_consumer_job": [
"internal/handler/admin/asset.go:AssetHandler.Packages -> asset.Service.GetPackages",
"internal/handler/app/client_asset.go:ClientAssetHandler.GetPackageHistory -> assetquery.NewPackageHistoryQuery.List"
],
"application_service_query": [
"internal/service/asset/service.go:Service.GetPackages -> assetquery.NewPackageHistoryQuery.List",
"internal/query/asset/package_history.go:PackageHistoryQuery.List"
],
"domain_state_amount": [
"internal/query/asset/package_history.go:PackageHistoryInput.AssetType/Generation/baseUsageQuery"
],
"store_migration_config": [
"internal/query/asset/package_history.go:baseUsageQuery"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'func (h *AssetHandler) Packages'\"'\"'), ('\"'\"'internal/handler/admin/asset.go'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'func (s *Service) GetPackages'\"'\"'), ('\"'\"'internal/service/asset/service.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"'), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'func (q *PackageHistoryQuery) List'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'AssetType'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'Generation'\"'\"'), ('\"'\"'internal/query/asset/package_history.go'\"'\"', '\"'\"'baseUsageQuery'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/asset.go'\"'\"', ['\"'\"'func (h *AssetHandler) Packages'\"'\"', '\"'\"'h.assetService.GetPackages(c.UserContext(), asset.AssetType, asset.AssetID, page, pageSize, status, callerAccountType)'\"'\"']), ('\"'\"'internal/service/asset/service.go'\"'\"', ['\"'\"'func (s *Service) GetPackages'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(s.db).List'\"'\"']), ('\"'\"'internal/handler/app/client_asset.go'\"'\"', ['\"'\"'func (h *ClientAssetHandler) GetPackageHistory'\"'\"', '\"'\"'assetquery.NewPackageHistoryQuery(h.db).List'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-lifecycle::套餐历史读取范围与兼容边界'\"'\"')'",
"literal_output": [
"OK: package-lifecycle::套餐历史读取范围与兼容边界"
],
"exit_status": 0
}
},
{
"capability": "package-queue-activation",
"requirement": "当前主套餐过期后自动激活下一个",
"spec": "openspec/specs/package-queue-activation/spec.md",
"entries": [
"constants.TaskTypePackageQueueActivation"
],
"handler_consumer_job": [
"internal/polling/package_activation_handler.go:PackageActivationHandler.Handle",
"pkg/queue/handler.go:HandlePackageQueueActivation"
],
"application_service_query": [
"internal/polling/package_activation_handler.go:activateNextPackage"
],
"domain_state_amount": [
"internal/model/package.go:PackageUsage.Priority/MasterUsageID"
],
"store_migration_config": [
"internal/polling/package_activation_handler.go:tb_package_usage"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'expires_at <= ?'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'enqueueActivationTask'\"'\"'), ('\"'\"'pkg/queue/handler.go'\"'\"', '\"'\"'TaskTypePackageQueueActivation'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: package-queue-activation::当前主套餐过期后自动激活下一个'\"'\"')'",
"literal_output": [
"OK: package-queue-activation::当前主套餐过期后自动激活下一个"
],
"exit_status": 0
}
},
{
"capability": "package-queue-activation",
"requirement": "孤儿待生效套餐必须公平恢复",
"spec": "openspec/specs/package-queue-activation/spec.md",
"entries": [
"constants.TaskTypePackageQueueActivation"
],
"handler_consumer_job": [
"internal/polling/package_activation_handler.go:findAndActivateOrphanPackages"
],
"application_service_query": [
"internal/polling/package_activation_handler.go:enqueueActivationTask"
],
"domain_state_amount": [
"internal/polling/package_activation_handler.go:ROW_NUMBER/priority/created_at/id"
],
"store_migration_config": [
"internal/polling/package_activation_handler.go:tb_package_usage"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'func (h *PackageActivationHandler) findAndActivateOrphanPackages'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'ROW_NUMBER() OVER'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'ORDER BY candidate.priority ASC, candidate.created_at ASC, candidate.id ASC'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: package-queue-activation::孤儿待生效套餐必须公平恢复'\"'\"')'",
"literal_output": [
"OK: package-queue-activation::孤儿待生效套餐必须公平恢复"
],
"exit_status": 0
}
},
{
"capability": "package-queue-activation",
"requirement": "Asynq 激活结果必须准确且可重试",
"spec": "openspec/specs/package-queue-activation/spec.md",
"entries": [
"constants.TaskTypePackageQueueActivation"
],
"handler_consumer_job": [
"pkg/queue/handler.go:registerPackageActivationHandlers -> TaskTypePackageQueueActivation",
"internal/polling/package_activation_handler.go:PackageActivationHandler.HandlePackageQueueActivation"
],
"application_service_query": [
"internal/polling/package_activation_handler.go:enqueueActivationTask",
"internal/service/package/activation_service.go:ActivationService.ActivateSpecificPackage"
],
"domain_state_amount": [
"internal/service/package/activation_service.go:SetNX conflict -> CodePackageActivationConflict",
"internal/polling/package_activation_handler.go:business failure returns err"
],
"store_migration_config": [
"internal/service/package/activation_service.go:RedisPackageActivationLockKey",
"internal/polling/package_activation_handler.go:tb_package_usage"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'pkg/queue/handler.go'\"'\"', '\"'\"'h.mux.HandleFunc(constants.TaskTypePackageQueueActivation, packageActivationHandler.HandlePackageQueueActivation)'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'func (h *PackageActivationHandler) enqueueActivationTask'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'asynq.MaxRetry(3)'\"'\"'), ('\"'\"'internal/polling/package_activation_handler.go'\"'\"', '\"'\"'return err'\"'\"'), ('\"'\"'internal/service/package/activation_service.go'\"'\"', '\"'\"'return errors.New(errors.CodePackageActivationConflict)'\"'\"')]; ordered=[('\"'\"'internal/polling/package_activation_handler.go'\"'\"', ['\"'\"'if err := h.activationService.ActivateSpecificPackage'\"'\"', '\"'\"'return err'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: package-queue-activation::Asynq 激活结果必须准确且可重试'\"'\"')'",
"literal_output": [
"OK: package-queue-activation::Asynq 激活结果必须准确且可重试"
],
"exit_status": 0
}
},
{
"capability": "polling-load-control",
"requirement": "轮询全局并发与背压",
"spec": "openspec/specs/polling-load-control/spec.md",
"entries": [
"constants.TaskTypePollingCarddata",
"constants.TaskTypePollingCardStatus",
"constants.TaskTypePollingPackage",
"constants.TaskTypePollingProtect",
"constants.TaskTypePollingRealname"
],
"handler_consumer_job": [
"internal/task/polling_carddata_handler.go:PollingCarddataHandler.Handle",
"internal/task/polling_cardstatus_handler.go:PollingCardStatusHandler.Handle",
"internal/task/polling_package_handler.go:PollingPackageHandler.Handle",
"internal/task/polling_protect_handler.go:PollingProtectHandler.Handle",
"internal/task/polling_realname_handler.go:PollingRealnameHandler.Handle"
],
"application_service_query": [
"internal/task/polling_base.go:PollingBase.acquireConcurrency/requeueCard/releaseConcurrency"
],
"domain_state_amount": [
"internal/task/polling_base.go:acquireConcurrencyScript"
],
"store_migration_config": [
"pkg/constants/redis.go",
"pkg/constants/polling.go"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_base.go'\"'\"', '\"'\"'var acquireConcurrencyScript'\"'\"')]; ordered=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"']), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"']), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: polling-load-control::轮询全局并发与背压'\"'\"')'",
"literal_output": [
"OK: polling-load-control::轮询全局并发与背压"
],
"exit_status": 0
}
},
{
"capability": "polling-load-control",
"requirement": "正常无变化观测的低写入处理",
"spec": "openspec/specs/polling-load-control/spec.md",
"entries": [
"constants.TaskTypePollingCarddata",
"constants.TaskTypePollingCardStatus",
"constants.TaskTypePollingRealname"
],
"handler_consumer_job": [
"internal/task/polling_carddata_handler.go:PollingCarddataHandler.Handle",
"internal/task/polling_cardstatus_handler.go:PollingCardStatusHandler.Handle",
"internal/task/polling_realname_handler.go:PollingRealnameHandler.Handle",
"internal/task/polling_integration_log.go:recordGatewayAttempt"
],
"application_service_query": [
"internal/application/cardobservation/traffic.go:ApplyTrafficObservation",
"internal/application/cardobservation/network.go:ApplyNetworkObservation",
"internal/application/cardobservation/apply.go:ApplyCardObservation"
],
"domain_state_amount": [
"internal/task/polling_integration_log.go:attempt created in memory then persisted only on decided outcome"
],
"store_migration_config": [
"internal/infrastructure/integrationlog.Repository"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'attempt := newGatewayAttempt'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'h.observation.ApplyTrafficObservation'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'changed := decision.IncrementMB > 0 || decision.CrossMonth'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'if changed {'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'attempt := newGatewayAttempt'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'h.observation.ApplyNetworkObservation'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'changed := decision.StatusChanged || decision.StopReasonChanged || decision.StopPolling'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'if changed {'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'attempt := newGatewayAttempt'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'h.observation.ApplyCardObservation'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'changed := decision.StatusChanged'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'if changed {'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"')]; ordered=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"']), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"']), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"']), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'attempt := newGatewayAttempt'\"'\"', '\"'\"'h.observation.ApplyTrafficObservation'\"'\"', '\"'\"'changed := decision.IncrementMB > 0 || decision.CrossMonth'\"'\"', '\"'\"'if changed {'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'attempt := newGatewayAttempt'\"'\"', '\"'\"'h.observation.ApplyNetworkObservation'\"'\"', '\"'\"'changed := decision.StatusChanged || decision.StopReasonChanged || decision.StopPolling'\"'\"', '\"'\"'if changed {'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'attempt := newGatewayAttempt'\"'\"', '\"'\"'h.observation.ApplyCardObservation'\"'\"', '\"'\"'changed := decision.StatusChanged'\"'\"', '\"'\"'if changed {'\"'\"', '\"'\"'IntegrationResultSuccess, true'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: polling-load-control::正常无变化观测的低写入处理'\"'\"')'",
"literal_output": [
"OK: polling-load-control::正常无变化观测的低写入处理"
],
"exit_status": 0
}
},
{
"capability": "polling-load-control",
"requirement": "业务变化与轮询异常仍可追溯",
"spec": "openspec/specs/polling-load-control/spec.md",
"entries": [
"constants.TaskTypePollingCarddata",
"constants.TaskTypePollingCardStatus",
"constants.TaskTypePollingRealname"
],
"handler_consumer_job": [
"internal/task/polling_carddata_handler.go:PollingCarddataHandler.Handle",
"internal/task/polling_cardstatus_handler.go:PollingCardStatusHandler.Handle",
"internal/task/polling_realname_handler.go:PollingRealnameHandler.Handle",
"internal/task/polling_integration_log.go:recordGatewayAttempt"
],
"application_service_query": [
"internal/application/cardobservation/traffic.go:ApplyTrafficObservation",
"internal/application/cardobservation/network.go:ApplyNetworkObservation",
"internal/application/cardobservation/apply.go:ApplyCardObservation"
],
"domain_state_amount": [
"internal/task polling gateway failure/result paths",
"internal/application/cardobservation traffic/network Outbox and worker audit paths"
],
"store_migration_config": [
"internal/infrastructure/integrationlog.Repository"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'IntegrationResultFailed'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'应用流量观测失败'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'IntegrationResultUnknown'\"'\"'), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'IntegrationResultFailed'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'应用网络状态观测失败'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'IntegrationResultUnknown'\"'\"'), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'IntegrationResultFailed'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'应用实名观测失败'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'IntegrationResultUnknown'\"'\"'), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"')]; ordered=[('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCarddata)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCarddata)'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingCardStatus)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingCardStatus)'\"'\"']), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingPackage)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingPackage)'\"'\"']), ('\"'\"'internal/task/polling_protect_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingProtect)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingProtect)'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'!h.base.acquireConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'return h.base.requeueCard(ctx, cardID, constants.TaskTypePollingRealname)'\"'\"', '\"'\"'defer h.base.releaseConcurrency(ctx, constants.TaskTypePollingRealname)'\"'\"']), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'IntegrationResultFailed'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"']), ('\"'\"'internal/task/polling_carddata_handler.go'\"'\"', ['\"'\"'IntegrationResultUnknown'\"'\"', '\"'\"'应用流量观测失败'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'IntegrationResultFailed'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"']), ('\"'\"'internal/task/polling_cardstatus_handler.go'\"'\"', ['\"'\"'IntegrationResultUnknown'\"'\"', '\"'\"'应用网络状态观测失败'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'IntegrationResultFailed'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"']), ('\"'\"'internal/task/polling_realname_handler.go'\"'\"', ['\"'\"'IntegrationResultUnknown'\"'\"', '\"'\"'应用实名观测失败'\"'\"', '\"'\"'return h.failAndRequeue'\"'\"'])]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: polling-load-control::业务变化与轮询异常仍可追溯'\"'\"')'",
"literal_output": [
"OK: polling-load-control::业务变化与轮询异常仍可追溯"
],
"exit_status": 0
}
},
{
"capability": "polling-operations",
"requirement": "停复机遵循实际生效实名策略",
"spec": "openspec/specs/polling-operations/spec.md",
"entries": [
"constants.TaskTypePollingPackage"
],
"handler_consumer_job": [
"internal/task/polling_package_handler.go:PollingPackageHandler.Handle",
"pkg/queue/handler.go:registerPollingHandlers"
],
"application_service_query": [
"internal/task/polling_package_handler.go:PollingPackageHandler.Handle -> StopResumeServiceInterface.EvaluateAndAct",
"internal/service/iot_card/stop_resume_service.go:StopResumeService.EvaluateAndAct/isRealnameOK"
],
"domain_state_amount": [
"internal/model/iot_card.go:IotCard.RealnamePolicy",
"internal/model/device.go:Device.RealnamePolicy"
],
"store_migration_config": [
"internal/task/polling_package_handler.go:IotCardStore.GetByID"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'func (h *PollingPackageHandler) Handle'\"'\"'), ('\"'\"'internal/task/polling_package_handler.go'\"'\"', '\"'\"'h.stopResumeSvc.EvaluateAndAct(ctx, freshCard)'\"'\"'), ('\"'\"'pkg/queue/handler.go'\"'\"', '\"'\"'h.mux.HandleFunc(constants.TaskTypePollingPackage, packageHandler.Handle)'\"'\"'), ('\"'\"'internal/service/iot_card/stop_resume_service.go'\"'\"', '\"'\"'func (s *StopResumeService) isRealnameOK'\"'\"')]; ordered=[]; absent=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: polling-operations::停复机遵循实际生效实名策略'\"'\"')'",
"literal_output": [
"OK: polling-operations::停复机遵循实际生效实名策略"
],
"exit_status": 0
}
},
{
"capability": "qicheng-migration-package-lifecycle-overrides",
"requirement": "迁移配置支持逐卡套餐生命周期覆盖",
"spec": "openspec/specs/qicheng-migration-package-lifecycle-overrides/spec.md",
"entries": [
"scripts/migration/migrate_runtime.py"
],
"handler_consumer_job": [
"scripts/migration/migrate_runtime.py:main"
],
"application_service_query": [
"scripts/migration/lib/mapping_loader.py:Mapping.lookup_package_lifecycle_override",
"scripts/migration/lib/sql_builder.py:_apply_package_lifecycle_override"
],
"domain_state_amount": [
"scripts/migration/lib/mapping_loader.py:PackageLifecycleOverride"
],
"store_migration_config": [
"scripts/migration/config/mapping.yaml",
"scripts/migration/lib/legacy_query.py:tbl_card_life"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/mapping_loader.py'\"'\"', '\"'\"'package_lifecycle_overrides'\"'\"'), ('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'_apply_package_lifecycle_override'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: qicheng-migration-package-lifecycle-overrides::迁移配置支持逐卡套餐生命周期覆盖'\"'\"')'",
"literal_output": [
"OK: qicheng-migration-package-lifecycle-overrides::迁移配置支持逐卡套餐生命周期覆盖"
],
"exit_status": 0
}
},
{
"capability": "qicheng-migration-package-lifecycle-overrides",
"requirement": "覆盖必须完整且可验证",
"spec": "openspec/specs/qicheng-migration-package-lifecycle-overrides/spec.md",
"entries": [
"scripts/migration/migrate_runtime.py"
],
"handler_consumer_job": [
"scripts/migration/migrate_runtime.py:main"
],
"application_service_query": [
"scripts/migration/lib/sql_builder.py:_apply_package_lifecycle_override"
],
"domain_state_amount": [
"scripts/migration/lib/sql_builder.py:selected != migratable"
],
"store_migration_config": [
"scripts/migration/lib/mapping_loader.py:_load_package_lifecycle_overrides"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'套餐生命周期覆盖必须完整裁决原本可迁移记录'\"'\"'), ('\"'\"'scripts/migration/lib/mapping_loader.py'\"'\"', '\"'\"'生命周期 ID 不可重复或跨状态重复'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: qicheng-migration-package-lifecycle-overrides::覆盖必须完整且可验证'\"'\"')'",
"literal_output": [
"OK: qicheng-migration-package-lifecycle-overrides::覆盖必须完整且可验证"
],
"exit_status": 0
}
},
{
"capability": "qicheng-migration-package-lifecycle-overrides",
"requirement": "未覆盖资产维持严格冲突阻断",
"spec": "openspec/specs/qicheng-migration-package-lifecycle-overrides/spec.md",
"entries": [
"scripts/migration/migrate_runtime.py"
],
"handler_consumer_job": [
"scripts/migration/migrate_runtime.py:main"
],
"application_service_query": [
"scripts/migration/lib/sql_builder.py:_resolve_runtime_packages"
],
"domain_state_amount": [
"scripts/migration/lib/sql_builder.py:multiple_active_packages/blocked"
],
"store_migration_config": [
"scripts/migration/lib/legacy_query.py:tbl_card_life"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'multiple_active_packages'\"'\"'), ('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'同一资产存在多个当前生效正式套餐,无法唯一裁决'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: qicheng-migration-package-lifecycle-overrides::未覆盖资产维持严格冲突阻断'\"'\"')'",
"literal_output": [
"OK: qicheng-migration-package-lifecycle-overrides::未覆盖资产维持严格冲突阻断"
],
"exit_status": 0
}
},
{
"capability": "qicheng-migration-package-usage",
"requirement": "迁移套餐使用记录保存计时条款快照",
"spec": "openspec/specs/qicheng-migration-package-usage/spec.md",
"entries": [
"scripts/migration/migrate_runtime.py"
],
"handler_consumer_job": [
"scripts/migration/migrate_runtime.py:main"
],
"application_service_query": [
"scripts/migration/lib/sql_builder.py:_write_package_usages"
],
"domain_state_amount": [
"scripts/migration/lib/sql_builder.py:expiry_base_snapshot/calendar_type_snapshot/duration snapshots"
],
"store_migration_config": [
"migrations/000163_add_package_usage_terms_snapshots.up.sql"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'expiry_base_snapshot, calendar_type_snapshot, duration_months_snapshot, duration_days_snapshot'\"'\"'), ('\"'\"'scripts/migration/lib/sql_builder.py'\"'\"', '\"'\"'INSERT INTO tb_package_usage'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: qicheng-migration-package-usage::迁移套餐使用记录保存计时条款快照'\"'\"')'",
"literal_output": [
"OK: qicheng-migration-package-usage::迁移套餐使用记录保存计时条款快照"
],
"exit_status": 0
}
},
{
"capability": "qicheng-migration-package-usage",
"requirement": "迁移套餐使用 SQL 满足快照完整性约束",
"spec": "openspec/specs/qicheng-migration-package-usage/spec.md",
"entries": [
"scripts/migration/migrate_runtime.py"
],
"handler_consumer_job": [
"scripts/migration/migrate_runtime.py:main"
],
"application_service_query": [
"scripts/migration/lib/sql_builder.py:_write_package_usages"
],
"domain_state_amount": [
"migrations/000163_add_package_usage_terms_snapshots.up.sql:validate_package_usage_terms_snapshot"
],
"store_migration_config": [
"migrations/000163_add_package_usage_terms_snapshots.up.sql:trg_validate_package_usage_terms_snapshot"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'migrations/000163_add_package_usage_terms_snapshots.up.sql'\"'\"', '\"'\"'CREATE TRIGGER trg_validate_package_usage_terms_snapshot'\"'\"'), ('\"'\"'migrations/000163_add_package_usage_terms_snapshots.up.sql'\"'\"', '\"'\"'套餐使用记录计时快照不完整或无效'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: qicheng-migration-package-usage::迁移套餐使用 SQL 满足快照完整性约束'\"'\"')'",
"literal_output": [
"OK: qicheng-migration-package-usage::迁移套餐使用 SQL 满足快照完整性约束"
],
"exit_status": 0
}
},
{
"capability": "refund-approval",
"requirement": "零金额退款审批通过",
"spec": "openspec/specs/refund-approval/spec.md",
"entries": [
"POST /api/admin/refunds/{id}/approve"
],
"handler_consumer_job": [
"internal/handler/admin/refund.go:RefundHandler.ApproveBodyParser 后直接传 Service该方法体无 Validate/ValidateStruct 调用)",
"cmd/worker/main.go:ApprovalBusinessTypeRefund -> refund.Service.Handle"
],
"application_service_query": [
"internal/service/refund/service.go:Service.Approve/validateApprovedRefundAmount",
"internal/service/refund/approval_decision.go:Service.applyApprovedDecision"
],
"domain_state_amount": [
"Service 和企业微信受控审批决策路径可传递/处理 approvedAmount == 0公开 DTO 字段仍标记 omitempty,min=1"
],
"store_migration_config": [
"internal/model/refund.go:RefundRequest",
"migrations/archive/000093_create_refund_request.up.sql"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/model/dto/refund_dto.go'\"'\"', '\"'\"'validate:\"omitempty,min=1\"'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'func (h *RefundHandler) Approve'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'if approvedAmount < 0'\"'\"'), ('\"'\"'internal/service/refund/approval_decision.go'\"'\"', '\"'\"'approvedAmount := refund.RequestedRefundAmount'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/refund.go'\"'\"', ['\"'\"'func (h *RefundHandler) Approve'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'])]; absent=[('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'ValidateStruct'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'.Validate('\"'\"')]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: refund-approval::零金额退款审批通过'\"'\"')'",
"literal_output": [
"OK: refund-approval::零金额退款审批通过"
],
"exit_status": 0
}
},
{
"capability": "refund-approval",
"requirement": "零金额退款不产生资金回款",
"spec": "openspec/specs/refund-approval/spec.md",
"entries": [
"POST /api/admin/refunds/{id}/approve"
],
"handler_consumer_job": [
"internal/handler/admin/refund.go:RefundHandler.ApproveBodyParser 后直接传 Service该方法体无 Validate/ValidateStruct 调用)",
"cmd/worker/main.go:ApprovalBusinessTypeRefund -> refund.Service.Handle"
],
"application_service_query": [
"internal/service/refund/service.go:Service.Approve/validateApprovedRefundAmount",
"internal/service/refund/approval_decision.go:Service.applyApprovedDecision"
],
"domain_state_amount": [
"Service 和企业微信受控审批决策路径可传递/处理 approvedAmount == 0公开 DTO 字段仍标记 omitempty,min=1"
],
"store_migration_config": [
"internal/model/refund.go:RefundRequest",
"migrations/archive/000093_create_refund_request.up.sql"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/model/dto/refund_dto.go'\"'\"', '\"'\"'validate:\"omitempty,min=1\"'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'func (h *RefundHandler) Approve'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'if approvedAmount < 0'\"'\"'), ('\"'\"'internal/service/refund/approval_decision.go'\"'\"', '\"'\"'approvedAmount := refund.RequestedRefundAmount'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'if amount == 0 || order.PaymentMethod != model.PaymentMethodWallet'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/refund.go'\"'\"', ['\"'\"'func (h *RefundHandler) Approve'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'])]; absent=[('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'ValidateStruct'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'.Validate('\"'\"')]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: refund-approval::零金额退款不产生资金回款'\"'\"')'",
"literal_output": [
"OK: refund-approval::零金额退款不产生资金回款"
],
"exit_status": 0
}
},
{
"capability": "refund-approval",
"requirement": "非法退款金额仍被拒绝",
"spec": "openspec/specs/refund-approval/spec.md",
"entries": [
"POST /api/admin/refunds/{id}/approve"
],
"handler_consumer_job": [
"internal/handler/admin/refund.go:RefundHandler.ApproveBodyParser 后直接传 Service该方法体无 Validate/ValidateStruct 调用)",
"cmd/worker/main.go:ApprovalBusinessTypeRefund -> refund.Service.Handle"
],
"application_service_query": [
"internal/service/refund/service.go:Service.Approve/validateApprovedRefundAmount",
"internal/service/refund/approval_decision.go:Service.applyApprovedDecision"
],
"domain_state_amount": [
"Service 和企业微信受控审批决策路径可传递/处理 approvedAmount == 0公开 DTO 字段仍标记 omitempty,min=1"
],
"store_migration_config": [
"internal/model/refund.go:RefundRequest",
"migrations/archive/000093_create_refund_request.up.sql"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'internal/model/dto/refund_dto.go'\"'\"', '\"'\"'validate:\"omitempty,min=1\"'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'func (h *RefundHandler) Approve'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'if approvedAmount < 0'\"'\"'), ('\"'\"'internal/service/refund/approval_decision.go'\"'\"', '\"'\"'approvedAmount := refund.RequestedRefundAmount'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'审批退款金额不能大于申请退款金额'\"'\"'), ('\"'\"'internal/service/refund/service.go'\"'\"', '\"'\"'申请退款金额不能大于订单实收金额'\"'\"')]; ordered=[('\"'\"'internal/handler/admin/refund.go'\"'\"', ['\"'\"'func (h *RefundHandler) Approve'\"'\"', '\"'\"'if err := c.BodyParser(&req); err != nil'\"'\"', '\"'\"'h.service.Approve(c.UserContext(), uint(id), &req)'\"'\"'])]; absent=[('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'ValidateStruct'\"'\"'), ('\"'\"'internal/handler/admin/refund.go'\"'\"', '\"'\"'.Validate('\"'\"')]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; unordered=[]; exec(\"for p,ts in ordered:\\n text=Path(p).read_text(); pos=-1; ok=True\\n for t in ts:\\n pos=text.find(t,pos+1)\\n if pos<0: ok=False; break\\n if not ok: unordered.append(f'\"'\"'{p}:{ts}'\"'\"')\"); present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in absent if t in Path(p).read_text()]; assert not missing and not unordered and not present, {'\"'\"'missing'\"'\"':missing,'\"'\"'unordered'\"'\"':unordered,'\"'\"'present'\"'\"':present}; print('\"'\"'OK: refund-approval::非法退款金额仍被拒绝'\"'\"')'",
"literal_output": [
"OK: refund-approval::非法退款金额仍被拒绝"
],
"exit_status": 0
}
},
{
"capability": "shop-bulk-import",
"requirement": "导入输入必须在生成 SQL 前完成全量预检",
"spec": "openspec/specs/shop-bulk-import/spec.md",
"entries": [
"scripts/migration/import_shops.py"
],
"handler_consumer_job": [
"scripts/migration/import_shops.py:main"
],
"application_service_query": [
"scripts/migration/lib/shop_import.py:load_config/load_plan"
],
"domain_state_amount": [
"scripts/migration/lib/shop_import.py:ShopImportPlan.errors"
],
"store_migration_config": [
"scripts/migration/config/shop_bulk_import.yaml"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/import_shops.py'\"'\"', '\"'\"'plan = load_plan(csv_path, config)'\"'\"'), ('\"'\"'scripts/migration/import_shops.py'\"'\"', '\"'\"'if plan.errors:'\"'\"'), ('\"'\"'scripts/migration/lib/shop_import.py'\"'\"', '\"'\"'def load_plan'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: shop-bulk-import::导入输入必须在生成 SQL 前完成全量预检'\"'\"')'",
"literal_output": [
"OK: shop-bulk-import::导入输入必须在生成 SQL 前完成全量预检"
],
"exit_status": 0
}
},
{
"capability": "shop-bulk-import",
"requirement": "生成的 SQL 必须在写入前校验目标库状态",
"spec": "openspec/specs/shop-bulk-import/spec.md",
"entries": [
"scripts/migration/import_shops.py"
],
"handler_consumer_job": [
"scripts/migration/import_shops.py:main"
],
"application_service_query": [
"scripts/migration/lib/shop_sql.py:build_shop_sql/_preflight_sql"
],
"domain_state_amount": [
"scripts/migration/lib/shop_sql.py:DO $shop_import_guard$"
],
"store_migration_config": [
"scripts/migration/lib/shop_sql.py:tb_role/tb_account/tb_shop guards"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'所有目标库守卫必须在业务写入前完成。'\"'\"'), ('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'DO $shop_import_guard$'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: shop-bulk-import::生成的 SQL 必须在写入前校验目标库状态'\"'\"')'",
"literal_output": [
"OK: shop-bulk-import::生成的 SQL 必须在写入前校验目标库状态"
],
"exit_status": 0
}
},
{
"capability": "shop-bulk-import",
"requirement": "批量导入 SQL 必须创建完整的店铺初始事实",
"spec": "openspec/specs/shop-bulk-import/spec.md",
"entries": [
"scripts/migration/import_shops.py"
],
"handler_consumer_job": [
"scripts/migration/import_shops.py:main"
],
"application_service_query": [
"scripts/migration/lib/shop_sql.py:_row_sql/_audit_sql"
],
"domain_state_amount": [
"scripts/migration/lib/shop_import.py:initial_password_hash"
],
"store_migration_config": [
"scripts/migration/lib/shop_sql.py:tb_shop/tb_account/tb_account_role/tb_shop_role/tb_agent_wallet/tb_audit_event"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'INSERT INTO tb_shop'\"'\"'), ('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'INSERT INTO tb_account_role'\"'\"'), ('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'INSERT INTO tb_agent_wallet'\"'\"'), ('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'INSERT INTO tb_audit_event'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: shop-bulk-import::批量导入 SQL 必须创建完整的店铺初始事实'\"'\"')'",
"literal_output": [
"OK: shop-bulk-import::批量导入 SQL 必须创建完整的店铺初始事实"
],
"exit_status": 0
}
},
{
"capability": "shop-bulk-import",
"requirement": "导入执行必须由维护者审核后以单事务手工确认",
"spec": "openspec/specs/shop-bulk-import/spec.md",
"entries": [
"scripts/migration/import_shops.py"
],
"handler_consumer_job": [
"scripts/migration/import_shops.py:main"
],
"application_service_query": [
"scripts/migration/lib/shop_sql.py:build_shop_sql"
],
"domain_state_amount": [
"scripts/migration/lib/shop_sql.py:review before psql -1"
],
"store_migration_config": [
"scripts/migration/lib/shop_sql.py:psql -1"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'执行前必须审核结果清单与摘要。'\"'\"'), ('\"'\"'scripts/migration/lib/shop_sql.py'\"'\"', '\"'\"'psql -1 -v ON_ERROR_STOP=1 -f <此文件>'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: shop-bulk-import::导入执行必须由维护者审核后以单事务手工确认'\"'\"')'",
"literal_output": [
"OK: shop-bulk-import::导入执行必须由维护者审核后以单事务手工确认"
],
"exit_status": 0
}
},
{
"capability": "shop-bulk-import",
"requirement": "导入结果必须可审核和重跑定位",
"spec": "openspec/specs/shop-bulk-import/spec.md",
"entries": [
"scripts/migration/import_shops.py"
],
"handler_consumer_job": [
"scripts/migration/import_shops.py:main"
],
"application_service_query": [
"scripts/migration/lib/shop_import.py:write_errors/write_results/write_summary"
],
"domain_state_amount": [
"scripts/migration/lib/shop_import.py:batch_id/ShopImportResult"
],
"store_migration_config": [
"scripts/migration/config/shop_bulk_import.yaml"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[('\"'\"'scripts/migration/import_shops.py'\"'\"', '\"'\"'write_results(result_path, plan.results)'\"'\"'), ('\"'\"'scripts/migration/import_shops.py'\"'\"', '\"'\"'write_summary(summary_path, plan, sql_path)'\"'\"'), ('\"'\"'scripts/migration/lib/shop_import.py'\"'\"', '\"'\"'batch_id={plan.config.batch_id}'\"'\"')]; negative=[]; missing=[f'\"'\"'{p}:{t}'\"'\"' for p,t in checks if t not in Path(p).read_text()]; present=[f'\"'\"'{p}:{t}'\"'\"' for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {'\"'\"'missing'\"'\"': missing, '\"'\"'present'\"'\"': present}; print('\"'\"'OK: shop-bulk-import::导入结果必须可审核和重跑定位'\"'\"')'",
"literal_output": [
"OK: shop-bulk-import::导入结果必须可审核和重跑定位"
],
"exit_status": 0
}
},
{
"capability": "employee-collection-bill",
"requirement": "员工代收款账单来源、金额与建账判据",
"spec": "openspec/specs/employee-collection-bill/spec.md",
"entries": [
"POST /api/admin/agent-recharges/{id}/offline-pay",
"POST /api/admin/orders",
"constants.OutboxEventTypeApprovalTerminalDecision"
],
"handler_consumer_job": [
"internal/service/order/service.go:Service.CreateAdminOrder",
"internal/service/agent_recharge/service.go:Service.OfflinePay",
"internal/application/agentrecharge/approval_decision.go:ApprovalDecisionHandler.Handle"
],
"application_service_query": [
"internal/application/employeecollection/bill_creation.go:BillCreationService.CreateFromOrderInTx",
"internal/application/employeecollection/bill_creation.go:BillCreationService.CreateFromRechargeInTx"
],
"domain_state_amount": [
"internal/domain/employeecollection/order_bill.go:ShouldCreateBillForOrder",
"internal/domain/employeecollection/order_bill.go:ShouldCreateBillForRecharge",
"internal/domain/employeecollection/order_bill.go:OrderBillSubjectFromOrder"
],
"store_migration_config": [
"internal/model/employee_collection.go:EmployeeCollectionBill",
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_bill"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/domain/employeecollection/order_bill.go\", \"func ShouldCreateBillForOrder(subject OrderBillSubject) bool\"), (\"internal/domain/employeecollection/order_bill.go\", \"subject.PaymentMethod == model.PaymentMethodOffline\"), (\"internal/service/order/service.go\", \"s.billCreation.CreateFromOrderInTx(ctx, tx, order, hasGiftPackage)\"), (\"internal/service/agent_recharge/service.go\", \"s.billCreation.CreateFromRechargeInTx(ctx, tx, record)\"), (\"internal/application/agentrecharge/approval_decision.go\", \"h.billCreation.CreateFromRechargeInTx(ctx, tx, record)\"), (\"internal/application/employeecollection/bill_creation.go\", \"Columns: []clause.Column{{Name: \\\"source_key\\\"}}\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: employee-collection-bill::员工代收款账单来源、金额与建账判据\")'",
"literal_output": [
"OK: employee-collection-bill::员工代收款账单来源、金额与建账判据"
],
"exit_status": 0
}
},
{
"capability": "employee-collection-bill",
"requirement": "账单余额、状态与关闭",
"spec": "openspec/specs/employee-collection-bill/spec.md",
"entries": [
"GET /api/admin/employee-collection-bills",
"GET /api/admin/employee-collection-bills/statistics",
"GET /api/admin/employee-collection-bills/{id}",
"POST /api/admin/employee-collection-bills/{id}/close",
"GET /api/admin/employee-collection-applications",
"GET /api/admin/employee-collection-applications/{id}"
],
"handler_consumer_job": [
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.ListBills",
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.StatisticsBills",
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.GetBill",
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.CloseBill"
],
"application_service_query": [
"internal/query/employeecollection/bill.go:BillQuery.List/Statistics/Detail",
"internal/query/employeecollection/bill.go:applyBillVisibility",
"internal/query/employeecollection/application.go:applyApplicationVisibility",
"internal/application/employeecollection/bill_close.go:BillCloseService.Close"
],
"domain_state_amount": [
"internal/domain/employeecollection/bill.go:BillAmounts.Reserve/Release/Approve",
"internal/domain/employeecollection/bill.go:BillAmounts.DerivedStatus",
"internal/domain/employeecollection/bill.go:ValidateBillClose"
],
"store_migration_config": [
"internal/model/employee_collection.go:EmployeeCollectionBill",
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_bill"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/domain/employeecollection/bill.go\", \"func (a BillAmounts) Reserve(amount int64) (BillAmounts, error)\"), (\"internal/domain/employeecollection/bill.go\", \"func (a BillAmounts) DerivedStatus() int\"), (\"internal/application/employeecollection/bill_close.go\", \"func (s *BillCloseService) Close(ctx context.Context, id uint, reason string)\"), (\"internal/query/employeecollection/bill.go\", \"func applyBillVisibility(ctx context.Context, query *gorm.DB) (*gorm.DB, error)\"), (\"internal/query/employeecollection/bill.go\", \"func (q *BillQuery) Statistics(\"), (\"internal/query/employeecollection/application.go\", \"func applyApplicationVisibility(ctx context.Context, query *gorm.DB) (*gorm.DB, error)\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: employee-collection-bill::账单余额、状态与关闭\")'",
"literal_output": [
"OK: employee-collection-bill::账单余额、状态与关闭"
],
"exit_status": 0
}
},
{
"capability": "employee-collection-bill",
"requirement": "外部付款核销申请与分摊",
"spec": "openspec/specs/employee-collection-bill/spec.md",
"entries": [
"POST /api/admin/employee-collection-applications",
"GET /api/admin/employee-collection-applications",
"GET /api/admin/employee-collection-applications/{id}"
],
"handler_consumer_job": [
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.CreateApplication",
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.ListApplications",
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.GetApplication",
"internal/handler/admin/employee_collection.go:bindApplicationRequest"
],
"application_service_query": [
"internal/application/employeecollection/application.go:ApplicationService.Create/submit",
"internal/application/employeecollection/application.go:lockBillsInAscendingOrder",
"internal/application/employeecollection/application.go:createAllocations",
"internal/query/employeecollection/application.go:ApplicationQuery.List/Detail"
],
"domain_state_amount": [
"internal/domain/employeecollection/allocation.go:ValidateAllocations",
"internal/domain/employeecollection/bill.go:BillAmounts.Reserve"
],
"store_migration_config": [
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_application",
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_application_allocation",
"internal/model/employee_collection.go:EmployeeCollectionApplicationAllocation"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/domain/employeecollection/allocation.go\", \"func ValidateAllocations(paidAmount int64, candidates []AllocationCandidate) error\"), (\"internal/application/employeecollection/application.go\", \"func (s *ApplicationService) Create(ctx context.Context, command SubmitApplicationCommand) (*ApplicationSubmitResult, error)\"), (\"internal/handler/admin/employee_collection.go\", \"func (h *EmployeeCollectionHandler) CreateApplication(c *fiber.Ctx) error\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: employee-collection-bill::外部付款核销申请与分摊\")'",
"literal_output": [
"OK: employee-collection-bill::外部付款核销申请与分摊"
],
"exit_status": 0
}
},
{
"capability": "employee-collection-bill",
"requirement": "核销申请审批、重提与幂等",
"spec": "openspec/specs/employee-collection-bill/spec.md",
"entries": [
"POST /api/callback/wecom/approval/{application_id}",
"constants.OutboxEventTypeApprovalSubmissionRequested",
"constants.OutboxEventTypeApprovalTerminalDecision",
"constants.TaskTypeWeComApprovalRecovery",
"constants.TaskTypeWeComApprovalSync",
"POST /api/admin/employee-collection-applications",
"PUT /api/admin/employee-collection-applications/{id}"
],
"handler_consumer_job": [
"internal/application/employeecollection/approval_decision.go:ApprovalDecisionHandler.Handle",
"internal/handler/callback/wecom_approval.go:WeComApprovalHandler.Receive",
"cmd/worker/main.go:ApprovalBusinessTypeEmployeeCollection -> employeecollectionApp.NewApprovalDecisionHandler",
"cmd/worker/main.go:TaskTypeWeComApprovalSync/TaskTypeWeComApprovalRecovery -> 既有查询与恢复机制"
],
"application_service_query": [
"internal/application/employeecollection/application.go:ApplicationService.Resubmit",
"internal/application/employeecollection/approval_decision.go:applyApproved/applyClosed/applyRevoked/revokeApproved/revokePending",
"internal/application/approval/create.go:CreationService.CreateInTx",
"internal/application/employeecollection/application.go:buildAttempt/nextAttemptNo"
],
"domain_state_amount": [
"internal/domain/employeecollection/application.go:ValidateApplicationResubmit",
"pkg/constants/approval.go:ApprovalBusinessTypeEmployeeCollection"
],
"store_migration_config": [
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_application_attempt",
"internal/model/employee_collection.go:EmployeeCollectionApplicationAttempt"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/application/employeecollection/application.go\", \"func (s *ApplicationService) Resubmit(ctx context.Context, applicationID uint, command SubmitApplicationCommand) (*ApplicationSubmitResult, error)\"), (\"internal/application/employeecollection/approval_decision.go\", \"func (h *ApprovalDecisionHandler) Handle(ctx context.Context, event approvalapp.TerminalDecisionEvent) error\"), (\"internal/application/employeecollection/approval_decision.go\", \"func (h *ApprovalDecisionHandler) revokePending(\"), (\"pkg/constants/approval.go\", \"ApprovalBusinessTypeEmployeeCollection = \\\"employee_collection_approval\\\"\"), (\"cmd/worker/main.go\", \"constants.ApprovalBusinessTypeEmployeeCollection: employeecollectionApp.NewApprovalDecisionHandler(\"), (\"internal/handler/callback/wecom_approval.go\", \"func (h *WeComApprovalHandler) Receive(c *fiber.Ctx) error\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: employee-collection-bill::核销申请审批、重提与幂等\")'",
"literal_output": [
"OK: employee-collection-bill::核销申请审批、重提与幂等"
],
"exit_status": 0
}
},
{
"capability": "employee-collection-bill",
"requirement": "收款方式字典、退款联动与可追溯性",
"spec": "openspec/specs/employee-collection-bill/spec.md",
"entries": [
"constants.OutboxEventTypeApprovalTerminalDecision",
"GET /api/admin/employee-collection-payment-methods",
"POST /api/admin/employee-collection-payment-methods",
"PUT /api/admin/employee-collection-payment-methods/{id}",
"DELETE /api/admin/employee-collection-payment-methods/{id}"
],
"handler_consumer_job": [
"internal/handler/admin/employee_collection.go:EmployeeCollectionHandler.ListPaymentMethods/CreatePaymentMethod/UpdatePaymentMethod/DeletePaymentMethod",
"internal/routes/employee_collection.go:requireEmployeeCollectionConfigAccess",
"internal/service/refund/approval_decision.go:Service.applyApprovedDecision"
],
"application_service_query": [
"internal/application/employeecollection/payment_method.go:PaymentMethodService.Create/Update/Delete",
"internal/application/employeecollection/refund_offset.go:RefundOffsetService.ApplyInTx"
],
"domain_state_amount": [
"internal/domain/employeecollection/bill.go:BillAmounts.ReduceReceivable",
"internal/domain/employeecollection/refund_offset.go:DecideRefundOffset"
],
"store_migration_config": [
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_payment_method",
"migrations/000212_add_employee_collection_bills.up.sql:tb_employee_collection_bill_refund",
"internal/model/employee_collection.go:EmployeeCollectionPaymentMethod",
"internal/model/employee_collection.go:EmployeeCollectionBillRefund"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/application/employeecollection/payment_method.go\", \"func (s *PaymentMethodService) Delete(ctx context.Context, id uint) error\"), (\"internal/application/employeecollection/payment_method.go\", \"func countPaymentMethodReferences(\"), (\"internal/routes/employee_collection.go\", \"func requireEmployeeCollectionConfigAccess(handler fiber.Handler) fiber.Handler\"), (\"internal/application/employeecollection/refund_offset.go\", \"func (s *RefundOffsetService) ApplyInTx(ctx context.Context, tx *gorm.DB, source RefundOffsetSource) error\"), (\"internal/domain/employeecollection/refund_offset.go\", \"func DecideRefundOffset(bill BillAmounts, refundAmount int64) (RefundOffsetDecision, error)\"), (\"internal/domain/employeecollection/bill.go\", \"func (a BillAmounts) ReduceReceivable(amount int64) (BillAmounts, error)\"), (\"internal/service/refund/approval_decision.go\", \"s.refundOffset.ApplyInTx(ctx, tx, employeecollectionapp.RefundOffsetSource{\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: employee-collection-bill::收款方式字典、退款联动与可追溯性\")'",
"literal_output": [
"OK: employee-collection-bill::收款方式字典、退款联动与可追溯性"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "代理自充允许方式配置可审计",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"GET /api/admin/agent-self-recharge-payment-methods",
"PUT /api/admin/agent-self-recharge-payment-methods"
],
"handler_consumer_job": [
"internal/routes/agent_self_recharge_payment_method.go",
"internal/handler/admin/agent_recharge.go"
],
"application_service_query": [
"internal/application/agentrecharge/online_payment_policy.go"
],
"domain_state_amount": [
"pkg/constants/system_config.go"
],
"store_migration_config": [
"internal/bootstrap/payment_method_config.go"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"pkg/constants/system_config.go\", \"SystemConfigAgentSelfRechargeAllowedMethods\"), (\"pkg/constants/system_config.go\", \"AgentSelfRechargeAllowedBoth\"), (\"internal/bootstrap/payment_method_config.go\", \"DefaultValue: constants.AgentSelfRechargeAllowedBoth\"), (\"internal/bootstrap/payment_method_config.go\", \"EnumValues: []string{constants.AgentSelfRechargeAllowedWechatOnly\"), (\"internal/handler/admin/agent_recharge.go\", \"func (h *AgentRechargeHandler) UpdateSelfRechargePaymentMethods(\"), (\"internal/routes/agent_self_recharge_payment_method.go\", \"仅超级管理员可以修改代理自充允许范围\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: agent-funds-commission::代理自充允许方式配置可审计\")'",
"literal_output": [
"OK: agent-funds-commission::代理自充允许方式配置可审计"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "线下预存款审批收款方式、其他凭证与交易流水号",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"POST /api/admin/agent-recharges"
],
"handler_consumer_job": [
"internal/handler/admin/agent_recharge.go",
"internal/application/agentrecharge/offline_creation.go"
],
"application_service_query": [
"internal/application/agentrecharge/offline_creation.go"
],
"domain_state_amount": [
"internal/model/agent_wallet.go"
],
"store_migration_config": [
"migrations/000213_add_agent_recharge_offline_fields.up.sql"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/application/agentrecharge/offline_creation.go\", \"func loadEnabledOfflinePaymentMethod(\"), (\"internal/application/agentrecharge/offline_creation.go\", \"func validateRechargeTransactionNo(\"), (\"internal/application/agentrecharge/offline_creation.go\", \"func validateVoucherKeys(\"), (\"migrations/000213_add_agent_recharge_offline_fields.up.sql\", \"external_transaction_no varchar(128)\"), (\"migrations/000213_add_agent_recharge_offline_fields.up.sql\", \"other_voucher_keys jsonb\"), (\"internal/model/agent_wallet.go\", \"column:external_transaction_no\"), (\"internal/model/agent_wallet.go\", \"column:offline_payment_method_code\"), (\"internal/application/wecom/scene.go\", \"constants.ApprovalFieldExternalTransactionNo\"), (\"internal/application/wecom/scene.go\", \"constants.ApprovalFieldOtherVoucherKey\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: agent-funds-commission::线下预存款审批收款方式、其他凭证与交易流水号\")'",
"literal_output": [
"OK: agent-funds-commission::线下预存款审批收款方式、其他凭证与交易流水号"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "付款凭证识别仅作交易流水号预填",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"POST /api/admin/agent-recharges/payment-voucher-ocr"
],
"handler_consumer_job": [
"internal/handler/admin/agent_recharge.go",
"internal/routes/agent_recharge.go"
],
"application_service_query": [
"internal/application/agentrecharge/payment_voucher_ocr.go"
],
"domain_state_amount": [],
"store_migration_config": [
"internal/gateway/payment_voucher.go"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/gateway/payment_voucher.go\", \"func (c *Client) ExtractPaymentVoucherOrderNumber(\"), (\"internal/application/agentrecharge/payment_voucher_ocr.go\", \"func (s *PaymentVoucherOCRService) Recognize(\"), (\"internal/application/agentrecharge/payment_voucher_ocr.go\", \"ExternalTransactionNo string\"), (\"internal/handler/admin/agent_recharge.go\", \"func (h *AgentRechargeHandler) PaymentVoucherOCR(\"), (\"internal/routes/agent_recharge.go\", \"/payment-voucher-ocr\")]; negative=[(\"internal/application/agentrecharge/payment_voucher_ocr.go\", \"AmountCent\"), (\"internal/application/agentrecharge/payment_voucher_ocr.go\", \"Payee\"), (\"internal/application/agentrecharge/payment_voucher_ocr.go\", \"PaymentTime\")]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: agent-funds-commission::付款凭证识别仅作交易流水号预填\")'",
"literal_output": [
"OK: agent-funds-commission::付款凭证识别仅作交易流水号预填"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "线下收款方式字典对代理充值引用的可见性",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"PUT /api/admin/employee-collection-payment-methods/{id}",
"DELETE /api/admin/employee-collection-payment-methods/{id}"
],
"handler_consumer_job": [
"internal/handler/admin/employee_collection.go"
],
"application_service_query": [
"internal/application/employeecollection/payment_method.go"
],
"domain_state_amount": [
"internal/domain/employeecollection/payment_method.go"
],
"store_migration_config": [
"internal/model/agent_wallet.go"
],
"verification": {
"command": "python3 -c 'from pathlib import Path; checks=[(\"internal/application/employeecollection/payment_method.go\", \"func countPaymentMethodReferences(\"), (\"internal/application/employeecollection/payment_method.go\", \"model.AgentRechargeRecord{}\"), (\"internal/application/employeecollection/payment_method.go\", \"offline_payment_method_id = ?\"), (\"internal/application/employeecollection/payment_method.go\", \"线下收款方式已被核销申请或代理充值申请引用,不能修改稳定编码\")]; negative=[]; missing=[f\"{p}:{t}\" for p,t in checks if t not in Path(p).read_text()]; present=[f\"{p}:{t}\" for p,t in negative if t in Path(p).read_text()]; assert not missing and not present, {\"missing\": missing, \"present\": present}; print(\"OK: agent-funds-commission::线下收款方式字典对代理充值引用的可见性\")'",
"literal_output": [
"OK: agent-funds-commission::线下收款方式字典对代理充值引用的可见性"
],
"exit_status": 0
}
},
{
"capability": "agent-distribution-withdrawal",
"requirement": "分销码与待审批代理注册",
"spec": "openspec/specs/agent-distribution-withdrawal/spec.md",
"entries": [
"/api/c/v1/agent-distribution-registrations"
],
"handler_consumer_job": [
"internal/routes/agent_distribution_public.go",
"internal/handler/app/agent_distribution.go",
"internal/application/distributionwithdrawal/registration_approval.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/application/distributionwithdrawal/registration.go"
],
"domain_state_amount": [
"internal/domain/distribution/distribution.go",
"pkg/constants/approval.go"
],
"store_migration_config": [
"migrations/000214_add_agent_distribution_registration.up.sql",
"migrations/000217_backfill_shop_distribution_code.up.sql"
],
"verification": {
"command": "grep -rn \"分销码不可用\" internal/",
"literal_output": [
"internal/application/distributionwithdrawal/registration.go:64:return nil, errors.New(errors.CodeInvalidParam, \"分销码不可用\")"
],
"exit_status": 0
}
},
{
"capability": "agent-distribution-withdrawal",
"requirement": "提现资料资格",
"spec": "openspec/specs/agent-distribution-withdrawal/spec.md",
"entries": [
"/api/admin/shops/{shop_id}/withdrawal-qualifications",
"/api/admin/withdrawal-qualifications/{id}/void"
],
"handler_consumer_job": [
"internal/routes/shop.go",
"internal/handler/admin/withdrawal_qualification.go",
"internal/application/distributionwithdrawal/qualification_approval.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/application/distributionwithdrawal/qualification.go"
],
"domain_state_amount": [
"pkg/constants/withdrawal_qualification.go",
"pkg/constants/approval.go"
],
"store_migration_config": [
"migrations/000215_add_withdrawal_qualification_and_attempt.up.sql"
],
"verification": {
"command": "grep -rn \"uk_withdrawal_qualification_valid\" migrations/",
"literal_output": [
"migrations/000215_add_withdrawal_qualification_and_attempt.up.sql:50:CREATE UNIQUE INDEX uk_withdrawal_qualification_valid"
],
"exit_status": 0
}
},
{
"capability": "agent-distribution-withdrawal",
"requirement": "提现冻结与企业微信终审",
"spec": "openspec/specs/agent-distribution-withdrawal/spec.md",
"entries": [
"/api/admin/shops/{shop_id}/withdrawal-requests"
],
"handler_consumer_job": [
"internal/routes/shop.go",
"internal/handler/admin/shop_commission.go",
"internal/application/distributionwithdrawal/withdrawal.go",
"internal/application/distributionwithdrawal/withdrawal_approval.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/application/distributionwithdrawal/withdrawal.go"
],
"domain_state_amount": [
"internal/domain/wallet/wallet.go",
"pkg/constants/commission_withdrawal.go",
"pkg/constants/approval.go"
],
"store_migration_config": [
"internal/store/postgres/commission_withdrawal_request_store.go",
"migrations/000215_add_withdrawal_qualification_and_attempt.up.sql"
],
"verification": {
"command": "sed -n \"120,130p\" internal/application/distributionwithdrawal/withdrawal_approval.go",
"literal_output": [
"internal/application/distributionwithdrawal/withdrawal_approval.go:125:\"status\": constants.WithdrawalStatusApproved,"
],
"exit_status": 0
}
},
{
"capability": "agent-distribution-withdrawal",
"requirement": "提现本地人工终审边界",
"spec": "openspec/specs/agent-distribution-withdrawal/spec.md",
"entries": [
"/api/admin/commission/withdrawal-requests/{id}/approve",
"/api/admin/commission/withdrawal-requests/{id}/reject"
],
"handler_consumer_job": [
"internal/routes/commission.go",
"internal/handler/admin/commission_withdrawal.go"
],
"application_service_query": [
"internal/service/commission_withdrawal/service.go"
],
"domain_state_amount": [
"pkg/constants/commission_withdrawal.go"
],
"store_migration_config": [
"internal/store/postgres/commission_withdrawal_request_store.go",
"migrations/000215_add_withdrawal_qualification_and_attempt.up.sql"
],
"verification": {
"command": "grep -rn \"提现申请已接入企业微信终审\" internal/",
"literal_output": [
"internal/service/commission_withdrawal/service.go:165:businessErr := errors.New(errors.CodeConflict, \"提现申请已接入企业微信终审,不支持本地人工处理\")",
"internal/service/commission_withdrawal/service.go:292:businessErr := errors.New(errors.CodeConflict, \"提现申请已接入企业微信终审,不支持本地人工处理\")"
],
"exit_status": 0
}
},
{
"capability": "agent-distribution-withdrawal",
"requirement": "待审提现与佣金回溯的释放接缝",
"spec": "openspec/specs/agent-distribution-withdrawal/spec.md",
"entries": [],
"handler_consumer_job": [
"internal/application/distributionwithdrawal/withdrawal.go",
"internal/service/refund/service.go"
],
"application_service_query": [
"internal/application/distributionwithdrawal/withdrawal.go"
],
"domain_state_amount": [
"internal/model/financial.go",
"pkg/constants/commission_withdrawal.go"
],
"store_migration_config": [
"internal/store/postgres/withdrawal_attempt_release.go",
"migrations/000215_add_withdrawal_qualification_and_attempt.up.sql"
],
"verification": {
"command": "grep -n \"released_at IS NULL\" internal/store/postgres/withdrawal_attempt_release.go",
"literal_output": [
"internal/store/postgres/withdrawal_attempt_release.go:41:.Where(\"request_id IN ? AND released_at IS NULL\", requestIDs).",
"internal/store/postgres/withdrawal_attempt_release.go:50:Where(\"id = ? AND released_at IS NULL\", attempt.ID)."
],
"exit_status": 0
}
},
{
"capability": "personal-customer",
"requirement": "资产信息展示当前可用或已用完主套餐",
"spec": "openspec/specs/personal-customer/spec.md",
"entries": [
"/api/c/v1/asset/info"
],
"handler_consumer_job": [
"internal/routes/personal.go",
"internal/handler/app/client_asset.go"
],
"application_service_query": [
"internal/service/asset/service.go"
],
"domain_state_amount": [
"pkg/constants/constants.go"
],
"store_migration_config": [
"internal/store/postgres/package_usage_store.go",
"internal/model/package.go"
],
"verification": {
"command": "grep -n \"PackageUsageStatusDepleted\" internal/store/postgres/package_usage_store.go",
"literal_output": [
"internal/store/postgres/package_usage_store.go:66:.Where(\"status IN (?, ?)\", constants.PackageUsageStatusActive, constants.PackageUsageStatusDepleted)."
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "退款实收金额与方式矩阵",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/handler/admin/refund.go"
],
"application_service_query": [
"internal/service/refund/method.go"
],
"domain_state_amount": [
"internal/model/refund.go",
"internal/model/payment.go",
"pkg/constants/refund.go"
],
"store_migration_config": [
"migrations/000218_add_refund_attempt_and_channel_refund.up.sql"
],
"verification": {
"command": "grep -n 'func (s \\*Service) decideRefundMethods' internal/service/refund/method.go",
"literal_output": [
"internal/service/refund/method.go:40:func (s *Service) decideRefundMethods(ctx context.Context, order *model.Order) (*refundMethodDecision, error) {"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "企业微信唯一终审与审批尝试重提",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds/{id}/resubmit",
"/api/callback/wecom/approval/{application_id}"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/handler/admin/refund.go",
"internal/application/refundapproval/creation.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/application/refundapproval/resolve.go",
"internal/service/refund/service.go"
],
"domain_state_amount": [
"pkg/constants/approval.go",
"internal/model/refund.go"
],
"store_migration_config": [
"migrations/000218_add_refund_attempt_and_channel_refund.up.sql"
],
"verification": {
"command": "grep -n 'BusinessID: attempt.ID' internal/application/refundapproval/creation.go",
"literal_output": [
"internal/application/refundapproval/creation.go:141:BusinessID: attempt.ID, SubmitterAccountID: current.Creator,",
"internal/application/refundapproval/creation.go:358:BusinessID: attempt.ID, SubmitterAccountID: current.Creator,"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "原路退款渠道能力与执行",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"constants.TaskTypeRefundChannelRecovery"
],
"handler_consumer_job": [
"internal/infrastructure/payment/refund_channel_recovery_task.go",
"internal/infrastructure/payment/refund_adapter.go",
"internal/application/refundchannel/event.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/application/refundchannel/service.go",
"internal/service/refund/payment_merchant.go"
],
"domain_state_amount": [
"pkg/constants/refund.go",
"pkg/wechat/payment_v2_refund.go",
"pkg/fuiou/refund.go",
"pkg/alipay/refund.go"
],
"store_migration_config": [
"migrations/000218_add_refund_attempt_and_channel_refund.up.sql",
"migrations/000219_add_wechat_v2_client_cert_credentials.up.sql"
],
"verification": {
"command": "grep -n 'func RefundCredentialIssue' internal/application/refundchannel/service.go",
"literal_output": [
"internal/application/refundchannel/service.go:452:func RefundCredentialIssue(providerType string, config *model.WechatConfig) string {"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "退款权益与订单状态时点",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/callback/wecom/approval/{application_id}",
"/api/admin/refunds/{id}/approve"
],
"handler_consumer_job": [
"internal/service/refund/approval_decision.go",
"internal/application/refundchannel/service.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/service/refund/service.go",
"internal/service/package/activation_service.go"
],
"domain_state_amount": [
"internal/model/order.go",
"internal/model/refund.go"
],
"store_migration_config": [
"migrations/000218_add_refund_attempt_and_channel_refund.up.sql"
],
"verification": {
"command": "grep -n 'originalRoute := refund.Method' internal/service/refund/approval_decision.go",
"literal_output": [
"internal/service/refund/approval_decision.go:120:originalRoute := refund.Method == constants.RefundMethodOriginalRoute"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "退款终态事实与失败分类",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds/{id}",
"constants.TaskTypeRefundChannelRecovery"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/handler/admin/refund.go",
"internal/infrastructure/audit/refund_channel.go"
],
"application_service_query": [
"internal/service/refund/attempt_query.go",
"internal/exporter/refund_scene.go"
],
"domain_state_amount": [
"pkg/constants/refund.go",
"internal/model/refund.go",
"internal/infrastructure/commissiondelivery/event.go"
],
"store_migration_config": [
"migrations/000218_add_refund_attempt_and_channel_refund.up.sql"
],
"verification": {
"command": "grep -n 'func RefundFailureReasonIsDefinitive' pkg/constants/refund.go",
"literal_output": [
"pkg/constants/refund.go:99:func RefundFailureReasonIsDefinitive(reason string) bool {"
],
"exit_status": 0
}
},
{
"capability": "order-refund-exchange",
"requirement": "退款展示当前退款套餐用量",
"spec": "openspec/specs/order-refund-exchange/spec.md",
"entries": [
"/api/admin/refunds",
"/api/admin/refunds/{id}"
],
"handler_consumer_job": [
"internal/routes/refund.go",
"internal/handler/admin/refund.go",
"internal/exporter/refund_scene.go"
],
"application_service_query": [
"internal/service/refund/package_usage.go"
],
"domain_state_amount": [
"internal/model/dto/refund_dto.go",
"internal/model/package.go"
],
"store_migration_config": [
"internal/model/package.go"
],
"verification": {
"command": "grep -n 'func (s \\*Service) loadRefundPackageUsages' internal/service/refund/package_usage.go",
"literal_output": [
"internal/service/refund/package_usage.go:33:func (s *Service) loadRefundPackageUsages(ctx context.Context, refunds []*model.RefundRequest) (map[uint]refundPackageUsage, error) {"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "套餐退款佣金回溯",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"constants.TaskTypeRefundCommissionRecovery"
],
"handler_consumer_job": [
"internal/service/refund/approval_decision.go",
"internal/infrastructure/commissiondelivery/event.go",
"cmd/worker/main.go"
],
"application_service_query": [
"internal/service/refund/clawback.go"
],
"domain_state_amount": [
"internal/model/commission_clawback.go",
"pkg/constants/iot.go"
],
"store_migration_config": [
"internal/store/postgres/commission_record_store.go",
"migrations/000220_add_commission_clawback_record.up.sql"
],
"verification": {
"command": "grep -nE 'uk_commission_clawback_refund_original|chk_commission_clawback_amount|chk_commission_clawback_withdrawable|chk_commission_clawback_status' migrations/000220_add_commission_clawback_record.up.sql",
"literal_output": [
"23: CONSTRAINT uk_commission_clawback_refund_original UNIQUE (refund_id, original_commission_id),",
"25: CONSTRAINT chk_commission_clawback_amount CHECK (amount < 0),",
"26: CONSTRAINT chk_commission_clawback_withdrawable CHECK (withdrawable = FALSE),",
"27: CONSTRAINT chk_commission_clawback_status CHECK (status = 5)"
],
"exit_status": 0
}
},
{
"capability": "agent-funds-commission",
"requirement": "回溯明细关联查询与导出",
"spec": "openspec/specs/agent-funds-commission/spec.md",
"entries": [
"/api/admin/shops/{shop_id}/commission-records",
"/api/admin/shops/{shop_id}/commission-records/{id}"
],
"handler_consumer_job": [
"internal/routes/shop.go",
"internal/handler/admin/shop_commission.go"
],
"application_service_query": [
"internal/service/shop_commission/service.go"
],
"domain_state_amount": [
"internal/model/dto/shop_commission_dto.go"
],
"store_migration_config": [
"internal/store/postgres/commission_record_store.go",
"internal/exporter/commission_record_scene.go"
],
"verification": {
"command": "grep -n 'ledger_clawback' internal/store/postgres/commission_record_store.go internal/exporter/commission_record_scene.go",
"literal_output": [
"internal/store/postgres/commission_record_store.go:118:\t\tRaw(\"SELECT * FROM (?) AS ledger_original UNION ALL SELECT * FROM (?) AS ledger_clawback\", original, clawback)",
"internal/exporter/commission_record_scene.go:60:\t\tRaw(\"SELECT * FROM (?) AS ledger_original UNION ALL SELECT * FROM (?) AS ledger_clawback\","
],
"exit_status": 0
}
},
{
"capability": "business-user-group",
"requirement": "业务用户组生命周期与成员归属",
"spec": "openspec/specs/business-user-group/spec.md",
"entries": [
"/api/admin/business-user-groups",
"/api/admin/business-user-groups/{id}",
"/api/admin/business-user-groups/{id}/members",
"/api/admin/business-user-groups/members"
],
"handler_consumer_job": [
"internal/routes/business_user_group.go",
"internal/handler/admin/business_user_group.go"
],
"application_service_query": [
"internal/application/businessusergroup/service.go"
],
"domain_state_amount": [
"internal/model/business_user_group.go",
"pkg/constants/business_user_group.go"
],
"store_migration_config": [
"internal/store/postgres/business_user_group_store.go",
"migrations/000221_add_business_user_group_and_shop_owner_import.up.sql"
],
"verification": {
"command": "grep -nE '用户组仍有成员|目标用户组已停用|uk_business_user_group_code|IsAvailablePlatformBusinessOwner' internal/application/businessusergroup/service.go",
"literal_output": [
"170:\t\t\treturn errors.New(errors.CodeInvalidStatus, \"用户组仍有成员,只能停用或先移走成员\")",
"202:\t\t\treturn errors.New(errors.CodeInvalidStatus, \"目标用户组已停用,不能作为成员归属目标\")",
"316:\t\tif constants.IsAvailablePlatformBusinessOwner(account.UserType, account.Status, account.DeletedAt.Valid) {",
"338:\tif strings.Contains(strings.ToLower(err.Error()), \"uk_business_user_group_code\") {"
],
"exit_status": 0
}
},
{
"capability": "business-user-group",
"requirement": "店铺负责人和所属组实时推导",
"spec": "openspec/specs/business-user-group/spec.md",
"entries": [
"/api/admin/shops",
"/api/admin/shops/{id}"
],
"handler_consumer_job": [
"internal/routes/shop.go",
"internal/query/shop/business_owner.go"
],
"application_service_query": [
"internal/query/shop/business_owner.go"
],
"domain_state_amount": [
"internal/model/dto/shop_dto.go",
"internal/model/business_user_group.go"
],
"store_migration_config": [
"migrations/000221_add_business_user_group_and_shop_owner_import.up.sql"
],
"verification": {
"command": "grep -nE 'EXISTS \\(SELECT 1 FROM tb_business_user_group_member|ungroupedCondition' internal/query/shop/business_owner.go",
"literal_output": [
"126:\t\t\t\"EXISTS (SELECT 1 FROM tb_business_user_group_member m WHERE m.account_id = tb_shop.business_owner_account_id AND m.deleted_at IS NULL AND m.business_user_group_id = ?)\",",
"131:\t\t\t\"EXISTS (SELECT 1 FROM tb_business_user_group_member m WHERE m.account_id = tb_shop.business_owner_account_id AND m.deleted_at IS NULL AND EXISTS (SELECT 1 FROM tb_business_user_group g WHERE g.id = m.business_user_group_id AND g.deleted_at IS NULL AND g.business_line = ?))\",",
"136:\t\tconst ungroupedCondition = \"(tb_shop.business_owner_account_id IS NULL OR NOT EXISTS (SELECT 1 FROM tb_business_user_group_member m WHERE m.account_id = tb_shop.business_owner_account_id AND m.deleted_at IS NULL))\"",
"138:\t\t\tdb = db.Where(ungroupedCondition)",
"140:\t\t\tdb = db.Where(\"NOT \" + ungroupedCondition)"
],
"exit_status": 0
}
},
{
"capability": "business-user-group",
"requirement": "店铺负责人批量交接",
"spec": "openspec/specs/business-user-group/spec.md",
"entries": [
"/api/admin/shops/business-owner/batch"
],
"handler_consumer_job": [
"internal/routes/business_user_group.go",
"internal/handler/admin/business_user_group.go"
],
"application_service_query": [
"internal/application/shop/batch_business_owner.go"
],
"domain_state_amount": [
"internal/model/dto/shop_dto.go"
],
"store_migration_config": [
"internal/infrastructure/audit/business_user_group.go"
],
"verification": {
"command": "grep -nE 'batchBusinessOwnerFailureMessage' internal/application/shop/batch_business_owner.go",
"literal_output": [
"102:\t\t\treturn errors.New(errors.CodeForbidden, batchBusinessOwnerFailureMessage)",
"122:\t\t\treturn errors.New(errors.CodeForbidden, batchBusinessOwnerFailureMessage)",
"203:// batchBusinessOwnerFailureMessage 复用平台维护入口的统一失败文案,不区分无权、不存在与已删除。",
"204:const batchBusinessOwnerFailureMessage = constants.PlatformManagementForbiddenMessage",
"243:\t\treturn nil, errors.New(errors.CodeForbidden, batchBusinessOwnerFailureMessage)",
"249:\t\treturn nil, errors.New(errors.CodeForbidden, batchBusinessOwnerFailureMessage)"
],
"exit_status": 0
}
},
{
"capability": "business-user-group",
"requirement": "店铺负责人 CSV 导入",
"spec": "openspec/specs/business-user-group/spec.md",
"entries": [
"/api/admin/shops/business-owner-imports",
"/api/admin/shops/business-owner-imports/{id}",
"constants.TaskTypeShopBusinessOwnerImport"
],
"handler_consumer_job": [
"internal/routes/business_user_group.go",
"internal/handler/admin/shop_business_owner_import.go"
],
"application_service_query": [
"internal/task/shop_business_owner_import.go",
"pkg/utils/encoding.go"
],
"domain_state_amount": [
"internal/model/shop_business_owner_import_task.go",
"pkg/constants/shop_business_owner_import.go"
],
"store_migration_config": [
"internal/store/postgres/shop_business_owner_import_task_store.go",
"migrations/000221_add_business_user_group_and_shop_owner_import.up.sql"
],
"verification": {
"command": "grep -nE 'ShopBusinessOwnerImportColumns|ShopBusinessOwnerImportErrorFileFormat|ShopBusinessOwnerImportRowErrorOwnerForbidden|ShopOwnerImportAccessDescription' pkg/constants/shop_business_owner_import.go",
"literal_output": [
"29:// ShopBusinessOwnerImportColumns 表示导入文件首行必须完全一致的固定列序。",
"30:var ShopBusinessOwnerImportColumns = []string{\"店铺编码\", \"操作类型\", \"业务员登录账号\", \"备注\"}",
"34:\t// ShopBusinessOwnerImportErrorFileFormat 表示文件格式或表头与固定列序不符。",
"35:\tShopBusinessOwnerImportErrorFileFormat = \"文件格式或表头与固定列序不符\"",
"50:\t// ShopBusinessOwnerImportRowErrorOwnerForbidden 表示清空却填写了业务员登录账号。",
"51:\tShopBusinessOwnerImportRowErrorOwnerForbidden = \"清空不得填写业务员登录账号\"",
"59:\t// ShopOwnerImportAccessDescription 表示店铺负责人导入入口的角色说明。",
"60:\tShopOwnerImportAccessDescription = \"仅超级管理员和平台账号可访问,代理与企业账号返回 403。\""
],
"exit_status": 0
}
}
]