feat: add detectAbilitySpike detector using activePlayer.abilities#41
feat: add detectAbilitySpike detector using activePlayer.abilities#41Copilot wants to merge 12 commits into
Conversation
Track ability levels (Q/W/E/R) between ticks in ContextState. Fire trading signals on R unlock (0→1, priority 78) and R rank-up (priority 74). Add ability-spike prompt templates to trading category. Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/bd73da1a-80d0-4657-9fc1-6cfa24d07aa7 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/bd73da1a-80d0-4657-9fc1-6cfa24d07aa7 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
|
@copilot This needs a first-snapshot guard. Right now I only want this detector to react to changes between observed ticks, not initial state seeding. Seed the stored ability levels on first observation and only fire once we've actually seen a transition. |
Use null sentinel for lastAbilityLevels initial state. On first observation, seed the levels without firing a spike. This prevents bogus prompts when Beacon attaches mid-game to a champion that already has R unlocked. Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/9de8993b-2547-4cef-879e-e07d94763238 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
Added in d0b4479. |
There was a problem hiding this comment.
Pull request overview
Adds a new stateful detector that uses activePlayer.abilities deltas to detect ultimate unlock/rank-up spikes and surface more targeted trading prompts than the existing level-based detector.
Changes:
- Extend
ContextStatewithlastAbilityLevelsto persist per-ability levels across ticks. - Add
detectAbilitySpiketo emitult_unlock/ult_rank_uptrading signals based on R level changes, and register it inALL_DETECTORS. - Add new trading prompt templates plus unit tests covering seeding, unlock, rank-up, and no-false-positive behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/main/detectors.ts | Introduces detectAbilitySpike and wires it into the detector pipeline. |
| src/main/context.ts | Adds AbilityLevels and lastAbilityLevels to context state initialization/type. |
| src/main/context.test.ts | Extends snapshot builder to vary ability levels and adds tests for the new detector behavior. |
| data/prompts.json | Adds two trading prompt templates that resolve via {ability} / {ability_level}. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
* Initial plan * fix: add sanitizeText guard for prompt text in renderer.js Defense-in-depth: strip HTML from prompt strings via DOMParser before DOM insertion so future changes to innerHTML won't introduce XSS. Also guards against null/undefined input. Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/4258d419-9607-411a-953a-1078f5aa6e8d Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * Rework: revert sanitizeText, add invariant test instead Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/78c779e4-6dd9-4ec6-b714-cd3064fe585f Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * fix: add renderer invariant test for innerText safety Adds a static-analysis test (renderer.test.ts) that reads renderer.js and asserts prompt text is set via innerText, not innerHTML. This protects against accidental XSS regression without mutating display text at runtime. Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/78c779e4-6dd9-4ec6-b714-cd3064fe585f Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
* Initial plan * self-host Rajdhani font and remove unsafe-inline from CSP - Add woff2 font files for Rajdhani (500, 600, 700) to assets/fonts/ - Create fonts.css with @font-face declarations - Remove Google Fonts CDN links and preconnect from both HTML files - Remove unsafe-inline from style-src and update font-src to 'self' in CSP Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/4659a37b-89be-454d-aa1d-e97931227613 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * add OFL.txt license for self-hosted Rajdhani font Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/9b20272a-0196-4444-a60e-c82d9a5034a8 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
* Initial plan
* refactor: return state changes instead of mutating newState parameter
- processEvents now returns { newEvents, stateUpdates } instead of mutating newState
- detectVision and detectTabCheck return stateUpdates via DetectorResult
- detectItemCompleted no longer mutates newState; item tracking moved to deriveContext
- Removed newState from DetectorInput type
- deriveContext merges all state updates from processEvents and detectors
- Added DetectorResult.stateUpdates optional field
- Exported getRealItems for use in deriveContext
- Added 3 immutability tests verifying state parameter is never mutated
Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/f01206eb-225b-423f-87d8-40450536f3d4
Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
* test: use deepFreeze and structuredClone in immutability tests
Shallow copy ({ ...state }) wouldn't catch mutations to nested arrays
like lastMyItemIds. Now deep-freeze the input state (so any mutation
throws) and use structuredClone for the comparison snapshot.
Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/b5f93a2a-cf0e-4c5b-9297-1bad73959eff
Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
…polling while hidden (#38) * Initial plan * fix: clear cursor hit-test interval on overlay window close Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/2e9aa352-242a-45c9-a972-57c47476c060 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * perf: skip cursor hit-test polling while overlay is hidden Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/5b544e64-fa09-4a43-8318-f0f4f7ad555c Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
* Initial plan * chore: document intentional output mode toggle bypass in main.ts Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/80f417f6-e948-4493-b31e-72fcf212dc5f Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
* Initial plan * feat: distinguish 'waiting for game' from server errors Categorize FETCH_ERROR by error type: - ECONNREFUSED/ECONNRESET → game_not_running (waiting for game) - Certificate errors → cert_error (config problem) - Other errors → unknown Only game_not_running resets to WAITING_FOR_GAME. Other errors surface to the hub UI with an error state (red styling + reason). Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/3c40a88e-4902-4fbb-b2da-880452de9dc1 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * fix: reset prompt state and window visibility on non-game errors Error transitions now call resetState() in handleServerMessage and stopPromptLoop()/overlay.hide()/hub.show() in main.ts, ensuring cooldown timers, prompt history, and window visibility are properly cleaned up when cert or unknown errors occur mid-game. Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/473cd351-5bf6-4edf-bb16-11738d19ab65 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * fix: type-safe error narrowing and preserve error state on server exit - Use typeof transition === 'object' narrowing before accessing .type - Track lastAppStatus to prevent exit handler from overwriting error state with 'waiting' Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/6fedba23-f7b2-4b19-9188-1d3d53c5c492 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> * refactor: use union type for lastAppStatus instead of loose string Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/6fedba23-f7b2-4b19-9188-1d3d53c5c492 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
|
@copilot correction to my last note: this branch is now stale against latest main after #35 merged. Please rebase or update it and adapt the ability-spike work to the current state-update flow instead of relying on the older newState mutation path. Keep the first-observation seed-without-firing behavior for lastAbilityLevels. |
…ility-spike-detector Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
Merge latest main (post-PR #35) and adapt ability-spike work: - Move ability-level tracking into deriveContext (like item tracking) so lastAbilityLevels is updated every snapshot regardless of detector result - Remove newState mutation from detectAbilitySpike; it now reads directly from state and snapshot as a pure comparison function - Remove unused AbilityLevels import from detectors.ts - Keep first-observation seed-without-firing behavior via null guard Agent-Logs-Url: https://github.com/Ilia01/Beacon/sessions/e6acf140-33ae-4815-9398-30ba93834e08 Co-authored-by: Ilia01 <155351862+Ilia01@users.noreply.github.com>
Merged latest main and adapted in 463271f. Ability-level tracking now lives in |
|
@copilot This branch is not just stale, it is still built on the pre-#35 detector flow. writes through , and the branch still carries the older context shape, so I can't merge it on top of current main as-is. Rebuild this on current main and implement the ability-spike state update through the current state-update path instead of reviving the old mutable detector input shape. |
What changed
New
detectAbilitySpikedetector that tracksactivePlayer.abilities.{Q,W,E,R}.abilityLevelbetween ticks and fires on R power spikes:context.ts— AddedlastAbilityLevels: { Q, W, E, R } | nulltoContextState. Initializes asnullto distinguish "never observed" from "all abilities at zero"detectors.ts—detectAbilitySpikefiresult_unlock(priority 78) on R 0→1,ult_rank_up(priority 74) on subsequent R rank-ups. Includes a first-snapshot guard: whenlastAbilityLevelsisnull, it seeds current levels into state without firing, preventing bogus prompts on mid-game attach. Registered inALL_DETECTORSahead ofdetectLevelSpikeso the more specific signal winsprompts.json— Two new trading templates with{ability}/{ability_level}placeholders, filtered via existingcanResolvelogiccontext.test.ts— 5 tests: first-snapshot seeding without firing, ult unlock, ult rank-up, no false positive on unchanged R, state trackingKept separate from
detectLevelSpike— ability unlocks are a distinct signal with different prompt templates.Why
detectLevelSpikefires generically on levels 2/3/6/9/11/16 without knowing which ability was actually ranked. The API exposes per-ability levels that change between ticks, enabling targeted prompts like "You just unlocked R — look for an all-in."How to test
npx vitest run— 33/33 passnpm run build— cleanChecklist