RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/k1tbyte-wand-enhancer-agents ↔ k1tbyte-wand-enhancer-web-panel-claude

Comparison

A · AGENTS.md · k1tbyte/Wand-EnhancerB · CLAUDE.md · k1tbyte/Wand-Enhancer
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections04140%
Commands0300%
Section tags34427%

What each file covers

Sections

0 shared · 4 only in A · 14 only in B
  • − Wand Enhancer Agent Notes
  • − Remote Web Panel
  • − ASAR Patch Pipeline
  • − Validation
  • + Core Principles
  • + Screaming Architecture
  • + Suggested Structure
  • + Dependency Direction
  • + Make Composition Read Like The Product
  • + UI Boundary
  • + State Ownership
  • + Effects And Async Work
  • + Data And Infrastructure
  • + Component And Hook APIs
  • + Public Boundaries
  • + Growing The Architecture
  • + Testing
  • + Review Checklist

Commands

0 shared · 3 only in A · 0 only in B
  • − pnpm run build:bridge
  • − node --check web-panel/dist/bridge.cjs
  • − node --check web-panel/dist/renderer-scripts/remote-popup-cleanup.js

Section tags

3 shared · 4 only in A · 4 only in B
  • − build
  • − security
  • − deployment
  • − agent-behaviour
  • + test
  • + architecture
  • + git-pr
  • + ui
  •   code-style
  •   testing-strategy
  •   do-not

Line diff

