test(runtime): add unattended connected R6 soak

Drive turn, movement, jump, and combat through the production InputDispatcher so connected Release testing works without an interactive Windows desktop. Track held automation actions through normal completion and every shutdown path.

Add a seven-destination ACE route with post-liveness memory, allocation, update, fatal-log, outbound-movement, and graceful-close gates. Record dynamic ACE population changes as context instead of a false lifetime oracle, and document the accepted rebaseline.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-20 12:12:08 +02:00
parent f961d70023
commit a755b764bf
14 changed files with 1021 additions and 20 deletions

View file

@ -38,6 +38,7 @@ public sealed class InputDispatcher
private readonly Stack<InputScope> _scopes = new();
private InputScope? _combatScope;
private readonly HashSet<KeyChord> _heldHoldChords = new();
private readonly HashSet<InputAction> _automationHeldActions = new();
// Double-click detection. _lastMouseDownButton == null means no recent press.
// _lastMouseDownTickMs is Environment.TickCount64 at the time of that press.
@ -72,6 +73,52 @@ public sealed class InputDispatcher
_mouse.Scroll += OnScroll;
}
/// <summary>
/// Diagnostic-only semantic press injection used by the connected retail-UI
/// automation runner. The action enters through the same multicast
/// <see cref="Fired"/> stream as a resolved physical binding, but does not
/// invent a keyboard chord or depend on an interactive Windows desktop.
/// </summary>
/// <returns><see langword="false"/> when modal/text capture owns the
/// keyboard and a physical press would have been suppressed.</returns>
public bool TryInvokeAutomationAction(InputAction action)
{
if (action == InputAction.None || !Enum.IsDefined(action))
throw new ArgumentOutOfRangeException(nameof(action));
if (_captureCallback is not null || _mouse.WantCaptureKeyboard)
return false;
Fired?.Invoke(action, ActivationType.Press);
return true;
}
/// <summary>
/// Diagnostic-only held-action injection. A down edge emits the same
/// <see cref="ActivationType.Press"/> transition as a Hold binding and is
/// visible to <see cref="IsActionHeld"/> until the matching up edge emits
/// <see cref="ActivationType.Release"/>. This keeps unattended connected
/// tests on the production input/movement path without OS-level key
/// synthesis, which Windows drops when no interactive desktop is attached.
/// </summary>
public bool TrySetAutomationActionHeld(InputAction action, bool held)
{
if (action == InputAction.None || !Enum.IsDefined(action))
throw new ArgumentOutOfRangeException(nameof(action));
if (held)
{
if (_captureCallback is not null || _mouse.WantCaptureKeyboard)
return false;
if (_automationHeldActions.Add(action))
Fired?.Invoke(action, ActivationType.Press);
return true;
}
if (_automationHeldActions.Remove(action))
Fired?.Invoke(action, ActivationType.Release);
return true;
}
/// <summary>Topmost scope on the stack — what the dispatcher looks up first.</summary>
public InputScope ActiveScope => _scopes.Peek() == InputScope.Game && _combatScope is { } combat
? combat
@ -177,6 +224,7 @@ public sealed class InputDispatcher
// movement only — latched state that isn't a key (e.g. autorun, ORed into Forward at
// the call site) keeps driving the character, so chat doesn't cancel autorun.
if (_mouse.WantCaptureKeyboard) return false;
if (_automationHeldActions.Contains(action)) return true;
foreach (var b in _bindings.ForAction(action))
{
if (!IsChordHeld(b.Chord)) continue;