2867 lines
156 KiB
JSON
2867 lines
156 KiB
JSON
[
|
||
{
|
||
"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"
|
||
],
|
||
"handler_consumer_job": [
|
||
"internal/handler/admin/agent_recharge.go:AgentRechargeHandler.PaymentMethods"
|
||
],
|
||
"application_service_query": [
|
||
"internal/application/agentrecharge/online_creation.go:OnlineCreationService.AvailablePaymentMethods"
|
||
],
|
||
"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/handler/admin/agent_recharge.go'\"'\"', '\"'\"'AvailablePaymentMethods'\"'\"'), ('\"'\"'internal/application/agentrecharge/online_creation.go'\"'\"', '\"'\"'adapter.Available(config)'\"'\"'), ('\"'\"'internal/model/agent_wallet.go'\"'\"', '\"'\"'PaymentChannel'\"'\"')]; 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
|
||
}
|
||
}
|
||
]
|