[ { "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. 每个请求必须携带 Header:X-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(¬ification)" ], "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.Approve(BodyParser 后直接传 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.Approve(BodyParser 后直接传 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.Approve(BodyParser 后直接传 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 } } ]