Problem Statement
The coach cannot reason about game mechanics. Asked why Counterspell might help, everything it knows is that Counterspell "is a Tier 3 Vitality Item that can be purchased from the Shop for 3,200." Asked about Dynamo, it returns lore about Columbia College. It has no access to what an ability or item actually does.
This blocks every item question a player actually asks:
- their lane opponent sustains heavily — what cuts that?
- their ult keeps getting interrupted — what stops that?
- an enemy just bought a counter to them — what answers it?
- an objective is contested soon and a specific enemy threat matters — what should be bought first?
None of these can be answered from win rates or usage tables. They need mechanics: which ability heals and by how much, which item applies healing reduction, which item grants stun immunity. All of it exists upstream as structured properties and none of it reaches the coach.
A second, related gap: the coach cannot tell a player whether they are building their hero correctly at all, independent of any opponent. There is no notion of what a hero's usual build looks like, so it cannot notice that a Seven is missing an item 54% of strong Sevens buy.
Solution
Give the coach mechanics — the structured properties of items and hero abilities — as primitives it composes per situation, and pair them with two statistical layers that keep its reasoning honest.
The player asks a question in natural language, describing their situation. The coach looks up the mechanics involved, checks them against what strong players actually buy, and answers with both the reason and the evidence:
Dynamo's Singularity is a 2.75s channel that stuns and pulls in a 7m radius. Unstoppable suppresses stun for its duration, which is why 54% of high-badge Sevens buy it — you have it in 2 of your last 12 games.
Four capabilities deliver this:
- Mechanics primitives — the coach can look up what a hero's abilities do, what an item does, and which items produce a given effect.
- Patch-aware mechanics freshness — mechanics are never stale, because a balance patch invalidates them immediately rather than up to a week later.
- Hero signature — for every hero, the items it buys far more often than average, so the coach can judge a build with no opponent context at all.
- Post-match review — the player's own purchase history compared against the high-badge baseline, so a recommendation can be checked against what they actually do.
User Stories
- As a player, I want the coach to tell me what an item actually does, so that I understand why it is being recommended instead of taking it on faith.
- As a player, I want the coach to know what a hero's abilities do, so that I can ask about threats without explaining the game to it first.
- As a player, I want to ask "what stops me getting interrupted during my ult", so that I get an answer without knowing which item to name.
- As a player, I want the coach to name the mechanic behind a recommendation, so that I can judge whether it applies to my situation.
- As a player, I want to describe my situation in my own words, so that I am not restricted to scenarios someone anticipated.
- As a player, I want the coach to answer questions about objective timing and enemy threats together, so that advice reflects the game state and not just the matchup.
- As a player, I want the coach to tell me which items reduce enemy healing, so that I can respond to a sustain-heavy lane.
- As a player, I want the coach to distinguish an item that reduces enemy healing from one that boosts my own, so that I am not sold a self-buff as a counter.
- As a player, I want mechanics answers to be correct immediately after a balance patch, so that I am not told to buy an item for an effect it no longer has.
- As a player, I want to know what items my hero usually buys, so that I can tell whether my build is unusual.
- As a player, I want to know which of my hero's items are distinctive rather than universal, so that I learn what matters for this hero specifically.
- As a player, I want the hero signature to reflect the current patch, so that I am not shown a build that a rework invalidated.
- As a player, I want to see how my own purchases compare against strong players, so that I know which habits to change.
- As a player, I want to know how often I buy an item in situations where it applies, so that the gap is concrete rather than a general suggestion.
- As a player, I want the coach to look at what my opponents bought in my own games, so that it can tell me about threats I failed to answer.
- As a player, I want every statistic to state which rank bracket it came from, so that I know whether it describes players like me.
- As a player, I want every statistic to state which patch window it came from, so that I know how current it is.
- As a player, I want every statistic to state its sample size, so that I can judge how much to trust it.
- As a player, I want the coach to decline to rank when the sample is too small, so that I am not given a number that is noise.
- As a player, I want the coach to say when it fell back to data from before the current patch, so that I can discount it if the patch changed something relevant.
- As a player, I want mechanics stated without hedging, so that provenance caveats attach only to statistics and do not bury the advice.
- As a player, I want to ask about a hero I rarely play and still get an answer, so that coverage does not depend on my history.
- As a player, I want the coach to tell me when it has no data for a matchup, so that I do not mistake silence for a recommendation.
- As a player, I want post-match review to cover as many of my matches as possible, so that patterns are visible rather than anecdotal.
- As a maintainer, I want mechanics stored in the warehouse rather than an ad-hoc cache, so that queries across all items are possible and complete.
- As a maintainer, I want the mechanics sync to be a small number of requests, so that refreshing after a patch is cheap.
- As a maintainer, I want the hero signature sync to follow the existing snapshot and normalize pattern, so that it is auditable and consistent with every other analytics surface.
- As a maintainer, I want every stored statistic to carry its snapshot, so that any answer can be traced to the data it came from.
- As a maintainer, I want asset freshness driven by patch detection rather than a timer, so that correctness does not depend on when the cache happened to expire.
- As a maintainer, I want match metadata backfilled in bulk, so that post-match review is not limited by hydration coverage.
- As a maintainer, I want new coaching scenarios to require no new tools, so that the surface does not grow one function per question.
- As a maintainer, I want the primitives testable at a single seam, so that coverage does not fragment across layers.
- As a maintainer, I want the sample floor to be a named threshold, so that the decline-to-rank behaviour is verifiable rather than a judgement call.
- As a maintainer, I want the rank bracket used for recommendations to be explicit and configurable, so that ADR-0003 can be revisited without a rewrite.
Implementation Decisions
Mechanics primitives (ADR-0004)
Four new coach tools, all compositional. No answer-shaped tool that returns a ranked recommendation directly — that was considered and rejected, because it expresses one scenario class and silently drops situational context for the others.
get_hero_mechanics(hero) — the hero's abilities with their properties: channel time, cooldown, radius, heal factor, applied status effects.
get_item_mechanics(item) — an item's tier, cost, slot, active/passive, description, and properties.
find_items_by_effect(effect) — items whose properties match an effect, e.g. "healing reduction" resolves to the items carrying heal-amp penalty properties. This is the primitive that makes unanticipated scenarios work; it must scan all items, which is why mechanics live in the warehouse and not a per-item cache.
get_hero_item_stats(hero, ...) — hero signature, and the player's own comparison where an account is in context.
Descriptions from upstream contain embedded markup and, in some cases, inline SVG. Text must be sanitised before reaching the coach. Property keys are the reliable structured signal; description prose is supporting detail only.
Mechanics storage
Mechanics are normalized into the warehouse following the existing source_snapshot → normalize_* → read_latest_* pattern, not read from the per-item asset cache. Two upstream calls populate everything — the item asset endpoint returns all entries in one response, likewise heroes.
Scope is roughly 173 shopable items and 200 abilities belonging to playable heroes. Item property keys number in the hundreds; ability property keys number over a thousand, the majority of which are plumbing (cooldowns, cast times, radii) rather than threat-bearing. Storage should preserve properties generically rather than modelling a fixed column per property, since the key space changes with patches.
Ability records must be associable with the hero that owns them, and only abilities belonging to selectable, non-disabled heroes are in scope.
Asset freshness
Item and hero assets currently expire on a fixed multi-day timer. Patches have shipped a day apart, so this can serve stale mechanics for up to a week — unacceptable for the layer that supplies the reason behind a recommendation.
Freshness becomes patch-driven: the arrival of a new patch event invalidates mechanics and triggers a re-sync. The timer remains only as a backstop for the case where no patch has been observed. Mechanics are always current; only statistics degrade with window age.
Hero signature
For each playable hero, pick-share lift over the global average establishes which items are distinctive to that hero. Ranking uses pick-share lift, never win rate (ADR-0001).
- Sourced at high badge, per ADR-0003. The player's own bracket is the comparison, not the source. Ranking on the player's bracket was measured to invert the result for at least one item.
- One request per hero plus one global baseline — a small, bounded sync.
- Scoped to a patch window. Where the current patch has insufficient sample, the window widens to prior patches and the widening is disclosed in the answer.
- Sample floor governs whether a ranking is produced at all; below it the coach declines rather than reporting a weak figure. Thin windows were measured to flip a lift from positive to negative.
- The denominator must be the true match count for the hero, not inferred from the most-purchased item. An inferred denominator distorts absolute percentages even where it preserves ordering.
Post-match review
Compares the player's own purchases against the high-badge baseline for the matchups they actually faced. A join between locally stored purchases and the signature baselines — no new upstream data.
Locally stored purchases already cover every player in a hydrated match, not only the coached account, so opponents' builds within the player's own history are available. This supports observations of the form "they bought X in N of your recent games and you never answered it".
Depends on hydration backfill. Match history currently runs far ahead of hydration — hundreds of matches in history against a few dozen hydrated. Review quality is bounded by the hydrated count. The bulk metadata endpoint accepts many match ids per request, so backfilling the full history is a handful of requests rather than one per match. Backfill must be resumable and must not re-fetch already-hydrated matches.
Disclosure
Every statistic carries its patch window, rank bracket, and sample size. Below the sample floor the coach declines to rank.
Attribution is part of the claim, not a caveat: the normal case is a recommendation drawn from a bracket the player does not play in, so an unattributed figure asserts something other than what was measured. Mechanics need no attribution — they hold at every bracket and patch. Answers should lead with mechanism and follow with evidence.
Confounds
Any new metric introduced here must be compared against a matched baseline. Comparing a filtered sample against an unfiltered one reintroduces confounds that have already produced three false signals during design: item win rate, enemy-networth as a proxy for an enemy being ahead, and item co-occurrence without duration control. Where a filter correlates with match length, the baseline must carry the same filter.
Testing Decisions
Tests assert external behaviour only — what the coach can answer — not internal structure. A normalizer signature or storage shape may change freely provided the tools still answer correctly.
Single seam: the public coach tool functions. This is the highest available seam and the one the agent actually calls. Prior art exists for it, patching the upstream client and building a temporary workspace per test. Sync routines are exercised as setup within these tests rather than as their own assertion target, so ingestion is covered without a second seam.
Directly testing the normalizers was considered and rejected — it duplicates coverage the tool seam already provides and couples tests to warehouse shape.
Cases to cover:
- A mechanics lookup returns an ability's structured properties, including a channelled ult's channel time and applied status effects.
- An item lookup returns properties and sanitised description text, with embedded markup and inline SVG stripped.
- An effect search returns items carrying the matching property and excludes a decoy — an item that superficially relates to the effect but applies it to the caster rather than the enemy. This is the direction problem that pure property matching cannot solve alone.
- Inserting a patch event invalidates mechanics and causes a re-sync on the next lookup; without one, no re-fetch occurs.
- A hero signature sync followed by a read returns items ranked by pick-share lift, with the hero's distinctive items ahead of universal ones.
- A signature response carries patch window, rank bracket, and sample size.
- Below the sample floor, the tool declines to rank rather than returning a low-confidence ordering.
- Where the current patch window is too thin, the window widens and the response states that it did.
- Post-match review reports the gap between the player's purchases and the high-badge baseline, with sample size attached.
- Post-match review surfaces an opponent's purchase from the player's own history that the player did not answer.
- Hydration backfill skips already-hydrated matches and is resumable across interrupted runs.
- A hero or matchup with no stored data returns an explicit no-data response rather than an empty or misleading one.
Fixtures should use realistic upstream payload shapes, including the markup and SVG contamination present in real item descriptions.
Out of Scope
- The SQL mining pipeline. Discovering counter reactions between items via cross-team queries is v2. It requires matched-baseline controls, significance testing, and mechanics-based pruning of candidate pairs — none of which are designed yet. It gets its own spec.
- Matchup and lane-duel statistics. Only hero signature (opponent-independent) is in scope. Matchup lift is real but roughly an order of magnitude weaker, and it depends on scoping decisions best made after the signature layer exists.
- Live match telemetry. Rejected in ADR-0002. The live endpoint exposes no items and no match clock, and the broadcast-parser path is rate-limited to two requests per hour. The enemy lineup is an input the player provides.
- Threat axes beyond sustain. The taxonomy expands later; the first axis proves the pipeline.
- Any UI surface. No new HTTP routes and no frontend work. The coach chat is the product surface.
- Automated sync scheduling. Who runs the sync — manual, local scheduler, or CI — is unresolved and deliberately excluded.
- Build archetype viability. Judging whether a whole build path suits a matchup needs build-level data not covered here.
Further Notes
The API key matters for v2, not v1. An upstream API key is already read from configuration and sent as a header, but is absent from the example environment file. v1 stays comfortably within anonymous rate limits; the mining pipeline does not. Adding it to the example file is a cheap, useful side task.
Ordering. Mechanics primitives first — that is the actual unblocker, and the hero signature is far less useful without a reason attached. The asset freshness fix belongs alongside it, since the two touch the same data. Hydration backfill must land before post-match review is judged, or it will look weak for reasons unrelated to its design.
Vocabulary. The domain glossary defines the terms used throughout: mechanics, hero signature, pick-share lift, patch window, grounding, confound. Use them rather than synonyms — particularly "pick-share lift" over "win rate delta", which names a rejected approach.
Effect sizes for calibration. Hero signature lifts run large — tens of percentage points over the global average, and every playable hero has a distinctive set. If the implemented signature produces uniformly small lifts, something is wrong with the baseline or denominator rather than with the data.
Problem Statement
The coach cannot reason about game mechanics. Asked why Counterspell might help, everything it knows is that Counterspell "is a Tier 3 Vitality Item that can be purchased from the Shop for 3,200." Asked about Dynamo, it returns lore about Columbia College. It has no access to what an ability or item actually does.
This blocks every item question a player actually asks:
None of these can be answered from win rates or usage tables. They need mechanics: which ability heals and by how much, which item applies healing reduction, which item grants stun immunity. All of it exists upstream as structured properties and none of it reaches the coach.
A second, related gap: the coach cannot tell a player whether they are building their hero correctly at all, independent of any opponent. There is no notion of what a hero's usual build looks like, so it cannot notice that a Seven is missing an item 54% of strong Sevens buy.
Solution
Give the coach mechanics — the structured properties of items and hero abilities — as primitives it composes per situation, and pair them with two statistical layers that keep its reasoning honest.
The player asks a question in natural language, describing their situation. The coach looks up the mechanics involved, checks them against what strong players actually buy, and answers with both the reason and the evidence:
Four capabilities deliver this:
User Stories
Implementation Decisions
Mechanics primitives (ADR-0004)
Four new coach tools, all compositional. No answer-shaped tool that returns a ranked recommendation directly — that was considered and rejected, because it expresses one scenario class and silently drops situational context for the others.
get_hero_mechanics(hero)— the hero's abilities with their properties: channel time, cooldown, radius, heal factor, applied status effects.get_item_mechanics(item)— an item's tier, cost, slot, active/passive, description, and properties.find_items_by_effect(effect)— items whose properties match an effect, e.g. "healing reduction" resolves to the items carrying heal-amp penalty properties. This is the primitive that makes unanticipated scenarios work; it must scan all items, which is why mechanics live in the warehouse and not a per-item cache.get_hero_item_stats(hero, ...)— hero signature, and the player's own comparison where an account is in context.Descriptions from upstream contain embedded markup and, in some cases, inline SVG. Text must be sanitised before reaching the coach. Property keys are the reliable structured signal; description prose is supporting detail only.
Mechanics storage
Mechanics are normalized into the warehouse following the existing
source_snapshot → normalize_* → read_latest_*pattern, not read from the per-item asset cache. Two upstream calls populate everything — the item asset endpoint returns all entries in one response, likewise heroes.Scope is roughly 173 shopable items and 200 abilities belonging to playable heroes. Item property keys number in the hundreds; ability property keys number over a thousand, the majority of which are plumbing (cooldowns, cast times, radii) rather than threat-bearing. Storage should preserve properties generically rather than modelling a fixed column per property, since the key space changes with patches.
Ability records must be associable with the hero that owns them, and only abilities belonging to selectable, non-disabled heroes are in scope.
Asset freshness
Item and hero assets currently expire on a fixed multi-day timer. Patches have shipped a day apart, so this can serve stale mechanics for up to a week — unacceptable for the layer that supplies the reason behind a recommendation.
Freshness becomes patch-driven: the arrival of a new patch event invalidates mechanics and triggers a re-sync. The timer remains only as a backstop for the case where no patch has been observed. Mechanics are always current; only statistics degrade with window age.
Hero signature
For each playable hero, pick-share lift over the global average establishes which items are distinctive to that hero. Ranking uses pick-share lift, never win rate (ADR-0001).
Post-match review
Compares the player's own purchases against the high-badge baseline for the matchups they actually faced. A join between locally stored purchases and the signature baselines — no new upstream data.
Locally stored purchases already cover every player in a hydrated match, not only the coached account, so opponents' builds within the player's own history are available. This supports observations of the form "they bought X in N of your recent games and you never answered it".
Depends on hydration backfill. Match history currently runs far ahead of hydration — hundreds of matches in history against a few dozen hydrated. Review quality is bounded by the hydrated count. The bulk metadata endpoint accepts many match ids per request, so backfilling the full history is a handful of requests rather than one per match. Backfill must be resumable and must not re-fetch already-hydrated matches.
Disclosure
Every statistic carries its patch window, rank bracket, and sample size. Below the sample floor the coach declines to rank.
Attribution is part of the claim, not a caveat: the normal case is a recommendation drawn from a bracket the player does not play in, so an unattributed figure asserts something other than what was measured. Mechanics need no attribution — they hold at every bracket and patch. Answers should lead with mechanism and follow with evidence.
Confounds
Any new metric introduced here must be compared against a matched baseline. Comparing a filtered sample against an unfiltered one reintroduces confounds that have already produced three false signals during design: item win rate, enemy-networth as a proxy for an enemy being ahead, and item co-occurrence without duration control. Where a filter correlates with match length, the baseline must carry the same filter.
Testing Decisions
Tests assert external behaviour only — what the coach can answer — not internal structure. A normalizer signature or storage shape may change freely provided the tools still answer correctly.
Single seam: the public coach tool functions. This is the highest available seam and the one the agent actually calls. Prior art exists for it, patching the upstream client and building a temporary workspace per test. Sync routines are exercised as setup within these tests rather than as their own assertion target, so ingestion is covered without a second seam.
Directly testing the normalizers was considered and rejected — it duplicates coverage the tool seam already provides and couples tests to warehouse shape.
Cases to cover:
Fixtures should use realistic upstream payload shapes, including the markup and SVG contamination present in real item descriptions.
Out of Scope
Further Notes
The API key matters for v2, not v1. An upstream API key is already read from configuration and sent as a header, but is absent from the example environment file. v1 stays comfortably within anonymous rate limits; the mining pipeline does not. Adding it to the example file is a cheap, useful side task.
Ordering. Mechanics primitives first — that is the actual unblocker, and the hero signature is far less useful without a reason attached. The asset freshness fix belongs alongside it, since the two touch the same data. Hydration backfill must land before post-match review is judged, or it will look weak for reasons unrelated to its design.
Vocabulary. The domain glossary defines the terms used throughout: mechanics, hero signature, pick-share lift, patch window, grounding, confound. Use them rather than synonyms — particularly "pick-share lift" over "win rate delta", which names a rejected approach.
Effect sizes for calibration. Hero signature lifts run large — tens of percentage points over the global average, and every playable hero has a distinctive set. If the implemented signature produces uniformly small lifts, something is wrong with the baseline or denominator rather than with the data.