Capabilities/GlinerCapabilityProbe.cs
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Sandbox;
using Sandbox.Diagnostics;
namespace GlinerPoc.Capabilities;
/// <summary>
/// Phase 0 capability probe. Read-only verification that the APIs the GLiNER
/// runtime will depend on compile and execute under the current s&box whitelist
/// (engine 26.09.15). No model inference happens here.
///
/// Evidence levels produced by this probe:
/// COMPILE+RUNTIME = API executed in play mode with expected result.
/// COMPILE-ONLY = API compiled; execution not exercised.
/// BLOCKED = whitelist rejected the API (see probe history in
/// docs/ai/gliner/CAPABILITIES.md; blocked-API checks are
/// temporary files that are removed after recording).
/// </summary>
[Title( "GLiNER Capability Probe" )]
[Category( "GLiNER" )]
public sealed class GlinerCapabilityProbe : Component
{
[Property]
public bool RunOnStart { get; set; } = true;
private int _checksPassed;
private int _checksFailed;
protected override void OnStart()
{
if ( !RunOnStart )
{
return;
}
_ = RunAsync();
}
private async Task RunAsync()
{
Log.Info( "[GLI:PROBE] capability probe start" );
// Main-thread API checks first (fail fast, deterministic).
Check( "span", () =>
{
Span<float> s = stackalloc float[4];
for ( int i = 0; i < s.Length; i++ ) s[i] = i * 0.5f;
return s[3] == 1.5f;
} );
Check( "bitconverter", () =>
{
byte[] b = BitConverter.GetBytes( 1.0f );
return b.Length == 4 && BitConverter.ToSingle( b, 0 ) == 1.0f;
} );
Check( "sha256_hashdata", () =>
{
byte[] h = SHA256.HashData( Encoding.UTF8.GetBytes( "abc" ) );
return Convert.ToHexString( h ).ToLowerInvariant() ==
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
} );
Check( "mathf_fma", () =>
{
// 2,1,3 -> 2*1+3 = 5
return MathF.FusedMultiplyAdd( 2f, 1f, 3f ) == 5f;
} );
// BLOCKED (SB1000, engine 26.09.15 - recorded in CAPABILITIES.md, probe removed):
// System.Numerics.Vector<T>.get_Count and .IsHardwareAccelerated
// System.Runtime.InteropServices.MemoryMarshal.Cast<TFrom,TTo>(ReadOnlySpan<TFrom>)
// Managed SIMD via System.Numerics.Vector<T> is therefore unavailable under
// the whitelist; P08 may not assume it without its own dedicated probe.
Check( "utf8_encoding", () =>
{
string s = "s\u00e9\u1e57box \u4f60\u597d";
byte[] b = Encoding.UTF8.GetBytes( s );
return Encoding.UTF8.GetString( b ) == s && b.Length > s.Length;
} );
Check( "regex_unicode", () =>
{
var rx = new System.Text.RegularExpressions.Regex( "\\p{Lu}+" );
return rx.Matches( "abcDEFghi" ).Count == 1;
} );
Check( "double_parse_invariant", () =>
{
return double.Parse( "1.5", System.Globalization.CultureInfo.InvariantCulture ) == 1.5;
} );
// Half precision: compile-allowed, but runtime behaviour is suspect
// (passed interpreted, failed DMD-compiled on engine 26.09.15). Log the
// actual conversions; the runtime must not depend on System.Half.
Check( "half_convert", () =>
{
float a = (float)(System.Half)1.5f;
float b = (float)(System.Half)0.5f;
float c = (float)(System.Half)65504f;
Log.Info( $"[GLI:PROBE] half values (Half)1.5f->{a} (Half)0.5f->{b} " +
"(Half)65504f->" + c.ToString( "R" ) );
return a == 1.5f && b == 0.5f && c == 65504f;
} );
// Worker-thread execution: the load-bearing CPU-heavy work path.
int mainThreadId = Environment.CurrentManagedThreadId;
int workerThreadId = -1;
bool workerRan = false;
await Task.RunInThreadAsync( () =>
{
workerThreadId = Environment.CurrentManagedThreadId;
workerRan = true;
} );
Log.Info( $"[GLI:PROBE] task_runinthreadasync ran={workerRan} " +
$"main_thread={mainThreadId} worker_thread={workerThreadId} " +
$"off_main={workerRan && workerThreadId != mainThreadId}" );
if ( workerRan && workerThreadId != mainThreadId ) _checksPassed++;
else { _checksFailed++; Log.Error( "[GLI:PROBE] FAIL task_runinthreadasync" ); }
// Session-scoped worker alternative (no component lifetime required).
int sessionThreadId = -1;
bool sessionRan = false;
await GameTask.RunInThreadAsync( () =>
{
sessionThreadId = Environment.CurrentManagedThreadId;
sessionRan = true;
} );
Log.Info( $"[GLI:PROBE] gametask_runinthreadasync ran={sessionRan} " +
$"main_thread={mainThreadId} worker_thread={sessionThreadId} " +
$"off_main={sessionRan && sessionThreadId != mainThreadId}" );
if ( sessionRan && sessionThreadId != mainThreadId ) _checksPassed++;
else { _checksFailed++; Log.Error( "[GLI:PROBE] FAIL gametask_runinthreadasync" ); }
Log.Info( $"[GLI:PROBE] capability probe complete passed={_checksPassed} " +
$"failed={_checksFailed}" );
}
private void Check( string name, Func<bool> check )
{
try
{
bool ok = check();
if ( ok )
{
_checksPassed++;
Log.Info( $"[GLI:PROBE] PASS {name}" );
}
else
{
_checksFailed++;
Log.Error( $"[GLI:PROBE] FAIL {name}" );
}
}
catch ( Exception e )
{
_checksFailed++;
Log.Error( $"[GLI:PROBE] FAIL {name} exception={e.GetType().Name}: {e.Message}" );
}
}
}