InkkOops

Technical overview

InkkOops is InkkSlinger's in-process runtime automation and diagnostics system. It exists for defects that only show up when the real host app is running: hover transitions, resize sequences, scrolling behavior, focus bugs, retained-render mismatches, dirty-region regressions, and parity issues that do not reproduce in a narrow unit test.

It is not an external driver. It runs inside the app process and works directly against the framework runtime: UiRoot, automation peers, input dispatch, rendering state, diagnostics hooks, and artifact writing.

This documentation set is written as technical documentation. It focuses on architecture, contracts, operational behavior, and debugging workflow.

Reading map

  • Overview: what InkkOops is for and when to prefer it over a smaller test.
  • Architecture and host integration: how the runtime, host profile, policies, and game-host adapter fit together.
  • Selectors, command patterns, and authoring: how to build scripts that are stable and diagnostic-friendly.
  • Runtime, recording, and artifacts: how to launch work and how to inspect what the runtime produced.

What InkkOops is for

Use it for live-runtime bugs

Choose InkkOops when the bug depends on real layout, real rendering, pointer hit-testing, live automation peers, viewport state, or app-host behavior that is difficult to model in a small in-memory test.

Do not overuse it

If the issue can be reproduced by constructing controls directly and asserting on their behavior without launching the full app, a normal xUnit control test is usually simpler and faster.

Core concepts

Host configuration

The app provides an InkkOopsHostConfiguration. That configuration supplies the script catalog, artifact naming policy, replay postamble policy, diagnostics serializer, diagnostics contributors, and default roots such as the pipe name and artifact directories.

Runtime service

InkkOopsRuntimeService coordinates script runs, recording replays, attach-mode requests, and recording startup. It serializes work and produces a single artifact bundle per run.

Host adapter

InkkOopsGameHost adapts the real MonoGame host to the automation runtime. It can resize the window, advance frames, inject pointer input, capture the composite target, and write structured telemetry.

Script model

A script is an InkkOopsScript, usually created through InkkOopsScriptBuilder. In this repository, built-in scripts are exposed through a reflection-backed catalog, but the runtime itself depends only on the catalog abstraction.

Recording model

A recording is a structured log of runtime input activity. Replay turns that log back into a normal InkkOops script and then appends a configurable diagnostics tail.

Execution modes

  • Startup script run. Launch with --inkkoops-script, execute one script, write artifacts, and exit automatically.
  • Startup replay. Launch with --inkkoops-recording, replay one recording, write artifacts, and exit automatically.
  • Attach mode. Submit work to an already-running app through the named pipe. The app stays open after the run.
  • Recording mode. Launch with --inkkoops-record, capture human interaction, and write the recording bundle on normal shutdown.

Selectors and actionability

InkkOops separates target resolution from interaction safety.

  • Resolution prefers x:Name, then automation id, then automation name.
  • Ambiguity is reported as a failure, not silently accepted.
  • WaitForElement means the target resolves.
  • WaitForInteractive means the target can be used safely for pointer interaction.

This distinction matters because a target can exist but still be clipped, offscreen, disabled, or otherwise unsuitable for the action you want to perform.

Pointer actions vs semantic actions

Pointer actions

Use pointer commands for hover bugs, hit-testing bugs, drag behavior, pointer capture, and any scenario where you need the real input path.

Semantic actions

Use semantic commands for stable control-level actions such as invoke, activate, and scroll provider operations when pointer fidelity is not the subject of the test.

Artifacts

Every run writes an artifact bundle. In this repository, the default run root is artifacts/inkkoops and the default recording root is artifacts/inkkoops-recordings.

  • result.json: overall status, command count, failure metadata, duration
  • commands.log: command execution timeline
  • *.png: captured frames
  • *.txt: telemetry dumps

Default host profile in this repository

  • Named pipe: InkkOops
  • Run root: artifacts/inkkoops
  • Recording root: artifacts/inkkoops-recordings
  • Script catalog: reflection-backed built-in scripts from the app assembly
  • Replay postamble: wait for diagnostics stability, capture final frame, dump final telemetry

These are host defaults, not core runtime requirements.

Examples

List scripts:

dotnet run --project InkkOops.Cli/InkkOops.Cli.csproj -- list

Run a startup script:

dotnet run --project InkkSlinger.csproj -- --inkkoops-script "sidebar-button-richtextbox"

Record a session:

dotnet run --project InkkSlinger.csproj -- --inkkoops-record

Replay a recording:

dotnet run --project InkkSlinger.csproj -- --inkkoops-recording ".\artifacts\inkkoops-recordings\20260328-120250760-recorded-session\recording.json"

Recommended workflow

  1. Start with a recording when the bug is hard to reproduce accurately by hand.
  2. Replay it to generate frame and telemetry proof.
  3. Reduce it to a focused built-in script for faster iteration if needed.
  4. Add a lower-level regression test once the root cause is isolated enough to test without the full app host.