+246 added−39 removed9 unchanged3.5% identical
k1tbyte/Wand-Enhancer · AGENTS.md
@@ −1 @@
1INFO ./docs/*
2 
3# Wand Enhancer Agent Notes
4 
5This repository patches the Wand Electron app from a .NET Framework WPF desktop tool. Keep changes narrow and preserve the patch pipeline invariants.
 
 
 
 
 
 
 
6 
7## Remote Web Panel
8 
9- The default local remote port is `3223`. Keep bridge and frontend constants aligned; C# must not duplicate the presentation URL or port.
10- The embedded panel must stay small because the desktop patcher embeds it and then injects it into Wand's `app.asar`.
11- Remote tooltip links and every rendered `remote-qr-code` are redirected by `web-panel/bridge/scripts/default/remote-popup-cleanup.js`. It reuses Wand's loaded QR renderer through the webpack runtime, keeps the local URL visible as a fallback, and hides the Pro onboarding remote mobile app card. Do not reintroduce C# ASAR patches for the tooltip URL or QR component; a changed UI bundle must not make the whole remote-panel patch fail.
12- Production builds must not include mock data, debug routes, sourcemaps, local fonts, heavy icon libraries, or runtime class helper packages.
13- The Electron bridge is authored as TypeScript under `web-panel/bridge/src/`, but production runtime must be bundled/minified into `web-panel/dist/bridge.cjs` by `pnpm run build:bridge`. Do not copy bridge source into Wand or embed it as ASAR resources.
14- Mock/demo data is dev-only and must be reached through `import.meta.env.DEV` dynamic imports.
15- Source can use React-compatible imports, but production runtime resolves them to Preact aliases in `web-panel/vite.config.ts`.
16- UI uses Tailwind CSS and lightweight local primitives under `web-panel/src/shared/ui/`.
17- Default renderer script sources live in `web-panel/bridge/scripts/default/` and are bundled/minified into `web-panel/dist/renderer-scripts/` by `pnpm run build:bridge`. Custom user scripts are selected in the WPF patch modal and copied from `PatchConfig.CustomScriptPaths`; only existing `.js` files are accepted. A local `renderer-scripts/` folder next to the patcher exe is still copied as an advanced fallback.
18- `web-panel/bridge/scripts/default/installed-apps-sync.js` resolves Wand's renderer services/store and publishes `My Games` snapshots through the `wand-remote-installed-apps` IPC channel. The synced list must mirror Wand's `my_games` source criteria: catalog games come from `installedGameVersions`, and extra installed unsupported titles come from `correlatedUnavailableTitles` whose `games[].correlationIds` match `installedApps`.
19- If the injected renderer cannot read a populated `correlatedUnavailableTitles` slice from the live store, `installed-apps-sync.js` must fall back to Wand's `/v3/unavailable_titles` correlation lookup through the renderer API client instead of degrading to raw install entries or an empty `My Games` list.
20- Installed app snapshots should include game artwork in `imageUrl` when possible. `installed-apps-sync.js` must prefer Wand's own client icon CDN shape `https://api-cdn.wemod.com/steam_community/<steamAppId>/client_icon/96.webp` whenever the matched title/game/version metadata contains a Steam AppID, regardless of install platform. Do not assume `steamAppId` is a flat property; search nested `steam*` metadata before falling back to installed Steam `sku`. If metadata still does not expose the icon, fall back to the rendered Wand sidebar DOM (`.sidebar-game-row-image` background-image) keyed by `titleId` parsed from `data-tooltip-trigger-for`. The web panel `GameCover` must tolerate broken artwork URLs and fall back to its text cover.
21- The same renderer sync script also forwards lifecycle state through `wand-remote-game-status`: `game-launched` / `game-ended` come from Wand's launch monitor service, and trainer runtime comes from the running-trainer visibility service. The web panel consumes this as the `game_status` websocket message.
22- When Wand does not emit a `game-launched` event but a trainer is already active, `wand-remote-game-status` must synthesize a running session from the running-trainer visibility payload so the remote panel does not show an idle game session next to a running trainer.
23- The websocket `hello` snapshot must still send cached `installed_apps` and `game_status` even when no trainer snapshot is active yet; do not reintroduce a handshake path that returns early after `trainer_changed`.
24- Remote Play/Stop uses the websocket `remote_command` message. The bridge forwards it over `wand-remote-command` / `wand-remote-command-response`, and `installed-apps-sync.js` resolves Wand's trainer API + trainer service to launch a trainer for a `gameId` or end the current trainer.
25- Remote Play must construct Wand's real trainer launch request class (`69482.vO`) before calling `trainerService.launch(...)`. Passing a plain object launches the game process but breaks Wand's `getMetadata(vO)`-based trainer state, causing missing status, disappearing play/close buttons, and stuck loading behavior.
26- Pro activation is a C# asar patch (`EPatchType.ActivatePro`, independent of the remote panel / bridge). It rewrites three account-returning service methods to inject `subscription:{period:"yearly",state:"active"}` into the response before it reaches the store: `getUserAccount` and `setAccountWandBrandExperience` (Resolver-style, service field via `<service_name>` placeholder) and `setAccountLanguage` (`BuildSetAccountLanguagePatch` PatchFactory — captures the real param names + the original `post("/v3/account/language",{...})` expr and wraps `.then`). A fourth patch (`setAccountReducer`) rewrites the `ACTION_SET_ACCOUNT` store reducer so any account write (periodic `refreshAccount`, push/profile updates, etc.) keeps Pro even when it bypasses those API methods. Pro is `am(account) = !!account.subscription` (flags/512 are irrelevant). `setAccountLanguage` is the one the original two patches missed, which is why Pro dropped on language change. If a future Wand build changes these method bodies, re-derive the regexes against the live `app-*.bundle.js` (do NOT trust `.source/new` — it is a different version).
27 
28## ASAR Patch Pipeline
29 
30- Preserve and restore both `resources/app.asar` and `resources/app.asar.unpacked` backups.
31- Inject `web-panel/dist` as `remote-panel/`; it must already contain `bridge.cjs` and generated default renderer scripts under `renderer-scripts/`. Selected/local custom renderer scripts are then copied under `remote-panel/renderer-scripts`.
32- Do not commit extracted `.source/` or `.sources/` output. Recreate it only for reverse-engineering sessions.
33- `AsarSharp.AsarExtractor.ExtractAll` must skip unpacked entries when their source path equals the destination (in-place extraction is a self-copy that fails on locked files like `TrainerLib_x64.dll`) and silently skip unpacked entries whose source is missing on disk (e.g. `auxiliary/GameLauncher.exe` removed by an installer). Do not reintroduce hard failure on either case.
34- The `DevToolsOnF12` patch anchors on the Electron main-process `<app>.whenReady().then(` site and attaches a `before-input-event` hook to every `BrowserWindow.webContents`. Do not patch the renderer keydown listener — the minified `ACTION_OPEN_DEV_TOOLS` dispatch site is not stable across Wand releases.
35- Cheats can be pinned per game in the web panel via `pinned-storage.ts` (`localStorage` key `wand-remote.pinned-cheats.v1:<gameId>`). Pinned cheats render as a virtual `pinned` category at the top of the list; their normal category placement is preserved.
36- Custom quick presets are per trainer/game and stored by `preset-storage.ts` under `localStorage` key `wand-remote.presets.v1:<gameId-or-trainerId>`. Presets capture persistent cheat values only; do not include `button` one-shot cheats in saved presets.
37- All `localStorage` access in `web-panel/src/` MUST go through `web-panel/src/shared/storage.ts` (`loadJson` / `saveJson` / `loadStringSet` / `saveStringSet`). Do not reintroduce per-capability `try/catch` + `JSON.parse` duplication. Trainer/game storage IDs are derived through the shared `getTrainerStorageId(trainer)` helper; do not re-implement the `gameId → titleId → trainerId → 'global'` precedence inline.
38- Shared web protocol version, port, and HTTP/WS paths live in `web-panel/protocol/web-contract.json`. Bridge-only IPC channels, WS opcodes, and renderer injection delays live in `web-panel/bridge/src/constants.ts`. Do not redeclare these values inline.
39- UI string-union types follow the `E*` enum convention from `.claude/rules/frontend-conventions.md` (currently `ECheatType` in `protocol/messages.ts`, `EConnectionStatus` in `remote-session/remote-session.reducer.ts`); wire string values must remain on the right-hand side of enum members. Reducer action tags stay as discriminated-union string literals.
40- Cheat input controls live one-per-file under `web-panel/src/trainer/controls/`; shared `SliderTrack` / `StepButton` / `ControlInternalProps` are in `controls/shared.tsx` and number formatting helpers in `controls/format-number.ts`. `controls/CheatControl.tsx` remains a thin dispatcher keyed by `ECheatType`.
41- Mobile drawer performance is sensitive to `backdrop-filter`. Keep drawer panels and nested glass controls blur-free under coarse pointers, and do not add per-row `backdrop-blur-*` inside drawer lists.
42 
43## Validation
44 
45- Web panel build: `cd web-panel && pnpm run build` (runs type-check, Vite build, then `build:bridge` into `dist`).
46- Bridge/script syntax checks after build: `node --check web-panel/dist/bridge.cjs` and `node --check web-panel/dist/renderer-scripts/remote-popup-cleanup.js`.
47- Production dist should contain only static assets and should not contain `mock-instance`, `Mock Adventure`, `Simulation`, `Debug session`, `mock=1`, `demo-session`, `vite.svg`, `tailwind-merge`, `class-variance-authority`, or `clsx`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48 
k1tbyte/Wand-Enhancer · web-panel/CLAUDE.md
@@ +1 @@
1Use these rules as defaults, not as a reason to add ceremonial folders or wrapper layers.
2 
3## Core Principles
4 
5- Organize code around product capabilities, not framework vocabulary.
6- Keep related UI, state, rules, and data access close until a real boundary justifies moving
7 them apart.
8- Dependencies point from composition and UI toward stable rules and narrow capabilities.
9- Protect rendering code from business, state-management, and infrastructure complexity.
10- Keep one source of truth and derive everything else.
11- Apply KISS, YAGNI, and DRY together. Remove duplicated knowledge, not merely similar syntax.
12- Prefer explicit, readable flow over clever abstractions and hidden behavior.
13 
14## Screaming Architecture
15 
16The repository structure and public APIs should reveal what the product does.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17 
18Prefer:
19 
20```text
21features/
22 checkout/
23 search/
24 account-security/
25```
 
 
 
 
 
 
26 
27Avoid making the application read primarily as:
28 
29```text
30components/
31hooks/
32services/
33stores/
34utils/
35```
36 
37Technical folders are useful inside a capability, where their owner is clear. Generic top-level
38folders easily become dependency magnets with unclear ownership.
39 
40Names should use product language. Prefer `useCheckoutSummary`, `reserveStock`, and
41`AccountSecurityPanel` over `useData`, `processItems`, and `GenericPanel`.
42 
43## Suggested Structure
44 
45Start with the smallest structure that makes ownership obvious:
46 
47```text
48src/
49 app/ startup, providers, router, global composition
50 pages/ route-level composition
51 features/
52 <capability>/
53 index.ts optional public API
54 ui/ optional rendering components
55 model/ optional state, view models, decisions
56 api/ optional external data access
57 lib/ optional feature-local pure helpers
58 domains/ optional shared product rules and types
59 shared/
60 ui/ domain-free visual primitives
61 api/ generic transport/query infrastructure
62 lib/ genuinely generic pure helpers
63```
64 
65Folders are created when they contain a real responsibility. A small feature may be one cohesive
66file. Do not create empty layers in anticipation of future complexity.
67 
68## Dependency Direction
69 
70- `app` installs providers, constructs dependencies, and composes the application.
71- `pages` compose capabilities for a route. They do not own business rules or data protocols.
72- A feature owns one user-recognizable capability end to end.
73- Feature UI consumes its own model/view-model API, not raw infrastructure.
74- Shared domain code contains reusable product rules and stays independent of React and I/O.
75- `shared` contains only domain-free code. Product-specific code is not shared merely because
76 two files use it.
77- Avoid feature-to-feature imports. Compose features in a page, promote truly shared rules to a
78 domain module, or introduce a named workflow when coordination is the actual responsibility.
79- Cyclic imports are an architecture problem, not something to solve with a tooling workaround.
80 
81For a simple feature, direct `ui -> model -> api` dependencies are sufficient. Introduce ports,
82facades, dependency injection, or workflows only when they hide real complexity, enable
83important tests, or separate unstable infrastructure.
84 
85## Make Composition Read Like The Product
86 
87Pages and other composition boundaries should use capability-level APIs.
88 
89Prefer:
90 
91```tsx
92<CheckoutSummary />
93<PlaceOrderButton />
94```
95 
96Over:
97 
98```tsx
99<Card>
100 <Select options={paymentOptions} onChange={handlePaymentChange} />
101 <Button onClick={handleSubmit}>Submit</Button>
102</Card>
103```
104 
105The second version makes the page understand checkout behavior and low-level UI configuration.
106That knowledge belongs to the checkout capability.
107 
108This does not mean wrapping every native element or design-system primitive. Semantic HTML and
109visual primitives are correct inside feature UI. Create a capability component when it hides
110product behavior or gives composition code a clearer product-level API.
111 
112Avoid "raw components" whose consumers must know internal options, state transitions, query
113shapes, or protocol details. Avoid generic configuration-driven components that combine
114unrelated product modes behind dozens of props.
115 
116## UI Boundary
117 
118- Components render data and translate DOM events into named user intents.
119- Keep business decisions, data mapping, persistence, protocol handling, and multi-step async
120 flows outside rendering components.
121- UI receives render-ready values. It should not reconstruct domain meaning from raw DTOs.
122- Prefer intent props and commands such as `onApprove`, `renameProject`, or `submitOrder` over
123 generic `onChange`, `setState`, or `patch` APIs at capability boundaries.
124- Keep ephemeral visual state local: focus, hover, open/closed, and uncommitted input usually
125 belong in the component.
126- Split components by responsibility and API clarity, not by arbitrary line limits.
127- Prefer slots and composition over components with many layout modes and boolean props.
128- Use semantic HTML and preserve accessibility behavior.
129 
130A view-model hook is useful when it protects UI from state shape, async coordination, or business
131decisions. Do not create a pass-through hook that only renames one value to satisfy a diagram.
132 
133## State Ownership
134 
135Choose the smallest correct owner:
136 
137| State | Preferred owner |
138| --- | --- |
139| Ephemeral visual state | local component state |
140| Uncommitted form state | the form or feature |
141| URL/shareable navigation state | the router/URL |
142| Remote server resource and cache | a query/cache layer |
143| Shared capability state | that feature's model/store |
144| Cross-capability process | a named workflow or app-level model |
145 
146- A store is not a bucket for every value used by several components.
147- Split state by capability and lifecycle, not by data type.
148- Expose narrow selectors, hooks, or commands. Do not expose a complete mutable store to all UI.
149- Store transitions should express user or domain intent, not generic object mutation.
150- Derive values instead of storing synchronized copies.
151- Do not use effects to keep two pieces of application state synchronized.
152- React Context is suitable for dependency injection or stable scoped state. Avoid one broad
153 app context whose every update rerenders unrelated consumers.
154 
155State-library choice is an implementation detail. Architecture should survive replacing it
156without rewriting pages and rendering components.
157 
158## Effects And Async Work
159 
160- Use effects to synchronize with external systems, not to calculate render data or handle user
161 events.
162- Start event-driven work from the event or model command that owns it.
163- Every subscription, timer, listener, or in-flight operation must have a clear owner and
164 cleanup path.
165- The owning feature/model defines pending, success, empty, error, retry, and cancellation
166 semantics.
167- Prevent stale async results and race conditions where users can trigger overlapping work.
168- Do not hide failures with broad `catch` blocks or silently convert errors into empty data.
169 
170## Data And Infrastructure
171 
172- Treat network responses, storage, URL input, files, and third-party SDK output as untrusted.
173- Validate and normalize data at the boundary where it enters the application.
174- Map transport DTOs and external errors into product-oriented values before they reach UI.
175- Keep raw `fetch`, storage APIs, SDK calls, and protocol details out of rendering components.
176- Keep a feature-specific API adapter inside the feature until it has a real shared consumer.
177- Introduce a client, repository, gateway, service, or facade only when its responsibility is
178 distinct and useful.
179- Avoid wrapper chains that only forward calls. One clear adapter is better than
180 `Client -> Service -> Facade` without separate responsibilities.
181- Inject infrastructure when tests, multiple implementations, lifecycle, or unstable external
182 APIs justify it. Do not introduce dependency injection for every pure helper.
183 
184## Component And Hook APIs
185 
186- Component and hook APIs describe product intent, not internal implementation.
187- Avoid boolean prop combinations that create unclear or invalid modes. Prefer explicit variants
188 or separate components.
189- Avoid passing raw query results, stores, SDK clients, or large configuration objects through
190 component trees.
191- Keep public props small and cohesive. A component that needs unrelated groups of props likely
192 owns too many responsibilities.
193- Custom hooks encapsulate React state, lifecycle, or reusable reactive behavior. Pure
194 calculations remain plain functions.
195- Do not use `useEffect`, `useMemo`, `useCallback`, or `memo` by habit. Use them for correctness
196 or measured performance needs.
197- Do not duplicate server or domain state into component state merely to make it editable.
198 Create an explicit draft only when the UX requires commit/cancel semantics.
199 
200## Public Boundaries
201 
202- Export the smallest useful public surface of a feature.
203- Consumers should use a feature's public components, hooks, commands, and types, not deep
204 internal paths.
205- Keep implementation-only state, DTOs, adapters, and helpers private.
206- Do not create barrel files everywhere. Use a public entry point only where a real boundary
207 exists.
208- A reusable abstraction should have a clear owner and at least one current reason to exist.
209- Avoid generic `core`, `common`, `helpers`, `services`, or `utils` modules that collect
210 unrelated responsibilities.
211 
212## Growing The Architecture
213 
214Start local and promote code only after pressure appears:
215 
216- A second consumer may justify shared domain code, but similar code is not automatically the
217 same knowledge.
218- Repeated external integration logic may justify a shared adapter.
219- A process coordinating several capabilities may justify a named workflow.
220- A large feature may split into smaller capabilities when they have distinct responsibilities
221 and lifecycles.
222- Separate packages are useful when an enforceable boundary, independent reuse, or independent
223 lifecycle outweighs their maintenance cost.
224 
225Do not begin a small application with every possible layer, package, provider, repository,
226facade, and design pattern. Strong architecture makes growth cheaper; it does not predict every
227future requirement.
228 
229## Testing
230 
231- Test product behavior and public contracts, not implementation trivia.
232- Test pure rules with unit tests.
233- Test feature models and async transitions without rendering where practical.
234- Test components through accessible user behavior.
235- Test infrastructure mapping and validation at external boundaries.
236- Keep end-to-end tests for critical user journeys.
237- Mock external systems and unstable boundaries, not every internal function.
238- Add tests proportional to risk, especially for validation, permissions, races, retries,
239 cancellation, and regressions.
240 
241## Review Checklist
242 
243Before finishing a change, ask:
244 
245- Does the file location make its owner obvious?
246- Does composition code read in product language?
247- Is UI protected from raw state, DTOs, infrastructure, and business decisions?
248- Is there one source of truth?
249- Are effects only synchronizing external systems?
250- Is new shared code genuinely domain-free or genuinely shared?
251- Does every abstraction remove current complexity?
252- Can important behavior be tested without rendering the whole app?
253- Did the change preserve accessibility, error handling, and cleanup?
254- Is this the least code that clearly solves the current problem?
255 
@@ −1 +1 @@
1−INFO ./docs/*
1+Use these rules as defaults, not as a reason to add ceremonial folders or wrapper layers.
22  
3−# Wand Enhancer Agent Notes
3+## Core Principles
44  
5−This repository patches the Wand Electron app from a .NET Framework WPF desktop tool. Keep changes narrow and preserve the patch pipeline invariants.
5+- Organize code around product capabilities, not framework vocabulary.
6+- Keep related UI, state, rules, and data access close until a real boundary justifies moving
7+ them apart.
8+- Dependencies point from composition and UI toward stable rules and narrow capabilities.
9+- Protect rendering code from business, state-management, and infrastructure complexity.
10+- Keep one source of truth and derive everything else.
11+- Apply KISS, YAGNI, and DRY together. Remove duplicated knowledge, not merely similar syntax.
12+- Prefer explicit, readable flow over clever abstractions and hidden behavior.
613  
7−## Remote Web Panel
14+## Screaming Architecture
815  
9−- The default local remote port is `3223`. Keep bridge and frontend constants aligned; C# must not duplicate the presentation URL or port.
10−- The embedded panel must stay small because the desktop patcher embeds it and then injects it into Wand's `app.asar`.
11−- Remote tooltip links and every rendered `remote-qr-code` are redirected by `web-panel/bridge/scripts/default/remote-popup-cleanup.js`. It reuses Wand's loaded QR renderer through the webpack runtime, keeps the local URL visible as a fallback, and hides the Pro onboarding remote mobile app card. Do not reintroduce C# ASAR patches for the tooltip URL or QR component; a changed UI bundle must not make the whole remote-panel patch fail.
12−- Production builds must not include mock data, debug routes, sourcemaps, local fonts, heavy icon libraries, or runtime class helper packages.
13−- The Electron bridge is authored as TypeScript under `web-panel/bridge/src/`, but production runtime must be bundled/minified into `web-panel/dist/bridge.cjs` by `pnpm run build:bridge`. Do not copy bridge source into Wand or embed it as ASAR resources.
14−- Mock/demo data is dev-only and must be reached through `import.meta.env.DEV` dynamic imports.
15−- Source can use React-compatible imports, but production runtime resolves them to Preact aliases in `web-panel/vite.config.ts`.
16−- UI uses Tailwind CSS and lightweight local primitives under `web-panel/src/shared/ui/`.
17−- Default renderer script sources live in `web-panel/bridge/scripts/default/` and are bundled/minified into `web-panel/dist/renderer-scripts/` by `pnpm run build:bridge`. Custom user scripts are selected in the WPF patch modal and copied from `PatchConfig.CustomScriptPaths`; only existing `.js` files are accepted. A local `renderer-scripts/` folder next to the patcher exe is still copied as an advanced fallback.
18−- `web-panel/bridge/scripts/default/installed-apps-sync.js` resolves Wand's renderer services/store and publishes `My Games` snapshots through the `wand-remote-installed-apps` IPC channel. The synced list must mirror Wand's `my_games` source criteria: catalog games come from `installedGameVersions`, and extra installed unsupported titles come from `correlatedUnavailableTitles` whose `games[].correlationIds` match `installedApps`.
19−- If the injected renderer cannot read a populated `correlatedUnavailableTitles` slice from the live store, `installed-apps-sync.js` must fall back to Wand's `/v3/unavailable_titles` correlation lookup through the renderer API client instead of degrading to raw install entries or an empty `My Games` list.
20−- Installed app snapshots should include game artwork in `imageUrl` when possible. `installed-apps-sync.js` must prefer Wand's own client icon CDN shape `https://api-cdn.wemod.com/steam_community/<steamAppId>/client_icon/96.webp` whenever the matched title/game/version metadata contains a Steam AppID, regardless of install platform. Do not assume `steamAppId` is a flat property; search nested `steam*` metadata before falling back to installed Steam `sku`. If metadata still does not expose the icon, fall back to the rendered Wand sidebar DOM (`.sidebar-game-row-image` background-image) keyed by `titleId` parsed from `data-tooltip-trigger-for`. The web panel `GameCover` must tolerate broken artwork URLs and fall back to its text cover.
21−- The same renderer sync script also forwards lifecycle state through `wand-remote-game-status`: `game-launched` / `game-ended` come from Wand's launch monitor service, and trainer runtime comes from the running-trainer visibility service. The web panel consumes this as the `game_status` websocket message.
22−- When Wand does not emit a `game-launched` event but a trainer is already active, `wand-remote-game-status` must synthesize a running session from the running-trainer visibility payload so the remote panel does not show an idle game session next to a running trainer.
23−- The websocket `hello` snapshot must still send cached `installed_apps` and `game_status` even when no trainer snapshot is active yet; do not reintroduce a handshake path that returns early after `trainer_changed`.
24−- Remote Play/Stop uses the websocket `remote_command` message. The bridge forwards it over `wand-remote-command` / `wand-remote-command-response`, and `installed-apps-sync.js` resolves Wand's trainer API + trainer service to launch a trainer for a `gameId` or end the current trainer.
25−- Remote Play must construct Wand's real trainer launch request class (`69482.vO`) before calling `trainerService.launch(...)`. Passing a plain object launches the game process but breaks Wand's `getMetadata(vO)`-based trainer state, causing missing status, disappearing play/close buttons, and stuck loading behavior.
26−- Pro activation is a C# asar patch (`EPatchType.ActivatePro`, independent of the remote panel / bridge). It rewrites three account-returning service methods to inject `subscription:{period:"yearly",state:"active"}` into the response before it reaches the store: `getUserAccount` and `setAccountWandBrandExperience` (Resolver-style, service field via `<service_name>` placeholder) and `setAccountLanguage` (`BuildSetAccountLanguagePatch` PatchFactory — captures the real param names + the original `post("/v3/account/language",{...})` expr and wraps `.then`). A fourth patch (`setAccountReducer`) rewrites the `ACTION_SET_ACCOUNT` store reducer so any account write (periodic `refreshAccount`, push/profile updates, etc.) keeps Pro even when it bypasses those API methods. Pro is `am(account) = !!account.subscription` (flags/512 are irrelevant). `setAccountLanguage` is the one the original two patches missed, which is why Pro dropped on language change. If a future Wand build changes these method bodies, re-derive the regexes against the live `app-*.bundle.js` (do NOT trust `.source/new` — it is a different version).
16+The repository structure and public APIs should reveal what the product does.
2717  
28−## ASAR Patch Pipeline
18+Prefer:
2919  
30−- Preserve and restore both `resources/app.asar` and `resources/app.asar.unpacked` backups.
31−- Inject `web-panel/dist` as `remote-panel/`; it must already contain `bridge.cjs` and generated default renderer scripts under `renderer-scripts/`. Selected/local custom renderer scripts are then copied under `remote-panel/renderer-scripts`.
32−- Do not commit extracted `.source/` or `.sources/` output. Recreate it only for reverse-engineering sessions.
33−- `AsarSharp.AsarExtractor.ExtractAll` must skip unpacked entries when their source path equals the destination (in-place extraction is a self-copy that fails on locked files like `TrainerLib_x64.dll`) and silently skip unpacked entries whose source is missing on disk (e.g. `auxiliary/GameLauncher.exe` removed by an installer). Do not reintroduce hard failure on either case.
34−- The `DevToolsOnF12` patch anchors on the Electron main-process `<app>.whenReady().then(` site and attaches a `before-input-event` hook to every `BrowserWindow.webContents`. Do not patch the renderer keydown listener — the minified `ACTION_OPEN_DEV_TOOLS` dispatch site is not stable across Wand releases.
35−- Cheats can be pinned per game in the web panel via `pinned-storage.ts` (`localStorage` key `wand-remote.pinned-cheats.v1:<gameId>`). Pinned cheats render as a virtual `pinned` category at the top of the list; their normal category placement is preserved.
36−- Custom quick presets are per trainer/game and stored by `preset-storage.ts` under `localStorage` key `wand-remote.presets.v1:<gameId-or-trainerId>`. Presets capture persistent cheat values only; do not include `button` one-shot cheats in saved presets.
37−- All `localStorage` access in `web-panel/src/` MUST go through `web-panel/src/shared/storage.ts` (`loadJson` / `saveJson` / `loadStringSet` / `saveStringSet`). Do not reintroduce per-capability `try/catch` + `JSON.parse` duplication. Trainer/game storage IDs are derived through the shared `getTrainerStorageId(trainer)` helper; do not re-implement the `gameId → titleId → trainerId → 'global'` precedence inline.
38−- Shared web protocol version, port, and HTTP/WS paths live in `web-panel/protocol/web-contract.json`. Bridge-only IPC channels, WS opcodes, and renderer injection delays live in `web-panel/bridge/src/constants.ts`. Do not redeclare these values inline.
39−- UI string-union types follow the `E*` enum convention from `.claude/rules/frontend-conventions.md` (currently `ECheatType` in `protocol/messages.ts`, `EConnectionStatus` in `remote-session/remote-session.reducer.ts`); wire string values must remain on the right-hand side of enum members. Reducer action tags stay as discriminated-union string literals.
40−- Cheat input controls live one-per-file under `web-panel/src/trainer/controls/`; shared `SliderTrack` / `StepButton` / `ControlInternalProps` are in `controls/shared.tsx` and number formatting helpers in `controls/format-number.ts`. `controls/CheatControl.tsx` remains a thin dispatcher keyed by `ECheatType`.
41−- Mobile drawer performance is sensitive to `backdrop-filter`. Keep drawer panels and nested glass controls blur-free under coarse pointers, and do not add per-row `backdrop-blur-*` inside drawer lists.
20+```text
21+features/
22+ checkout/
23+ search/
24+ account-security/
25+```
4226  
43−## Validation
27+Avoid making the application read primarily as:
4428  
45−- Web panel build: `cd web-panel && pnpm run build` (runs type-check, Vite build, then `build:bridge` into `dist`).
46−- Bridge/script syntax checks after build: `node --check web-panel/dist/bridge.cjs` and `node --check web-panel/dist/renderer-scripts/remote-popup-cleanup.js`.
47−- Production dist should contain only static assets and should not contain `mock-instance`, `Mock Adventure`, `Simulation`, `Debug session`, `mock=1`, `demo-session`, `vite.svg`, `tailwind-merge`, `class-variance-authority`, or `clsx`.
29+```text
30+components/
31+hooks/
32+services/
33+stores/
34+utils/
35+```
36+ 
37+Technical folders are useful inside a capability, where their owner is clear. Generic top-level
38+folders easily become dependency magnets with unclear ownership.
39+ 
40+Names should use product language. Prefer `useCheckoutSummary`, `reserveStock`, and
41+`AccountSecurityPanel` over `useData`, `processItems`, and `GenericPanel`.
42+ 
43+## Suggested Structure
44+ 
45+Start with the smallest structure that makes ownership obvious:
46+ 
47+```text
48+src/
49+ app/ startup, providers, router, global composition
50+ pages/ route-level composition
51+ features/
52+ <capability>/
53+ index.ts optional public API
54+ ui/ optional rendering components
55+ model/ optional state, view models, decisions
56+ api/ optional external data access
57+ lib/ optional feature-local pure helpers
58+ domains/ optional shared product rules and types
59+ shared/
60+ ui/ domain-free visual primitives
61+ api/ generic transport/query infrastructure
62+ lib/ genuinely generic pure helpers
63+```
64+ 
65+Folders are created when they contain a real responsibility. A small feature may be one cohesive
66+file. Do not create empty layers in anticipation of future complexity.
67+ 
68+## Dependency Direction
69+ 
70+- `app` installs providers, constructs dependencies, and composes the application.
71+- `pages` compose capabilities for a route. They do not own business rules or data protocols.
72+- A feature owns one user-recognizable capability end to end.
73+- Feature UI consumes its own model/view-model API, not raw infrastructure.
74+- Shared domain code contains reusable product rules and stays independent of React and I/O.
75+- `shared` contains only domain-free code. Product-specific code is not shared merely because
76+ two files use it.
77+- Avoid feature-to-feature imports. Compose features in a page, promote truly shared rules to a
78+ domain module, or introduce a named workflow when coordination is the actual responsibility.
79+- Cyclic imports are an architecture problem, not something to solve with a tooling workaround.
80+ 
81+For a simple feature, direct `ui -> model -> api` dependencies are sufficient. Introduce ports,
82+facades, dependency injection, or workflows only when they hide real complexity, enable
83+important tests, or separate unstable infrastructure.
84+ 
85+## Make Composition Read Like The Product
86+ 
87+Pages and other composition boundaries should use capability-level APIs.
88+ 
89+Prefer:
90+ 
91+```tsx
92+<CheckoutSummary />
93+<PlaceOrderButton />
94+```
95+ 
96+Over:
97+ 
98+```tsx
99+<Card>
100+ <Select options={paymentOptions} onChange={handlePaymentChange} />
101+ <Button onClick={handleSubmit}>Submit</Button>
102+</Card>
103+```
104+ 
105+The second version makes the page understand checkout behavior and low-level UI configuration.
106+That knowledge belongs to the checkout capability.
107+ 
108+This does not mean wrapping every native element or design-system primitive. Semantic HTML and
109+visual primitives are correct inside feature UI. Create a capability component when it hides
110+product behavior or gives composition code a clearer product-level API.
111+ 
112+Avoid "raw components" whose consumers must know internal options, state transitions, query
113+shapes, or protocol details. Avoid generic configuration-driven components that combine
114+unrelated product modes behind dozens of props.
115+ 
116+## UI Boundary
117+ 
118+- Components render data and translate DOM events into named user intents.
119+- Keep business decisions, data mapping, persistence, protocol handling, and multi-step async
120+ flows outside rendering components.
121+- UI receives render-ready values. It should not reconstruct domain meaning from raw DTOs.
122+- Prefer intent props and commands such as `onApprove`, `renameProject`, or `submitOrder` over
123+ generic `onChange`, `setState`, or `patch` APIs at capability boundaries.
124+- Keep ephemeral visual state local: focus, hover, open/closed, and uncommitted input usually
125+ belong in the component.
126+- Split components by responsibility and API clarity, not by arbitrary line limits.
127+- Prefer slots and composition over components with many layout modes and boolean props.
128+- Use semantic HTML and preserve accessibility behavior.
129+ 
130+A view-model hook is useful when it protects UI from state shape, async coordination, or business
131+decisions. Do not create a pass-through hook that only renames one value to satisfy a diagram.
132+ 
133+## State Ownership
134+ 
135+Choose the smallest correct owner:
136+ 
137+| State | Preferred owner |
138+| --- | --- |
139+| Ephemeral visual state | local component state |
140+| Uncommitted form state | the form or feature |
141+| URL/shareable navigation state | the router/URL |
142+| Remote server resource and cache | a query/cache layer |
143+| Shared capability state | that feature's model/store |
144+| Cross-capability process | a named workflow or app-level model |
145+ 
146+- A store is not a bucket for every value used by several components.
147+- Split state by capability and lifecycle, not by data type.
148+- Expose narrow selectors, hooks, or commands. Do not expose a complete mutable store to all UI.
149+- Store transitions should express user or domain intent, not generic object mutation.
150+- Derive values instead of storing synchronized copies.
151+- Do not use effects to keep two pieces of application state synchronized.
152+- React Context is suitable for dependency injection or stable scoped state. Avoid one broad
153+ app context whose every update rerenders unrelated consumers.
154+ 
155+State-library choice is an implementation detail. Architecture should survive replacing it
156+without rewriting pages and rendering components.
157+ 
158+## Effects And Async Work
159+ 
160+- Use effects to synchronize with external systems, not to calculate render data or handle user
161+ events.
162+- Start event-driven work from the event or model command that owns it.
163+- Every subscription, timer, listener, or in-flight operation must have a clear owner and
164+ cleanup path.
165+- The owning feature/model defines pending, success, empty, error, retry, and cancellation
166+ semantics.
167+- Prevent stale async results and race conditions where users can trigger overlapping work.
168+- Do not hide failures with broad `catch` blocks or silently convert errors into empty data.
169+ 
170+## Data And Infrastructure
171+ 
172+- Treat network responses, storage, URL input, files, and third-party SDK output as untrusted.
173+- Validate and normalize data at the boundary where it enters the application.
174+- Map transport DTOs and external errors into product-oriented values before they reach UI.
175+- Keep raw `fetch`, storage APIs, SDK calls, and protocol details out of rendering components.
176+- Keep a feature-specific API adapter inside the feature until it has a real shared consumer.
177+- Introduce a client, repository, gateway, service, or facade only when its responsibility is
178+ distinct and useful.
179+- Avoid wrapper chains that only forward calls. One clear adapter is better than
180+ `Client -> Service -> Facade` without separate responsibilities.
181+- Inject infrastructure when tests, multiple implementations, lifecycle, or unstable external
182+ APIs justify it. Do not introduce dependency injection for every pure helper.
183+ 
184+## Component And Hook APIs
185+ 
186+- Component and hook APIs describe product intent, not internal implementation.
187+- Avoid boolean prop combinations that create unclear or invalid modes. Prefer explicit variants
188+ or separate components.
189+- Avoid passing raw query results, stores, SDK clients, or large configuration objects through
190+ component trees.
191+- Keep public props small and cohesive. A component that needs unrelated groups of props likely
192+ owns too many responsibilities.
193+- Custom hooks encapsulate React state, lifecycle, or reusable reactive behavior. Pure
194+ calculations remain plain functions.
195+- Do not use `useEffect`, `useMemo`, `useCallback`, or `memo` by habit. Use them for correctness
196+ or measured performance needs.
197+- Do not duplicate server or domain state into component state merely to make it editable.
198+ Create an explicit draft only when the UX requires commit/cancel semantics.
199+ 
200+## Public Boundaries
201+ 
202+- Export the smallest useful public surface of a feature.
203+- Consumers should use a feature's public components, hooks, commands, and types, not deep
204+ internal paths.
205+- Keep implementation-only state, DTOs, adapters, and helpers private.
206+- Do not create barrel files everywhere. Use a public entry point only where a real boundary
207+ exists.
208+- A reusable abstraction should have a clear owner and at least one current reason to exist.
209+- Avoid generic `core`, `common`, `helpers`, `services`, or `utils` modules that collect
210+ unrelated responsibilities.
211+ 
212+## Growing The Architecture
213+ 
214+Start local and promote code only after pressure appears:
215+ 
216+- A second consumer may justify shared domain code, but similar code is not automatically the
217+ same knowledge.
218+- Repeated external integration logic may justify a shared adapter.
219+- A process coordinating several capabilities may justify a named workflow.
220+- A large feature may split into smaller capabilities when they have distinct responsibilities
221+ and lifecycles.
222+- Separate packages are useful when an enforceable boundary, independent reuse, or independent
223+ lifecycle outweighs their maintenance cost.
224+ 
225+Do not begin a small application with every possible layer, package, provider, repository,
226+facade, and design pattern. Strong architecture makes growth cheaper; it does not predict every
227+future requirement.
228+ 
229+## Testing
230+ 
231+- Test product behavior and public contracts, not implementation trivia.
232+- Test pure rules with unit tests.
233+- Test feature models and async transitions without rendering where practical.
234+- Test components through accessible user behavior.
235+- Test infrastructure mapping and validation at external boundaries.
236+- Keep end-to-end tests for critical user journeys.
237+- Mock external systems and unstable boundaries, not every internal function.
238+- Add tests proportional to risk, especially for validation, permissions, races, retries,
239+ cancellation, and regressions.
240+ 
241+## Review Checklist
242+ 
243+Before finishing a change, ask:
244+ 
245+- Does the file location make its owner obvious?
246+- Does composition code read in product language?
247+- Is UI protected from raw state, DTOs, infrastructure, and business decisions?
248+- Is there one source of truth?
249+- Are effects only synchronizing external systems?
250+- Is new shared code genuinely domain-free or genuinely shared?
251+- Does every abstraction remove current complexity?
252+- Can important behavior be tested without rendering the whole app?
253+- Did the change preserve accessibility, error handling, and cleanup?
254+- Is this the least code that clearly solves the current problem?
48255  
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack