Every studio says it uses its own tools. I wanted to find out what that's actually worth, so I took the newest thing we make, the JavaScript SDK, and put it in a football game that has taken over nine hundred commits in six weeks. Then I played it, and I let Ravensight's AI personas play it too.
This is what happened, including the parts that don't flatter Ravensight.
The game
Texas High School Football Dynasty is a program management sim. You take over a real Texas high school, all 1,268 UIL programs are in it, and you run the coaching week: practice plans, depth charts, parent meetings, the inbox, then Friday night. It's a Vue front end over a Node API, and it already sent about thirty events to another analytics service through two thin wrappers, one in the browser and one on the server.
That made it a good test. A management sim has no levels in the platformer sense, no deaths, no boss. If Ravensight's level funnels and insights only make sense for action games, this is where it would show.
Wiring it in
Ravensight went in as a second sink behind the same two wrappers. No existing call site changed. The browser loads the SDK lazily, in its own chunk, only when a key is set. The server keeps one client per active player and retires idle ones.
Three decisions mattered more than the code.
One player, one id. A signed in coach is u_ plus their account id, on the browser and the server alike, so a game result recorded by the API and the screen the coach was looking at land on the same player. Before sign in, the browser uses an anonymous id, and setDeviceId switches it the moment the coach logs in.
The playoffs are the only level. Ravensight reads level starts, completions and deaths from event names. In a football sim, plenty of ordinary events contain "start" or "finish" without meaning anything of the kind. So every event now declares its kind with rs_kind. Making the playoffs is a level start, a playoff loss is a death, a state title is a completion, and season_completed explicitly opts out. A test fails the build if anyone adds an event whose name the substring rules would misread.
Screens are journeys, not levels. Each screen view carries its route name, so the journey graph shows how coaches actually move through the week.
Within a minute of the first local session, the dashboard showed the screens, the weeks advanced, the games simmed, and a brand new event I'd added on the way: action_blocked, which fires whenever the server refuses something the player tried to do.
What playing it found in the game
I played a season with analytics on, the way a new coach would. Three things broke.
One database hiccup took down the whole server. Partway through the season the local database stalled, and the API process exited. The cause was a lock release inside an error handler: when the database timed out, the release threw too, and that second error escaped the request entirely. One slow query should cost one request, not the server. Fixed, with a test that simulates the outage.
The lineup screen said everything was fine while the game refused to play. A starting lineman got hurt in week two. From then on, Friday night answered "your depth chart starts unavailable players," which is correct. But the lineup card on the coach's desk still said every position group was assigned. It checked that each slot had a name, not that the name could play. It now uses the same rule as the server and names the players to move.
action_blocked earned its place on day one. It caught every refused action: advancing the week before playing the game, simming with an injured starter. That's the event that tells you where players hit walls, and it's exactly what a stuck flag can't see in a game with no deaths.
What the AI personas found
Then I ran Ravensight Playtest against the local build. Two personas, a curious kid and a grumpy veteran, two dollars.
The good part first. One persona reported that clicking a school on the "take a program" screen did nothing. On screen it did: a panel slid up with the school's name and a coach picker. But the persona reads the page the way a screen reader does, and nothing in the accessibility tree changed. The cards had no selected state and the panel was never announced. That's a real accessibility bug that I would not have found by looking, and it's fixed now.
The rest of what they filed was either expected, like the sign in check that returns 401 for a logged out visitor, or not reproducible, like a "Start free" link that works every time I click it.
What it found in Ravensight
Here's the part I promised.
The run was too short to reach the game. Each persona ran out of its model budget after about ten actions. A management sim's first screen lists 249 schools, and reading that page eats most of a persona's budget. Neither persona got past picking a school. --max-actions didn't help, and the budget flag was accepted but never applied.
Since then: partly fixed. Playtest 0.2.5 removed the budget flag that did nothing and made the help honest, and it trims what a persona reads: long pages are compacted and an unchanged screen is sent as one line. The budget itself is still set by the server as a fixed share of what the run costs, so it is not yet sized by how heavy your pages are. That part is still open.
The report dropped the personas' own notes. The transcripts held eight notes, bugs and UX observations with severities. The report said zero findings, because runs that hit their budget never promoted notes into findings.
Since then: fixed in playtest 0.2.5 and the matching server release. A run that hits its budget writes a partial report from its notes, and each note arrives as an unreviewed finding.
It charged for a report with nothing in it. The job ended "budget exceeded" and refunded nothing. Our own pricing promise is that work producing nothing usable is refunded. A report with zero findings is nothing usable.
Since then: partly fixed. A run that leaves no report, or one the server refuses, is now refunded in full. A run with an accepted report is still charged once it took five or more actions, even when that report holds no findings. Because notes now become findings, the run in this post would no longer end empty, but the general case is still open.
Persona sessions counted as real players. This is the one I care about most. For Godot builds, the runner passes a playtest token into the game and the SDK tags every event synthetic, so personas stay out of your real numbers. For web builds on ravensight-js, nothing passed that token to the page. The personas' accounts and sessions landed as real players.
Since then: fixed. Playtest 0.2.5 hands the run's identity to the page, ravensight-js 0.3.0 reads it, and the server tags those sessions synthetic, including the few events a page sends before it joins. It needs the game to ship ravensight-js 0.3.0 or later.
The pre-flight check missed the browser. ravensight-playtest check said "Ready," then the first run failed because the test browser wasn't installed. The job was refunded automatically, which is the system working, but the check should have caught it.
Since then: fixed in playtest 0.2.5. check now launches the browser it is about to use, and tells you the install command when it can't.
Smaller things, all fixed since: the level funnel listed every screen as a level with a red "0% complete" (screens you only pass through are now left out and counted); the overview said the latest activity was 21 hours ago when it was minutes (it now reads the latest event); run_sql took game_id while list_games returned gameId (both say game_id now); and the doctor reported "healthy" on an integration it couldn't see, because it only recognised literal rs.track( calls, not a wrapper (it follows wrappers now, and says "inconclusive" when it can't see your tracking).
What changes
In the game, all three fixes are on a branch and covered by tests.
In Ravensight, here is where each one stands:
- Synthetic tagging for web builds, so a persona's session is marked from its
first event. Shipped.
- A per run budget sized by how heavy your pages are. Not yet: the budget is
still a fixed share of the run's price.
- Notes from a run that hit its budget become findings. Shipped. An accepted
report with no findings is refunded. Not yet.
checklaunches the browser it's about to use. Shipped.- The doctor says what it saw, and says "inconclusive" when it saw nothing.
Shipped.
Why publish this
Because the alternative is a launch post that only lists features. A dogfood that finds nothing wrong wasn't a dogfood. This one found a server crash, a screen that contradicted the game, an accessibility gap, and five things in Ravensight I'd rather know about now than hear from a customer.
The game is better for it, and so is Ravensight. Two of these are still open, and the next post will say when they close.