Files
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

21 lines
24 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"role":"user","message":{"content":[{"type":"text","text":"<user_query>\nSearch the slot monorepo for implementation related to \"首充前免费余额定格与分档释放\" / free credits freeze before first deposit / tiered release. Look in slot_wallet, slot_user, slot_pay, backend, slot-foundation, slot_lib, etc.\n\nFind:\n1. Key files, classes, services (e.g. FreeCredits, FrozenBalance, ReleaseTier, first deposit)\n2. API endpoints mentioned in requirements\n3. Database migrations/models\n4. What's implemented vs stub/TODO\n\nReturn a structured summary with file paths and brief description of each component found. Note any TODO/FIXME or missing pieces.\n</user_query>"}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"Searching the monorepo for free-credits freeze and tiered-release implementation.\n\n[REDACTED]"},{"type":"tool_use","name":"updateCurrentStep","input":{"current_step":"Searching free credits implementation"}},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|FrozenBalance|ReleaseTier|free_credits|freeCredits","path":"/Users/ray/Documents/project/www/slot","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"首充|定格|分档释放|frozen.*balance|tiered.*release","path":"/Users/ray/Documents/project/www/slot","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"first.?deposit|firstDeposit|FirstDeposit","path":"/Users/ray/Documents/project/www/slot","-i":true}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"free.?credits|FreeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot","-i":true,"glob":"*.{php,vue,ts,js,sql,md}"}},{"type":"tool_use","name":"Grep","input":{"pattern":"TODO|FIXME|stub|未实现|待实现","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"*FreeCredits*"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md"}},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/*FreeCredits*","target_directory":"/Users/ray/Documents/project/www/slot"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|free-credits|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"**/route*.php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|free_credits|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"type":"tool_use","name":"Grep","input":{"pattern":"/api/|innerapi/|POST|GET","path":"/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md","head_limit":80}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/logic/FreeCreditsLogic.php"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/controller/FreeCreditsController.php"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_console"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/model/common/FreeCreditsPlayerModel.php"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/model/common/FreeCreditsPackageModel.php"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/db/install.sql","offset":30,"limit":60}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","offset":555,"limit":120}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/route/**","target_directory":"/Users/ray/Documents/project/www/slot/slot_console"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|FreeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_wallet","glob":"**/*"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/innerapi/controller/FreeCreditsController.php"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/model/common/RechargeGiftConfigModel.php","offset":60,"limit":90}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/command/event/RechargeEvent.php","offset":80,"limit":40}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/.cursor/plans/free_credits_release_902566c9.plan.md"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|FreeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/backend"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim|WALLET_TYPE_FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md","offset":700,"limit":250}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/command/EventBus.php","offset":115,"limit":35}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/validator/FreeCreditsValidator.php"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"接口|API|/api/|innerapi","path":"/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md","head_limit":60}},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|free_credits|freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_gateway"}},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/*route*","target_directory":"/Users/ray/Documents/project/www/slot/slot_console"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"type":"tool_use","name":"Grep","input":{"pattern":"TYPE_FREE_CREDITS|free_credit|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_pay"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/config/route.php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_lib/src/services/WalletService.php","offset":1,"limit":200}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_pay/app/entity/WithdrawalOrderEntity.php","offset":55,"limit":90}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credit|FreeCredits|TYPE_FREE_CREDITS|free_credits","path":"/Users/ray/Documents/project/www/slot/slot-foundation"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim|FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api"}},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_pwa"}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credits|FreeCredits|TYPE_FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/backend/slot_admin"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php","offset":60,"limit":30}},{"type":"tool_use","name":"Grep","input":{"pattern":"TODO|FIXME|@todo","path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/logic/FreeCreditsLogic.php"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet","type":"php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"case.*freeCredits|WALLET_TYPE_FREE","path":"/Users/ray/Documents/project/www/slot"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md","offset":1040,"limit":100}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/WalletController.php","target_directory":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"type":"tool_use","name":"Grep","input":{"pattern":"innerapi.*free|FreeCredits","path":"/Users/ray/Documents/project/www/slot"}},{"type":"tool_use","name":"Grep","input":{"pattern":"tests.*[Ff]ree[Cc]redits|FreeCredits","path":"/Users/ray/Documents/project/www/slot"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"function update|freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/controller/WalletController.php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"RechargeEvent|recharge.*Event","path":"/Users/ray/Documents/project/www/slot/slot_pay"}},{"type":"tool_use","name":"Grep","input":{"pattern":"ext_config|win_threshold|recharge_unlock","path":"/Users/ray/Documents/project/www/slot"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/controller/WalletController.php","offset":30,"limit":80}},{"type":"tool_use","name":"Grep","input":{"pattern":"TYPE_FREE_CREDITS|type.*11|free.?credit","path":"/Users/ray/Documents/project/www/slot/backend","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"innerapi/free|FreeCredits","path":"/Users/ray/Documents/project/www/slot/backend"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim|FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_pay/app/entity/WithdrawalOrderEntity.php","offset":115,"limit":50}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_pay/app/entity/WithdrawalOrderEntity.php","offset":230,"limit":30}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"function run|'freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"broadcast|广播|Free Play","path":"/Users/ray/Documents/project/www/slot/slot_console"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","offset":40,"limit":80}},{"type":"tool_use","name":"Grep","input":{"pattern":"y1|Y1|wager.*multiplier|打码倍数","path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/logic/FreeCreditsLogic.php","-i":true}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_gateway"}},{"type":"tool_use","name":"Grep","input":{"pattern":"SOURCE_TYPE_FREE|createTask","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","head_limit":20}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/command/event/RechargeEvent.php","offset":1,"limit":50}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_pay/app/command/EventWithdrawal.php","offset":95,"limit":45}},{"type":"tool_use","name":"Grep","input":{"pattern":"first_recharge_order_id|frozen_amount_qf","path":"/Users/ray/Documents/project/www/slot/slot_console"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"updateCurrentStep","input":{"current_step":"Summarizing search findings","final_summary":"Free Credits is implemented mainly in **slot_console** (domain logic, APIs, DB), with wallet freeze/claim in **slot_wallet**/**slot_lib** and first-cashout wiring in **slot_pay**. **backend**, **slot_user**, **slot-foundation**, **slot_pwa**, and **slot_gateway** have no feature-specific code; admin UI and broadcast APIs from the requirements doc appear missing.","completed_subtitle":"Mapped free credits codebase"}}]}}
{"role":"assistant","message":{"content":[{"type":"text","text":"# Free Credits / 首充前免费余额定格与分档释放 — Codebase Search Summary\n\nImplementation is **concentrated in `slot_console`**, with wallet primitives in **`slot_wallet` / `slot_lib`** and first-tier cashout in **`slot_pay`**. There is **no dedicated code** in `backend`, `slot_user`, `slot-foundation`, `slot_gateway`, or `slot_pwa`. Requirements live in `/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md` (product/UI spec, not REST path list).\n\n---\n\n## 1. Key files, classes, services\n\n### `slot_console` — core domain (primary)\n\n| Path | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_console/app/api/logic/FreeCreditsLogic.php` | **Main orchestrator**: status, home-withdraw unlock, first-recharge freeze, tier unlock on recharge, claim, first cashout, callback handling |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/api/controller/FreeCreditsController.php` | Client API: `status`, `claim`, `firstCashout` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/api/validator/FreeCreditsValidator.php` | Validates `package_id`, cashout fields |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/model/common/FreeCreditsPlayerModel.php` | Player pool / state machine constants (`STATUS_*`, `HOME_WITHDRAW_*`) |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/model/common/FreeCreditsPackageModel.php` | Tier rows (`TYPE_FIRST_CASH`, `TYPE_RELEASE`; `STATUS_LOCKED`…`REJECTED`) |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/model/common/RechargeGiftConfigModel.php` | `TYPE_FREE_CREDITS = 11`; `getFreeCreditsActiveInfo()` reads active config from `s_recharge_gift_config` + `ext_config` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/innerapi/controller/FreeCreditsController.php` | Admin stats: `statistics`, `list` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php` | Embeds `free_credits` in lobby/config payload |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/command/event/RechargeEvent.php` | On recharge success → `FreeCreditsLogic::handleRecharge()` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/command/EventBus.php` | `win`/`reward`/… → `syncHomeWithdrawUnlocked()`; cashout MQ events → `handleFirstCashoutResult()` |\n| `/Users/ray/Documents/project/www/slot/slot_console/db/install.sql` | DDL for `s_common.free_credits_player` + `free_credits_package` |\n\n**Config keys** (in `RechargeGiftConfigModel.ext_config`, read by `FreeCreditsLogic`): `win_threshold`, `recharge_unlock_amount`, `first_cash_amount`, `package_amount`, `subsequent_min_recharge`, `max_unlock_per_recharge` (and optional `*_qf` variants).\n\n**Not present as named types**: `FrozenBalance`, `ReleaseTier` — behavior is modeled as `FreeCreditsPlayerModel` + `FreeCreditsPackageModel`.\n\n---\n\n### `slot_lib` — wallet client SDK\n\n| Path | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_lib/src/services/WalletService.php` | `WALLET_TYPE_FREE_CREDITS_FREEZE` / `CLAIM`; `freeCreditsFreeze()`, `freeCreditsClaim()` → `POST api/wallet/update` |\n\n---\n\n### `slot_wallet` — wallet atomic ops\n\n| Path | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php` | `freeCreditsFreeze()` (deduct gift balance + log); `freeCreditsClaim()` (credit deposit + `createTask(..., SOURCE_TYPE_FREE)` + console bus) |\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/api/controller/WalletController.php` | `update()` dispatches by `type` string → method name |\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/model/multi/WalletLogModel.php` | `BIZ_TYPE_FREE_CREDITS_FREEZE` / `CLAIM` |\n\n---\n\n### `slot_pay` — first-tier withdrawal\n\n| Path | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_pay/app/entity/WithdrawalOrderEntity.php` | `BIZ_TYPE_FREE_CREDITS_FIRST_CASHOUT = 'free_credit_first_cashout'`; skips `withdrawFrozen` on apply; rejection → console bus |\n| `/Users/ray/Documents/project/www/slot/slot_pay/app/command/EventWithdrawal.php` | Success/fail/reject → `FreeCreditsFirstCashoutSuccess/Fail` MQ to console |\n\n---\n\n### Other repos — no Free Credits feature code\n\n| Repo | Finding |\n|------|---------|\n| `backend` | No `FreeCredits` / `free_credits` |\n| `slot_user`, `slot-foundation`, `slot_gateway`, `slot_sdk`, `slot_pwa` | None |\n| `slot_agent` | “首充” = referral fission, unrelated |\n\n---\n\n## 2. API endpoints (inferred — Webman convention routing)\n\nRequirements doc describes **screens/flows**, not literal REST paths. Implemented controllers map to typical paths:\n\n### Client (`slot_console` → `app/api/controller/FreeCreditsController.php`)\n\n| Inferred path | Method | Handler | Purpose |\n|---------------|--------|---------|---------|\n| `/api/freeCredits/status` | GET/POST | `status` | Activity + player + packages |\n| `/api/freeCredits/claim` | POST | `claim` | Claim next release tier (`package_id`) |\n| `/api/freeCredits/firstCashout` | POST | `firstCashout` | Submit tier-1 no-wager withdrawal |\n\n### NAPI lobby\n\n| Inferred path | Field | Purpose |\n|---------------|-------|---------|\n| `/napi/.../LobbyController` config | `free_credits` | Same as `status()` when user logged in |\n\n### Admin inner API (`app/innerapi/controller/FreeCreditsController.php`)\n\n| Inferred path | Handler | Purpose |\n|---------------|---------|---------|\n| `/innerapi/freeCredits/statistics` | `statistics` | Aggregate frozen/first cashout/claimed/pending |\n| `/innerapi/freeCredits/list` | `list` | Paginated players + packages |\n\n### Wallet internal (`slot_lib` → `slot_wallet`)\n\n| Path | Body `type` | Purpose |\n|------|-------------|---------|\n| `POST api/wallet/update` | `freeCreditsFreeze` | Deduct free balance at freeze |\n| `POST api/wallet/update` | `freeCreditsClaim` | Credit deposit + wager task |\n\n### Events (not HTTP)\n\n- Recharge: `RechargeEvent` → `handleRecharge(uid, wallet_amount, orderId, isFirstRecharge)`\n- Cashout: `FreeCreditsFirstCashoutSuccess|Fail|Rejected` on console `EventBus`\n- Home unlock: `win` / `reward` / … on `EventBus` → `syncHomeWithdrawUnlocked`\n\n---\n\n## 3. Database / models\n\n| Table | Model | Migration |\n|-------|-------|-----------|\n| `s_common.free_credits_player` | `FreeCreditsPlayerModel` | `/Users/ray/Documents/project/www/slot/slot_console/db/install.sql` |\n| `s_common.free_credits_package` | `FreeCreditsPackageModel` | same file |\n| Config (existing) | `RechargeGiftConfigModel` (`type=11`, `ext_config` JSON) | pre-existing recharge-gift table |\n\n**Activity link**: `activity_id` → `s_recharge_gift_config.id` (not `recharge_gift_player`).\n\n---\n\n## 4. Implemented vs missing / gaps\n\n### Implemented (substantial backend core)\n\n| Area | Status |\n|------|--------|\n| Schema + models | Done |\n| Active config via `TYPE_FREE_CREDITS` + `ext_config` | Done |\n| Home withdraw unlock when balance ≥ `win_threshold` | Done (via wallet `win` bus + `syncHomeWithdrawUnlocked`) |\n| First real recharge freeze (`balance - wallet_amount`) + wallet freeze | Done |\n| Tier split (first cash + release packages) | Done |\n| Unlock first tier when cumulative recharge ≥ threshold (`wallet.r`) | Done |\n| Unlock release tiers per recharge (`subsequent_min_recharge`, `max_unlock_per_recharge`) | Done |\n| Ordered claim + wallet credit + idempotent `claim_biz_id` | Done |\n| First-tier cashout via `slot_pay` + status sync | Done |\n| Lobby `free_credits` embed | Done |\n| InnerAPI statistics + list | Done |\n| No `TODO`/`FIXME` in Free Credits PHP files | — |\n\n### Partial / gaps vs requirements doc\n\n| Gap | Notes |\n|-----|--------|\n| **`STATUS_FROZEN` (2)** | Defined on player model + DDL comment but **never set** in logic (jumps to `DEPOSIT_PENDING` / `FIRST_CASH_READY`) |\n| **Freeze idempotency by order** | Guards on `frozen_amount_qf <= 0`, not `first_recharge_order_id` match |\n| **Y1 wager multiplier** | Doc §17 `后续档打码倍数`; claim uses fixed `WagerTaskModel::SOURCE_TYPE_FREE` in wallet, **no config-driven multiplier** |\n| **Admin config UI** | `backend/slot_admin*` has generic `ext_config` activity editor, **no type-11 / Free Creditsspecific fields** |\n| **Admin stats UI** | InnerAPI exists; **no Vue/admin pages** calling it found |\n| **Broadcast feed** (doc §13) | **Not implemented** |\n| **Dedicated activity/popup APIs** | Only `status` + lobby embed; no separate “Free Play to Go” endpoint |\n| **`累计充值金额` in admin list** | Not stored on player; would need live wallet stat or join |\n| **Tests** | No `FreeCredits` tests found in monorepo |\n| **Client UI** | `slot_pwa` has zero references (expected per plan: frontend elsewhere) |\n| **Plan todo** | `.cursor/plans/free_credits_release_902566c9.plan.md` still marks `implement-console-core` as **pending** though code exists |\n\n### Repos with zero involvement\n\n`slot_user`, `slot-foundation`, `slot_gateway`, `backend` (for this feature), `slot_notification`, `slot_center`, `slot_hub`, `slot_risk`.\n\n---\n\n## 5. State machine (as coded)\n\n**Player** (`FreeCreditsPlayerModel`): \n`0 NOT_STARTED` → `1 HOME_UNLOCKED` → after freeze: `3 DEPOSIT_PENDING` or `4 FIRST_CASH_READY` → `5 FIRST_CASH_PROCESSING` → `6 FIRST_CASH_DONE` → `7 RELEASING` → `10 COMPLETED`\n\n**Package**: `LOCKED` → `READY` → `PROCESSING` → `COMPLETED` (or `REJECTED` on tier-1 audit reject)\n\n**First deposit trigger**: `RechargeEvent` + `isFirstRecharge`; freeze amount = pre-recharge free balance; config type **11** on `s_recharge_gift_config`.\n\n---\n\n## 6. Quick architecture diagram\n\n```mermaid\nflowchart LR\n RechargeMQ[RechargeEvent MQ] --> FCLogic[FreeCreditsLogic]\n WinMQ[win/reward EventBus] --> FCLogic\n FCLogic --> WalletSDK[slot_lib WalletService]\n WalletSDK --> WalletAPI[slot_wallet freeCreditsFreeze/Claim]\n FCLogic --> DB[(free_credits_player/package)]\n FCLogic --> Pay[slot_pay first cashout]\n Pay --> CashoutMQ[FreeCreditsFirstCashout* events]\n CashoutMQ --> FCLogic\n ClientAPI[api/FreeCreditsController] --> FCLogic\n Lobby[napi LobbyController] --> FCLogic\n Admin[innerapi FreeCreditsController] --> DB\n```\n\n---\n\n**Bottom line**: Backend **domain logic for freeze, tiered release, claim, and first cashout is largely in place** in `slot_console` + wallet/pay integration. **Missing** pieces are mainly **admin UI**, **broadcast**, **configurable Y1 wagering**, stricter freeze state/idempotency, and **client/frontend** (out of these repos). No `TODO`/`FIXME` markers in the Free Credits PHP files themselves.\n\n[REDACTED]"}]}}