{"role":"user","message":{"content":[{"type":"text","text":"\nSearch the slot monorepo for implementation related to \"首充前免费余额定格与分档释放\" / free credits freeze / tiered release before first deposit. Look in backend, slot_wallet, slot_user, slot_pay, slot_gateway, slot_sdk, etc.\n\nFind:\n1. Key files, classes, services implementing this feature\n2. Database migrations or models (frozen balance, release tiers, etc.)\n3. API endpoints\n4. Any TODO/FIXME or incomplete stubs\n\nReturn a structured summary with file paths and what each implements. Search for keywords: free_credits, frozen, freeze, release_tier, first_deposit, 首充, 定格, 分档释放, FreeCredits, etc.\n\nWorkspace roots include:\n- /Users/ray/Documents/project/www/slot/backend\n- /Users/ray/Documents/project/www/slot/slot_wallet\n- /Users/ray/Documents/project/www/slot/slot_user\n- /Users/ray/Documents/project/www/slot/slot_pay\n- /Users/ray/Documents/project/www/slot/docs\n\nBe thorough - check requirements doc references if found in code comments.\n"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"Searching the monorepo for free-credits freeze and tiered-release implementation across backend services.\n\n[REDACTED]"},{"type":"tool_use","name":"updateCurrentStep","input":{"current_step":"Searching free credits freeze"}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credits|FreeCredits|freeCredits","path":"/Users/ray/Documents/project/www/slot","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"release_tier|releaseTier|ReleaseTier","path":"/Users/ray/Documents/project/www/slot","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"frozen|freeze|定格","path":"/Users/ray/Documents/project/www/slot","glob":"*.{php,go,ts,js,vue,sql,md}","-i":true,"head_limit":150}},{"type":"tool_use","name":"Grep","input":{"pattern":"first_deposit|firstDeposit|首充|分档释放","path":"/Users/ray/Documents/project/www/slot","-i":true,"head_limit":150}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"FreeCredits|free_credits|freeCredits","path":"/Users/ray/Documents/project/www/slot","output_mode":"files_with_matches"}},{"type":"tool_use","name":"Grep","input":{"pattern":"TODO|FIXME|XXX|stub|未实现|待实现","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"*FreeCredits*"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim|FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot"}},{"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","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"**/route*"}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"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/db/install.sql","offset":30,"limit":80}},{"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":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/api/controller/FreeCreditsController.php"}},{"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/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":"Grep","input":{"pattern":"FreeCredits|freeCredits|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"**/*.{php,json,yml,yaml}"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/route*.php","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/backend"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","offset":555,"limit":120}},{"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/Documents/project/www/slot/slot_console/app/model/common/RechargeGiftConfigModel.php","offset":60,"limit":90}}]}} {"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","glob":"**/*"}},{"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_pay/app/entity/WithdrawalOrderEntity.php","offset":55,"limit":90}},{"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":"freeCreditsFreeze|freeCreditsClaim|free_credits","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"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_console/app/napi/controller/LobbyController.php","offset":60,"limit":35}},{"type":"tool_use","name":"Grep","input":{"pattern":"TYPE_FREE_CREDITS|free_credits|FreeCredits","path":"/Users/ray/Documents/project/www/slot","glob":"**/*.{vue,ts,js,php}"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCreditsFreeze|freeCreditsClaim|WALLET_TYPE_FREE","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":"freeCredits|FreeCredits|TYPE_FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"**/config/**"}},{"type":"tool_use","name":"Grep","input":{"pattern":"TODO|FIXME|待实现|未实现|stub","path":"/Users/ray/Documents/project/www/slot/slot_console/app","glob":"**/*FreeCredits*"}}]}} {"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","limit":120}},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits|case.*type","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/controller"}},{"type":"tool_use","name":"Glob","input":{"glob_pattern":"**/middleware/**/*.php","target_directory":"/Users/ray/Documents/project/www/slot/slot_console"}},{"type":"tool_use","name":"Grep","input":{"pattern":"innerapi|napi|api/","path":"/Users/ray/Documents/project/www/slot/slot_console/config"}}]}} {"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":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_pay/app/command/EventWithdrawal.php","offset":105,"limit":35}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credits|freeCredits|FreeCredits|TYPE_FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/docs"}},{"type":"tool_use","name":"Grep","input":{"pattern":"test.*[Ff]ree[Cc]redits|FreeCredits","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/logic/WalletLogic.php","offset":35,"limit":80}},{"type":"tool_use","name":"Grep","input":{"pattern":"LobbyController|free-credits|FreeCredits","path":"/Users/ray/Documents/project/www/slot/slot_console","glob":"**/*"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/config/middleware.php"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php","limit":30}},{"type":"tool_use","name":"Grep","input":{"pattern":"class Lobby|function ","path":"/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php"}},{"type":"tool_use","name":"Grep","input":{"pattern":"ext_config|win_threshold|recharge_unlock","path":"/Users/ray/Documents/project/www/slot"}},{"type":"tool_use","name":"Grep","input":{"pattern":"STATUS_FROZEN|STATUS_FROZEN","path":"/Users/ray/Documents/project/www/slot/slot_console"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credits","path":"/Users/ray/Documents/project/www/slot","glob":"**/*.sql"}},{"type":"tool_use","name":"Grep","input":{"pattern":"SOURCE_TYPE_FREE","path":"/Users/ray/Documents/project/www/slot/slot_wallet"}},{"type":"tool_use","name":"Grep","input":{"pattern":"TYPE_FREE_CREDITS|type.*11","path":"/Users/ray/Documents/project/www/slot/backend"}},{"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":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/command/event/RechargeEvent.php","limit":95}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credit|FreeCredits|freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_gateway"}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credit|FreeCredits|freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_pwa"}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credit|FreeCredits|TYPE_FREE_CREDITS","path":"/Users/ray/Documents/project/www/slot/backend/slot_admin"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"FREE_CREDITS|free.?credits|type.*11","path":"/Users/ray/Documents/project/www/slot/slot_console/app/entity","-i":true}},{"type":"tool_use","name":"Grep","input":{"pattern":"free_credit_first_cashout","path":"/Users/ray/Documents/project/www/slot"}},{"type":"tool_use","name":"Read","input":{"path":"/Users/ray/Documents/project/www/slot/slot_console/app/model/common/RechargeGiftConfigModel.php","offset":125,"limit":35}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"[REDACTED]"},{"type":"tool_use","name":"Grep","input":{"pattern":"freeCredits","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/validator"}},{"type":"tool_use","name":"Grep","input":{"pattern":"biz_id|bizId","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","head_limit":30}},{"type":"tool_use","name":"Grep","input":{"pattern":"addLog","path":"/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php","head_limit":5}}]}} {"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":830,"limit":50}},{"type":"tool_use","name":"updateCurrentStep","input":{"current_step":"Compiling implementation summary","final_summary":"The feature lives mainly in **slot_console** (domain logic, DB, APIs) with wallet freeze/claim in **slot_wallet**, SDK client in **slot_lib**, and first-cashout wiring in **slot_pay**. **backend**, **slot_user**, **slot_gateway**, and **slot_sdk** have no Free Credits code; requirements are only in docs. No dedicated tests or admin UI for type 11 were found; the dev plan still marks console core as pending despite substantial implementation.","completed_subtitle":"Mapped free credits implementation"}}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"## Summary: 首充前免费余额定格与分档释放 (Free Credits)\n\nImplementation is **concentrated in `slot_console`** (domain + APIs + DB). Supporting pieces are in **`slot_wallet`** (balance freeze/claim), **`slot_lib`** (wallet HTTP client), and **`slot_pay`** (first-tier cashout order type + MQ callbacks).\n\n**No matches** in: `backend/`, `slot_user/`, `slot_gateway/`, `slot_sdk/`, `slot_pwa/`, `slot_agent/`, `slot_center/`, `slot_hub/`, `slot_risk/`, `slot_notification/`.\n\nRequirements doc only: `/Users/ray/Documents/project/www/slot/docs/requirements/首充前免费余额定格与分档释放需求文档.md`\n\nDev plan: `/Users/ray/.cursor/plans/free_credits_release_902566c9.plan.md` (notes `implement-console-core` still **pending** despite substantial code existing)\n\n---\n\n## 1. Key files / classes / services\n\n### slot_console — core domain (orchestration)\n\n| File | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_console/app/api/logic/FreeCreditsLogic.php` | **Main business logic**: activity status, home-withdraw unlock (`syncHomeWithdrawUnlocked`), first-recharge freeze (`freezeFirstRecharge`), tier package creation, recharge-driven unlock (`advanceByRecharge`), release claim, first-cashout submit + result 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 `type` |\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 helpers |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/model/common/RechargeGiftConfigModel.php` | `TYPE_FREE_CREDITS = 11`; `getFreeCreditsActiveInfo()` loads active config from `s_recharge_gift_config` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php` | Embeds `free_credits` in lobby `frontData` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/innerapi/controller/FreeCreditsController.php` | Admin/inner stats: `statistics`, `list` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/command/event/RechargeEvent.php` | On recharge MQ: calls `FreeCreditsLogic::handleRecharge()` |\n| `/Users/ray/Documents/project/www/slot/slot_console/app/command/EventBus.php` | On `win`/`bonusToDeposit`/etc.: `syncHomeWithdrawUnlocked`; handles `FreeCreditsFirstCashout{Success,Fail,Rejected}` |\n\n**Config keys** (in `ext_config` JSON on `s_recharge_gift_config`): `win_threshold`, `recharge_unlock_amount`, `first_cash_amount`, `package_amount`, `subsequent_min_recharge`, `max_unlock_per_recharge` (with `_qf` variants supported).\n\n**Defaults** in logic: win $50, unlock $50, first cash $20, package $10, min subsequent recharge $10, max 1 unlock per recharge.\n\n### slot_wallet — atomic wallet ops\n\n| File | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/api/logic/WalletLogic.php` | `freeCreditsFreeze()` — deduct `deposit_balance` + `withdraw_balance`; `freeCreditsClaim()` — credit deposit, create Y1 wager task (`SOURCE_TYPE_FREE = 11`) |\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/api/controller/WalletController.php` | `POST api/wallet/update` dispatches by `type` field |\n| `/Users/ray/Documents/project/www/slot/slot_wallet/app/model/multi/WalletLogModel.php` | `BIZ_TYPE_FREE_CREDITS_FREEZE` / `BIZ_TYPE_FREE_CREDITS_CLAIM` |\n\n### slot_lib — wallet SDK\n\n| File | Role |\n|------|------|\n| `/Users/ray/Documents/project/www/slot/slot_lib/src/services/WalletService.php` | `freeCreditsFreeze()`, `freeCreditsClaim()` → `POST api/wallet/update` with types `freeCreditsFreeze` / `freeCreditsClaim` |\n\n### slot_pay — first-tier cashout\n\n| File | 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** normal `withdrawFrozen` on apply |\n| `/Users/ray/Documents/project/www/slot/slot_pay/app/command/EventWithdrawal.php` | Success/fail → MQ `FreeCreditsFirstCashoutSuccess` / `FreeCreditsFirstCashoutFail` |\n| Same entity (audit reject) | MQ `FreeCreditsFirstCashoutRejected` |\n\n---\n\n## 2. Database / models\n\n**DDL** (only in install SQL, no separate migration file found):\n\n`/Users/ray/Documents/project/www/slot/slot_console/db/install.sql` (lines 36–86)\n\n| Table | Purpose |\n|-------|---------|\n| `s_common.free_credits_player` | Per-user pool: `frozen_amount_qf`, `first_cash_amount_qf`, `first_recharge_order_id`, status, home unlock flag |\n| `s_common.free_credits_package` | Tiers: `package_type` (1=first cashout, 2=release), `amount_qf`, status, `withdraw_order_id`, `claim_biz_id` |\n\n**Related config table** (existing): `s_common.s_recharge_gift_config` with `type = 11` (`TYPE_FREE_CREDITS`).\n\n**Not implemented**: separate “Free Credits Pool” wallet table; pool is logical (player + package rows + deducted wallet balance).\n\n---\n\n## 3. API endpoints\n\nWebman uses **convention routing** (`config/route.php` only defines `/metrics`). Typical paths:\n\n### Client (`api` + `AuthMiddleware`)\n\n| Method / path (conventional) | Controller action | Purpose |\n|------------------------------|-------------------|---------|\n| `/api/free-credits/status` | `FreeCreditsController::status` | Full activity state + packages |\n| `/api/free-credits/claim` | `FreeCreditsController::claim` | Claim next release tier → wallet |\n| `/api/free-credits/first-cashout` | `FreeCreditsController::firstCashout` | Submit tier-1 no-wager withdrawal |\n\n### Lobby (`napi` + `NAuthMiddleware`)\n\n| Path (conventional) | Action | Purpose |\n|---------------------|--------|---------|\n| `/napi/lobby/front-data` | `LobbyController::frontData` | Returns `free_credits` alongside lobby config |\n\n### Inner admin (`innerapi` + `InnerAuthMiddleware`)\n\n| Path (conventional) | Action | Purpose |\n|---------------------|--------|---------|\n| `/innerapi/free-credits/statistics` | `statistics` | Aggregates: frozen users/amount, cashout, claimed, pending |\n| `/innerapi/free-credits/list` | `list` | Paginated player list + packages |\n\n### Wallet service (called by slot_console via slot_lib)\n\n| Path | `type` param | 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---\n\n## 4. Event / integration flow\n\n```mermaid\nflowchart LR\n recharge[Recharge MQ] --> RechargeEvent\n RechargeEvent --> FCLogic[FreeCreditsLogic.handleRecharge]\n FCLogic --> freeze[freeCreditsFreeze via slot_lib]\n FCLogic --> packages[free_credits_player/package]\n\n win[win/bonus/etc MQ] --> EventBus\n EventBus --> unlockHome[syncHomeWithdrawUnlocked]\n\n claim[API claim] --> FCLogic2[FreeCreditsLogic.claim]\n FCLogic2 --> walletClaim[freeCreditsClaim]\n\n cashout[API firstCashout] --> PayService\n PayService --> slot_pay[slot_pay withdrawal]\n slot_pay --> bus[FreeCreditsFirstCashout* MQ]\n bus --> EventBus\n```\n\n- **Freeze trigger**: first recharge (`recharge_count <= 0` before increment in `RechargeEvent`); `frozenAmount = balance_after_recharge - wallet_amount` (pre-recharge free balance).\n- **Idempotency (partial)**: skip freeze if `frozen_amount_qf > 0`; claim uses unique `claim_biz_id` on package table.\n- **Home withdraw unlock**: wallet events `win`, `bonusToDeposit`, `withdrawFrozen`, `reward`, `switchBonus`, `addBonus` → `syncHomeWithdrawUnlocked` when balance ≥ `win_threshold`.\n\n---\n\n## 5. TODO / FIXME / gaps (no literal TODOs in FreeCredits files)\n\n| Gap | Detail |\n|-----|--------|\n| **No TODO/FIXME** in `*FreeCredits*` files | Clean of explicit stubs |\n| **Plan vs code** | Plan item `implement-console-core` still **pending**; code is largely present |\n| **`STATUS_FROZEN = 2`** | Defined on `FreeCreditsPlayerModel` but **never set** in `FreeCreditsLogic` (jumps to `DEPOSIT_PENDING` / `FIRST_CASH_READY`) |\n| **Admin UI** | No `TYPE_FREE_CREDITS` / Free Credits UI in `backend/slot_admin*`; config likely manual DB/`ext_config` |\n| **Tests** | No unit/integration tests referencing FreeCredits |\n| **Frontend** | No PWA/Vue references; plan says client UI is out of repo |\n| **Deposit Lot** | Plan mentions Deposit Lot; claim only does deposit increment + `createTask(SOURCE_TYPE_FREE)` |\n| **Dedicated pool account** | No separate wallet shard for “Free Credits Pool”; balance removed from gift wallet |\n| **Wallet biz_id dedup** | `addLog` stores `biz_id` but freeze/claim paths don’t show explicit duplicate-biz guard in wallet layer |\n| **Y1 multiplier config** | Doc mentions configurable Y1; code uses fixed `createTask(0, fee, SOURCE_TYPE_FREE)` |\n\n---\n\n## 6. Repos searched — result matrix\n\n| Repo | Free Credits implementation |\n|------|------------------------------|\n| **slot_console** | Full backend feature |\n| **slot_wallet** | Freeze + claim wallet ops |\n| **slot_lib** | Wallet client methods |\n| **slot_pay** | First cashout order + callbacks |\n| **docs** | Requirements only |\n| **backend** | None |\n| **slot_user** | None |\n| **slot_gateway** | None |\n| **slot_sdk** | None (only unrelated “first deposit” referral entities) |\n\n---\n\n## 7. State machine reference (implemented)\n\n**Player** (`FreeCreditsPlayerModel`): `0` not started → `1` home unlocked → `3` deposit pending / `4` first cash ready → `5` processing → `6` done → `7` releasing → `10` completed.\n\n**Package** (`FreeCreditsPackageModel`): `0` locked → `1` ready → `2` processing → `3` completed (also `4` failed, `5` rejected).\n\nIf you want next steps, the highest-value follow-ups are: admin config UI for `type=11`, aligning `STATUS_FROZEN` with the spec, automated tests for freeze idempotency and ordered claim, and confirming Webman route prefixes in your deployment config.\n\n[REDACTED]"}]}}