using System.Diagnostics;
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
internal static class OriginalDockingResetAcceptance
{
// Fixed-image 12C1040 initializes this original task to 15.0 seconds;
// 2C84660 forwards its update delta to 12BF440, which expires that task.
private static readonly TimeSpan OriginalAtcPendingWindow=TimeSpan.FromSeconds(15);
private static bool OriginalGrantReady(SystemFlightFrame frame,SystemNavigationTarget target,ulong entity,DateTimeOffset requestedAt,DateTimeOffset now,JsonElement? refusal)
{
if(frame.ShipEntity!=entity||frame.SelectedTarget is not {} selected||!target.SameIdentity(selected)||frame.TargetDistance>7500
||frame.ObservedAt>now||now-frame.ObservedAt>TimeSpan.FromMilliseconds(250))throw new InvalidDataException("Original ATC request identity, station or fresh frame changed.");
if(refusal is not null||frame.Clearance is {Permission:DockingPermission.Denied} denied&&denied.MarketId==target.MarketId)throw new InvalidOperationException("The original station refused or cancelled this ATC request.");
if(frame.Clearance is {} permission&&permission.MarketId!=target.MarketId)throw new InvalidDataException("An unrelated station clearance cannot complete this ATC request.");
if(now>=requestedAt+OriginalAtcPendingWindow)throw new TimeoutException("The original fifteen-second ATC request deadline expired; the request will not be replayed.");
return frame.Clearance?.Allows(target,now)==true;
}
internal static async Task RunAsync(int pid,string report,string recoveryPackage,bool requireNonzero=true,long targetMarketId=4210924803,string targetName="Homer Platform",string? sharedStopFile=null,string? protectionWorkRoot=null)
{
if(targetMarketId is <=0 or >uint.MaxValue||string.IsNullOrWhiteSpace(targetName))throw new ArgumentException("One exact station name and original market identity are required.");
report=Path.GetFullPath(report);recoveryPackage=Path.GetFullPath(recoveryPackage);
if(File.Exists(report)||File.Exists(report+".jsonl"))throw new IOException("Use a fresh original-reset report.");
Directory.CreateDirectory(Path.GetDirectoryName(report)!);
FileStream? exclusivity=new(Path.Combine(Path.GetDirectoryName(report)!,"docking-fixture-wait.lock"),FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);
var settings=ToolboxSettings.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"XFEstudio","XFEEDToolBox","settings.json"));
await using var journal=new JournalMonitor(settings.JournalDirectory);await journal.StartAsync();var initial=journal.State;
if(!initial.InGame||initial.Docked||initial.CurrentShipId!=5||initial.CargoCount!=0||initial.CargoCapacity!=192||NavigationSafety.HasExternalThreat(initial)||NavigationSafety.UnhealthyHull(initial))
throw new InvalidOperationException("Healthy empty undocked Corsair/5 required for the bounded normal-space reset test.");
using var process=Process.GetProcessById(pid);var started=process.StartTime.ToUniversalTime().Ticks;
using var guardian=await PersistentProtectionProcess.StartOrReuseAsync(pid,protectionWorkRoot??Path.GetDirectoryName(report)!,CancellationToken.None,allowStart:false);
PersistentProtectionProcess.Current=guardian;FlightTestProtectionScope? protection=null;
var start=DateTimeOffset.UtcNow;var phase="preflight";string? failure=null;var resetZero=false;var meaningfulNonzero=false;var initiallyZero=false;var originalStart=false;var ai=false;var docked=false;var recovered=false;var controlStarted=false;var atcRequestSent=false;DateTimeOffset? grantAt=null,atcRequestAt=null;JsonElement? receipt=null,dockedEvidence=null,inputProvenance=null,publishedBefore=null,atcRefusal=null;
var atcEventLock=new object();
void ObserveAtc(ObservedJournalEvent observed)
{
var value=observed.Data;
if(!value.TryGetProperty("event",out var kind)||kind.GetString() is not("DockingDenied" or "DockingCancelled"))return;
var marketMatches=value.TryGetProperty("MarketID",out var market)&&market.ValueKind==JsonValueKind.Number&&market.TryGetInt64(out var id)&&id==targetMarketId;
var nameMatches=value.TryGetProperty("StationName",out var name)&&name.GetString()==targetName;
lock(atcEventLock)if(atcRequestAt is {} requested&&observed.ObservedAt>=requested&&(marketMatches||nameMatches&&(!value.TryGetProperty("MarketID",out var rawMarket)||rawMarket.ValueKind!=JsonValueKind.Number)))atcRefusal=value.Clone();
}
journal.JournalEvent+=ObserveAtc;
using var timeout=new CancellationTokenSource(TimeSpan.FromMinutes(8));var token=timeout.Token;
await using var log=new StreamWriter(new FileStream(report+".jsonl",FileMode.CreateNew,FileAccess.Write,FileShare.Read));
async Task Log(object value){await log.WriteLineAsync(JsonSerializer.Serialize(value,ToolboxSettings.JsonOptions));await log.FlushAsync();}
async Task Save()
{
var temp=report+".tmp";
await File.WriteAllTextAsync(temp,JsonSerializer.Serialize(new{passed=resetZero&&ai&&docked&&(requireNonzero?meaningfulNonzero:originalStart&&initiallyZero)&&failure is null,pid,started,start,finishedAt=DateTimeOffset.UtcNow,phase,
validationKind=requireNonzero?"nonzero-reset-and-docking":"original-start-with-confirmed-zero",requireNonzero,initiallyZero,originalDockingStartCalled=originalStart,
station=targetName,marketId=targetMarketId,meaningfulNonzero,nonzeroReproduction=meaningfulNonzero,originalResetZero=meaningfulNonzero&&resetZero,fourSourcesZeroConfirmed=resetZero,aiEngaged=ai,actualDocked=docked,grantAt,atcRequestSent,atcRequestAt,atcDeadline=atcRequestAt+OriginalAtcPendingWindow,atcRefusal,receipt,dockedEvidence,inputProvenance,publishedBefore,recoveredViaOriginalMenu=recovered,
persistent075=false,persistent075Acceptance=false,supercruiseUsed=false,gameSupercruiseAssistUsed=false,tradeOrdersSent=0,clientTerminated=false,failure},ToolboxSettings.JsonOptions));File.Move(temp,report,true);
}
void CheckSession()
{
process.Refresh();var current=journal.State;
if(File.Exists(sharedStopFile??report+".stop"))throw new OperationCanceledException("Original reset diagnostic explicitly stopped.");
if(process.HasExited||process.StartTime.ToUniversalTime().Ticks!=started||!current.InGame||current.CommanderId!=initial.CommanderId||current.CurrentShipId!=5||current.CargoCount!=0||current.CargoCapacity!=192||current.LoadGameAt!=initial.LoadGameAt
||NavigationSafety.HasExternalThreat(current)||NavigationSafety.UnhealthyHull(current))throw new InvalidOperationException("Reset diagnostic session, ship or safety identity changed.");
guardian.RequireReady(pid);
}
var driver=new NativeSystemFlightControlDriver(pid,NativeSystemLocationReader.GameSha256,()=>journal.State,
new NativeGameInputChannel(pid,NativeSystemLocationReader.GameSha256,Path.Combine(AppContext.BaseDirectory,"PluginPackage")),t=>{t.ThrowIfCancellationRequested();CheckSession();NativeFlightTestProtection.CheckBeforeInput(pid);return Task.CompletedTask;},useNativeSupercruiseAssist:false);
try
{
protection=await FlightTestProtectionScope.ArmAsync(pid,exitForFailedHandoff:false);
await driver.EnableOriginalDockingResetTestAsync(startDockingAfterZero:true,token);
inputProvenance=JsonSerializer.SerializeToElement(await NativeDockingInputDiagnostics.ReadForStationAsync(pid,targetMarketId,token));
var mainNode=inputProvenance.Value.GetProperty("graph").GetProperty("matches").EnumerateArray().Single(x=>x.GetProperty("registryMatches").GetBoolean()&&x.GetProperty("outputMatches").GetBoolean());
var node=mainNode.GetProperty("node").GetString()!;var output=mainNode.GetProperty("output").GetString()!;var registry=mainNode.GetProperty("registry").GetString()!;
if(inputProvenance.Value.GetProperty("entity").GetString() is not {Length:>0})throw new InvalidDataException("Original source owner is not verified.");
static bool Zero(double value)=>double.IsFinite(value)&&Math.Abs(value)<=.001;
initiallyZero=Zero(mainNode.GetProperty("accumulator").GetDouble())&&Zero(inputProvenance.Value.GetProperty("dockingThrottle").GetDouble())
&&Zero(inputProvenance.Value.GetProperty("actualThrottle").GetDouble())
&&(Zero(inputProvenance.Value.GetProperty("controllerThrottle").GetDouble())||inputProvenance.Value.GetProperty("controllerThrottle").GetDouble()==-100);
if(!requireNonzero&&!initiallyZero)throw new InvalidDataException("The separate original AI start test requires an already confirmed zero source; it cannot stand in for a nonzero reset reproduction.");
using var source=new NativeCurrentSystemSource(pid,NativeSystemLocationReader.GameSha256,()=>journal.State);
var catalogue=await source.ReadLocationsAsync(token);var row=catalogue.Locations.Single(x=>x.MarketId==targetMarketId&&x.Name==targetName);
var target=new SystemNavigationTarget(catalogue.SystemAddress,row.WorldAddress,row.Name,SystemTargetKind.Station,row.MarketId){NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity};
await driver.SelectAsync(target,token);await driver.PrepareAsync(token);phase="normal-space-approach";Console.WriteLine(phase);
async Task<SystemFlightFrame> Read()
{
var unavailableUntil=DateTimeOffset.UtcNow.AddSeconds(3);
while(true)
{
token.ThrowIfCancellationRequested();CheckSession();
if(grantAt is {} granted&&!ai&&DateTimeOffset.UtcNow-granted>TimeSpan.FromSeconds(2))throw new InvalidOperationException("Original AI takeover was not confirmed inside two seconds.");
if(DateTimeOffset.UtcNow>unavailableUntil)throw new FlightTelemetryUnavailableException("Original normal-space telemetry remained unavailable for three seconds.");
try
{
var frame=await driver.ReadSystemFlightAsync(token);
if(frame.Mode is not(LocalFlightMode.Normal or LocalFlightMode.Docked)||frame.PlayerOverride||frame.ExternalThreat||frame.SupercruiseAssist==NativeAssistState.Engaged||(frame.HeatPercent??100)>=75)
throw new InvalidOperationException("Bounded normal-space reset safety condition failed.");
return frame;
}
catch(Exception error)when(NavigationRecovery.CanRetry(error,token)){await Task.Delay(40,token);}
}
}
while(true)
{
var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});
if(frame.TargetDistance<=7000)break;
var aim=(frame.TargetPosition-frame.Position).Unit();var throttle=Vector3d.AngleDegrees(frame.Forward,aim)<=7?.6:0;
controlStarted=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.NormalApproach,phase,aim,throttle),frame,target,frame.ObservedAt.AddMilliseconds(250),token);
await Task.Delay(60,token);
}
phase="original-atc";Console.WriteLine(phase);
var atcFrame=await Read();
var atcEntity=ulong.Parse(inputProvenance.Value.GetProperty("entity").GetString()!);
if(atcFrame.ShipEntity!=atcEntity)throw new InvalidDataException("Original main ship changed before the ATC request.");
lock(atcEventLock)atcRequestAt=atcFrame.ObservedAt;
if(atcFrame.Clearance?.Allows(target,DateTimeOffset.UtcNow)!=true)
{controlStarted=true;atcRequestSent=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.RequestingDocking,phase,null,null,SystemNavigationAction.RequestDocking|SystemNavigationAction.ReleaseFlightAxes),atcFrame,target,atcFrame.ObservedAt.AddMilliseconds(250),token);}
await Log(new{at=DateTimeOffset.UtcNow,phase,atcRequestSent,sourceSequence=atcFrame.Sequence,entity=atcEntity,target,atcRequestAt,atcDeadline=atcRequestAt+OriginalAtcPendingWindow,originalTaskWindowSeconds=OriginalAtcPendingWindow.TotalSeconds,requestReplayed=false});
while(true)
{
var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});
JsonElement? refusal;lock(atcEventLock)refusal=atcRefusal;
if(OriginalGrantReady(frame,target,atcEntity,atcRequestAt.Value,DateTimeOffset.UtcNow,refusal))
{
grantAt=(frame.Clearance??throw new InvalidDataException("Original ATC grant disappeared.")).ObservedAt;phase="original-reset-and-ai";Console.WriteLine(phase);
var observer=await new NavigationPipeClient(pid,NativeSystemFlightControlDriver.OriginalDockingService).CallAsync(new{op="read"},token);
publishedBefore=observer.GetProperty("mapperNodes").EnumerateArray().Single(x=>x.GetProperty("node").GetString()==node&&x.GetProperty("source").GetString()==output&&x.GetProperty("registry").GetString()==registry).Clone();
if(ulong.Parse(inputProvenance.Value.GetProperty("entity").GetString()!)!=frame.ShipEntity)throw new InvalidDataException("Original mapper owner changed before reset.");
controlStarted=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.NativeLanding,phase,null,null,SystemNavigationAction.EnableDockingAssist|SystemNavigationAction.ReleaseFlightAxes),frame,target,frame.ObservedAt.AddMilliseconds(250),token);
receipt=driver.LastOriginalDockingResetReceipt;
originalStart=receipt is {} startedDocking&&startedDocking.TryGetProperty("originalDockingStartCalled",out var called)&&called.ValueKind==JsonValueKind.True;
resetZero=receipt is {} verified&&DockingValidationProof.OriginalResetZero(verified,frame.ShipEntity,target.MarketId!.Value,frame.ObservedAt,DateTimeOffset.UtcNow);
meaningfulNonzero=receipt is {} nonzero&&DockingValidationProof.OriginalResetZero(nonzero,frame.ShipEntity,target.MarketId!.Value,frame.ObservedAt,DateTimeOffset.UtcNow,requireNonzeroBefore:true)
&&DockingValidationProof.PriorPublishedResetSource(nonzero,publishedBefore.Value,node,output,registry);
await Log(new{at=DateTimeOffset.UtcNow,phase,resetZero,meaningfulNonzero,receipt});break;
}
await Task.Delay(25,token);
}
while(true)
{
var frame=await Read();ai=frame.DockingAssist==NativeAssistState.Engaged;await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry,receipt});
if(resetZero&&ai)break;
if(DateTimeOffset.UtcNow-grantAt>TimeSpan.FromSeconds(2))throw new InvalidOperationException("Original source reset and real AI takeover were not confirmed inside two seconds.");
await Task.Delay(25,token);
}
phase="native-ai-docking";Console.WriteLine(phase);var dockLimit=DateTimeOffset.UtcNow.AddMinutes(5);
while(true)
{
token.ThrowIfCancellationRequested();CheckSession();
if(journal.State.Docked&&journal.State.MarketId==target.MarketId)
{
dockedEvidence=await new NavigationPipeClient(pid).CallAsync(new{op="commerce.docked.status",marketId=target.MarketId},token);
await Log(new{at=DateTimeOffset.UtcNow,phase,dockedEvidence});
var actual=dockedEvidence.Value.GetProperty("actualMarketId").GetInt64();
if(actual!=0&&actual!=target.MarketId)throw new InvalidDataException("Original docked market differs from the selected station.");
if(dockedEvidence.Value.GetProperty("ready").GetBoolean()&&actual==target.MarketId){docked=true;break;}
}
else{var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});}
if(DateTimeOffset.UtcNow>dockLimit)throw new TimeoutException("Original AI has not confirmed actual docking.");await Task.Delay(100,token);
}
if(!docked||(requireNonzero?!meaningfulNonzero:!originalStart))throw new InvalidDataException("Actual docking/source or original start evidence is incomplete; an initially zero source is not a reset reproduction.");
phase=requireNonzero?"passed-nonzero-reset-selected-station":"passed-original-ai-docking-selected-station";
}
catch(Exception error)
{
failure=error.ToString();Console.WriteLine(error.Message);await Log(new{at=DateTimeOffset.UtcNow,phase,failure});
try{await driver.ReleaseSystemFlightAsync();}catch(Exception release){await Log(new{releaseFailure=release.ToString()});}
receipt??=driver.LastOriginalDockingResetReceipt;await Save();
if(protection is not null){await protection.DisposeAsync();protection=null;}
exclusivity?.Dispose();exclusivity=null;
if(controlStarted&&!File.Exists(sharedStopFile??report+".stop")&&!journal.State.Docked&&!process.HasExited&&journal.State.CurrentShipId==5&&journal.State.CargoCount==0)
{
try
{
phase="same-process-original-menu-recovery";await EnterPauseAsync(pid,guardian,report+".pause.json");
await SessionRecoveryAcceptance.RunAsync(pid,recoveryPackage,report+".menu-recovery.json",leave:true,protectionWorkRoot:protectionWorkRoot);
await GameSessionAcceptance.StartAsync(settings.PluginGameExecutable,report+".solo-reentry.json",pid);
recovered=journal.State.InGame&&journal.State.LoadGameAt>initial.LoadGameAt&&journal.State.CurrentShipId==5&&journal.State.CargoCount==0;
}
catch(Exception recovery){await Log(new{recoveryFailure=recovery.ToString(),clientTerminated=false});}
}
}
finally
{
journal.JournalEvent-=ObserveAtc;
try{await driver.ReleaseSystemFlightAsync();}catch(Exception release){await Log(new{finalReleaseFailure=release.ToString()});}
if(protection is not null)await protection.DisposeAsync();exclusivity?.Dispose();PersistentProtectionProcess.Current=null;await Save();
}
if(failure is not null)throw new InvalidOperationException("Original reset diagnostic did not pass; original failure was preserved.");
}
internal static int SelfTestAtcWait()
{
var at=DateTimeOffset.FromUnixTimeSeconds(1700000000);var target=new SystemNavigationTarget(1,2,"Original station",SystemTargetKind.Station,7);const ulong entity=42;
SystemFlightFrame Frame(double seconds,DockingClearance? permission=null,ulong ship=entity)=>new(){ObservedAt=at.AddSeconds(seconds),ShipEntity=ship,SelectedTarget=target,TargetDistance=6400,Clearance=permission};
DockingClearance Grant(double seconds,long market=7)=>new(market,DockingPermission.Granted,5,at.AddSeconds(seconds),at.AddSeconds(seconds+1));
bool Refused(Action action){try{action();return false;}catch(Exception error)when(error is InvalidOperationException or InvalidDataException or TimeoutException){return true;}}
var refusal=JsonSerializer.SerializeToElement(new{ @event="DockingDenied",MarketID=7,StationName="Original station",Reason="NoSpace"});
var checks=new[]{!OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6),null),OriginalGrantReady(Frame(6,Grant(6)),target,entity,at,at.AddSeconds(6),null),
Refused(()=>OriginalGrantReady(Frame(15),target,entity,at,at.AddSeconds(15),null)),Refused(()=>OriginalGrantReady(Frame(6,Grant(6,8)),target,entity,at,at.AddSeconds(6),null)),
Refused(()=>OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6),refusal)),Refused(()=>OriginalGrantReady(Frame(6,ship:43),target,entity,at,at.AddSeconds(6),null)),
Refused(()=>OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6).AddMilliseconds(251),null))};
if(checks.Any(value=>!value))throw new InvalidDataException("Original ATC task-window, late-grant or refusal/identity regression failed.");return checks.Length;
}
internal static async Task EnterPauseAsync(int pid,PersistentProtectionProcess guardian,string report)
{
var channel=new NativeRelogChannel(pid,NativeRelogChannel.SupportedGameSha256,t=>{t.ThrowIfCancellationRequested();guardian.RequireReady(pid);return Task.CompletedTask;},returnToMenuTrial:true);
var owner=Guid.NewGuid().ToString("N");var request=Guid.NewGuid().ToString("N");var submitted=false;var paused=false;string? failure=null;
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(8));
try
{
await channel.BeginAsync(owner,stop.Token);
while(true)
{
var frame=await channel.ReadAsync(owner,stop.Token);
if(frame.Stable&&frame.State=="Pause"){paused=true;break;}
if(frame.Stable&&frame.State=="MainMenu"){paused=true;break;}
if(!submitted&&frame.Stable&&frame.State=="InGame")
{
submitted=true;
try{await channel.SubmitAsync(owner,request,frame,"@pause",stop.Token);}catch(Exception error)when(error is IOException or OperationCanceledException&&!stop.IsCancellationRequested){}
}
await Task.Delay(40,stop.Token);
}
}
catch(Exception error){failure=error.ToString();throw;}
finally{await channel.EndAsync(owner);await File.WriteAllTextAsync(report,JsonSerializer.Serialize(new{pid,paused,submitted,request,failure,clientTerminated=false},ToolboxSettings.JsonOptions));}
}
}
using System.Diagnostics;
using System.Text.Json;
using XFEEDToolBox.Core.Data;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Session;
internal static class OriginalDockingResetAcceptance
{
// Fixed-image 12C1040 initializes this original task to 15.0 seconds;
// 2C84660 forwards its update delta to 12BF440, which expires that task.
private static readonly TimeSpan OriginalAtcPendingWindow=TimeSpan.FromSeconds(15);
private static bool OriginalGrantReady(SystemFlightFrame frame,SystemNavigationTarget target,ulong entity,DateTimeOffset requestedAt,DateTimeOffset now,JsonElement? refusal)
{
if(frame.ShipEntity!=entity||frame.SelectedTarget is not {} selected||!target.SameIdentity(selected)||frame.TargetDistance>7500
||frame.ObservedAt>now||now-frame.ObservedAt>TimeSpan.FromMilliseconds(250))throw new InvalidDataException("Original ATC request identity, station or fresh frame changed.");
if(refusal is not null||frame.Clearance is {Permission:DockingPermission.Denied} denied&&denied.MarketId==target.MarketId)throw new InvalidOperationException("The original station refused or cancelled this ATC request.");
if(frame.Clearance is {} permission&&permission.MarketId!=target.MarketId)throw new InvalidDataException("An unrelated station clearance cannot complete this ATC request.");
if(now>=requestedAt+OriginalAtcPendingWindow)throw new TimeoutException("The original fifteen-second ATC request deadline expired; the request will not be replayed.");
return frame.Clearance?.Allows(target,now)==true;
}
internal static async Task RunAsync(int pid,string report,string recoveryPackage,bool requireNonzero=true,long targetMarketId=4210924803,string targetName="Homer Platform",string? sharedStopFile=null,string? protectionWorkRoot=null)
{
if(targetMarketId is <=0 or >uint.MaxValue||string.IsNullOrWhiteSpace(targetName))throw new ArgumentException("One exact station name and original market identity are required.");
report=Path.GetFullPath(report);recoveryPackage=Path.GetFullPath(recoveryPackage);
if(File.Exists(report)||File.Exists(report+".jsonl"))throw new IOException("Use a fresh original-reset report.");
Directory.CreateDirectory(Path.GetDirectoryName(report)!);
FileStream? exclusivity=new(Path.Combine(Path.GetDirectoryName(report)!,"docking-fixture-wait.lock"),FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);
var settings=ToolboxSettings.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),"XFEstudio","XFEEDToolBox","settings.json"));
await using var journal=new JournalMonitor(settings.JournalDirectory);await journal.StartAsync();var initial=journal.State;
if(!initial.InGame||initial.Docked||initial.CurrentShipId!=5||initial.CargoCount!=0||initial.CargoCapacity!=192||NavigationSafety.HasExternalThreat(initial)||NavigationSafety.UnhealthyHull(initial))
throw new InvalidOperationException("Healthy empty undocked Corsair/5 required for the bounded normal-space reset test.");
using var process=Process.GetProcessById(pid);var started=process.StartTime.ToUniversalTime().Ticks;
using var guardian=await PersistentProtectionProcess.StartOrReuseAsync(pid,protectionWorkRoot??Path.GetDirectoryName(report)!,CancellationToken.None,allowStart:false);
PersistentProtectionProcess.Current=guardian;FlightTestProtectionScope? protection=null;
var start=DateTimeOffset.UtcNow;var phase="preflight";string? failure=null;var resetZero=false;var meaningfulNonzero=false;var initiallyZero=false;var originalStart=false;var ai=false;var docked=false;var recovered=false;var controlStarted=false;var atcRequestSent=false;DateTimeOffset? grantAt=null,atcRequestAt=null;JsonElement? receipt=null,dockedEvidence=null,inputProvenance=null,publishedBefore=null,atcRefusal=null;
var atcEventLock=new object();
void ObserveAtc(ObservedJournalEvent observed)
{
var value=observed.Data;
if(!value.TryGetProperty("event",out var kind)||kind.GetString() is not("DockingDenied" or "DockingCancelled"))return;
var marketMatches=value.TryGetProperty("MarketID",out var market)&&market.ValueKind==JsonValueKind.Number&&market.TryGetInt64(out var id)&&id==targetMarketId;
var nameMatches=value.TryGetProperty("StationName",out var name)&&name.GetString()==targetName;
lock(atcEventLock)if(atcRequestAt is {} requested&&observed.ObservedAt>=requested&&(marketMatches||nameMatches&&(!value.TryGetProperty("MarketID",out var rawMarket)||rawMarket.ValueKind!=JsonValueKind.Number)))atcRefusal=value.Clone();
}
journal.JournalEvent+=ObserveAtc;
using var timeout=new CancellationTokenSource(TimeSpan.FromMinutes(8));var token=timeout.Token;
await using var log=new StreamWriter(new FileStream(report+".jsonl",FileMode.CreateNew,FileAccess.Write,FileShare.Read));
async Task Log(object value){await log.WriteLineAsync(JsonSerializer.Serialize(value,ToolboxSettings.JsonOptions));await log.FlushAsync();}
async Task Save()
{
var temp=report+".tmp";
await File.WriteAllTextAsync(temp,JsonSerializer.Serialize(new{passed=resetZero&&ai&&docked&&(requireNonzero?meaningfulNonzero:originalStart&&initiallyZero)&&failure is null,pid,started,start,finishedAt=DateTimeOffset.UtcNow,phase,
validationKind=requireNonzero?"nonzero-reset-and-docking":"original-start-with-confirmed-zero",requireNonzero,initiallyZero,originalDockingStartCalled=originalStart,
station=targetName,marketId=targetMarketId,meaningfulNonzero,nonzeroReproduction=meaningfulNonzero,originalResetZero=meaningfulNonzero&&resetZero,fourSourcesZeroConfirmed=resetZero,aiEngaged=ai,actualDocked=docked,grantAt,atcRequestSent,atcRequestAt,atcDeadline=atcRequestAt+OriginalAtcPendingWindow,atcRefusal,receipt,dockedEvidence,inputProvenance,publishedBefore,recoveredViaOriginalMenu=recovered,
persistent075=false,persistent075Acceptance=false,supercruiseUsed=false,gameSupercruiseAssistUsed=false,tradeOrdersSent=0,clientTerminated=false,failure},ToolboxSettings.JsonOptions));File.Move(temp,report,true);
}
void CheckSession()
{
process.Refresh();var current=journal.State;
if(File.Exists(sharedStopFile??report+".stop"))throw new OperationCanceledException("Original reset diagnostic explicitly stopped.");
if(process.HasExited||process.StartTime.ToUniversalTime().Ticks!=started||!current.InGame||current.CommanderId!=initial.CommanderId||current.CurrentShipId!=5||current.CargoCount!=0||current.CargoCapacity!=192||current.LoadGameAt!=initial.LoadGameAt
||NavigationSafety.HasExternalThreat(current)||NavigationSafety.UnhealthyHull(current))throw new InvalidOperationException("Reset diagnostic session, ship or safety identity changed.");
guardian.RequireReady(pid);
}
var driver=new NativeSystemFlightControlDriver(pid,NativeSystemLocationReader.GameSha256,()=>journal.State,
new NativeGameInputChannel(pid,NativeSystemLocationReader.GameSha256,Path.Combine(AppContext.BaseDirectory,"PluginPackage")),t=>{t.ThrowIfCancellationRequested();CheckSession();NativeFlightTestProtection.CheckBeforeInput(pid);return Task.CompletedTask;},useNativeSupercruiseAssist:false);
try
{
protection=await FlightTestProtectionScope.ArmAsync(pid,exitForFailedHandoff:false);
await driver.EnableOriginalDockingResetTestAsync(startDockingAfterZero:true,token);
inputProvenance=JsonSerializer.SerializeToElement(await NativeDockingInputDiagnostics.ReadForStationAsync(pid,targetMarketId,token));
var mainNode=inputProvenance.Value.GetProperty("graph").GetProperty("matches").EnumerateArray().Single(x=>x.GetProperty("registryMatches").GetBoolean()&&x.GetProperty("outputMatches").GetBoolean());
var node=mainNode.GetProperty("node").GetString()!;var output=mainNode.GetProperty("output").GetString()!;var registry=mainNode.GetProperty("registry").GetString()!;
if(inputProvenance.Value.GetProperty("entity").GetString() is not {Length:>0})throw new InvalidDataException("Original source owner is not verified.");
static bool Zero(double value)=>double.IsFinite(value)&&Math.Abs(value)<=.001;
initiallyZero=Zero(mainNode.GetProperty("accumulator").GetDouble())&&Zero(inputProvenance.Value.GetProperty("dockingThrottle").GetDouble())
&&Zero(inputProvenance.Value.GetProperty("actualThrottle").GetDouble())
&&(Zero(inputProvenance.Value.GetProperty("controllerThrottle").GetDouble())||inputProvenance.Value.GetProperty("controllerThrottle").GetDouble()==-100);
if(!requireNonzero&&!initiallyZero)throw new InvalidDataException("The separate original AI start test requires an already confirmed zero source; it cannot stand in for a nonzero reset reproduction.");
using var source=new NativeCurrentSystemSource(pid,NativeSystemLocationReader.GameSha256,()=>journal.State);
var catalogue=await source.ReadLocationsAsync(token);var row=catalogue.Locations.Single(x=>x.MarketId==targetMarketId&&x.Name==targetName);
var target=new SystemNavigationTarget(catalogue.SystemAddress,row.WorldAddress,row.Name,SystemTargetKind.Station,row.MarketId){NativeKey=row.Key,NativeKind=row.NativeKind,NativeIdentity=row.Identity};
await driver.SelectAsync(target,token);await driver.PrepareAsync(token);phase="normal-space-approach";Console.WriteLine(phase);
async Task<SystemFlightFrame> Read()
{
var unavailableUntil=DateTimeOffset.UtcNow.AddSeconds(3);
while(true)
{
token.ThrowIfCancellationRequested();CheckSession();
if(grantAt is {} granted&&!ai&&DateTimeOffset.UtcNow-granted>TimeSpan.FromSeconds(2))throw new InvalidOperationException("Original AI takeover was not confirmed inside two seconds.");
if(DateTimeOffset.UtcNow>unavailableUntil)throw new FlightTelemetryUnavailableException("Original normal-space telemetry remained unavailable for three seconds.");
try
{
var frame=await driver.ReadSystemFlightAsync(token);
if(frame.Mode is not(LocalFlightMode.Normal or LocalFlightMode.Docked)||frame.PlayerOverride||frame.ExternalThreat||frame.SupercruiseAssist==NativeAssistState.Engaged||(frame.HeatPercent??100)>=75)
throw new InvalidOperationException("Bounded normal-space reset safety condition failed.");
return frame;
}
catch(Exception error)when(NavigationRecovery.CanRetry(error,token)){await Task.Delay(40,token);}
}
}
while(true)
{
var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});
if(frame.TargetDistance<=7000)break;
var aim=(frame.TargetPosition-frame.Position).Unit();var throttle=Vector3d.AngleDegrees(frame.Forward,aim)<=7?.6:0;
controlStarted=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.NormalApproach,phase,aim,throttle),frame,target,frame.ObservedAt.AddMilliseconds(250),token);
await Task.Delay(60,token);
}
phase="original-atc";Console.WriteLine(phase);
var atcFrame=await Read();
var atcEntity=ulong.Parse(inputProvenance.Value.GetProperty("entity").GetString()!);
if(atcFrame.ShipEntity!=atcEntity)throw new InvalidDataException("Original main ship changed before the ATC request.");
lock(atcEventLock)atcRequestAt=atcFrame.ObservedAt;
if(atcFrame.Clearance?.Allows(target,DateTimeOffset.UtcNow)!=true)
{controlStarted=true;atcRequestSent=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.RequestingDocking,phase,null,null,SystemNavigationAction.RequestDocking|SystemNavigationAction.ReleaseFlightAxes),atcFrame,target,atcFrame.ObservedAt.AddMilliseconds(250),token);}
await Log(new{at=DateTimeOffset.UtcNow,phase,atcRequestSent,sourceSequence=atcFrame.Sequence,entity=atcEntity,target,atcRequestAt,atcDeadline=atcRequestAt+OriginalAtcPendingWindow,originalTaskWindowSeconds=OriginalAtcPendingWindow.TotalSeconds,requestReplayed=false});
while(true)
{
var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});
JsonElement? refusal;lock(atcEventLock)refusal=atcRefusal;
if(OriginalGrantReady(frame,target,atcEntity,atcRequestAt.Value,DateTimeOffset.UtcNow,refusal))
{
grantAt=(frame.Clearance??throw new InvalidDataException("Original ATC grant disappeared.")).ObservedAt;phase="original-reset-and-ai";Console.WriteLine(phase);
var observer=await new NavigationPipeClient(pid,NativeSystemFlightControlDriver.OriginalDockingService).CallAsync(new{op="read"},token);
publishedBefore=observer.GetProperty("mapperNodes").EnumerateArray().Single(x=>x.GetProperty("node").GetString()==node&&x.GetProperty("source").GetString()==output&&x.GetProperty("registry").GetString()==registry).Clone();
if(ulong.Parse(inputProvenance.Value.GetProperty("entity").GetString()!)!=frame.ShipEntity)throw new InvalidDataException("Original mapper owner changed before reset.");
controlStarted=true;await driver.ApplySystemFlightAsync(new(SystemNavigationPhase.NativeLanding,phase,null,null,SystemNavigationAction.EnableDockingAssist|SystemNavigationAction.ReleaseFlightAxes),frame,target,frame.ObservedAt.AddMilliseconds(250),token);
receipt=driver.LastOriginalDockingResetReceipt;
originalStart=receipt is {} startedDocking&&startedDocking.TryGetProperty("originalDockingStartCalled",out var called)&&called.ValueKind==JsonValueKind.True;
resetZero=receipt is {} verified&&DockingValidationProof.OriginalResetZero(verified,frame.ShipEntity,target.MarketId!.Value,frame.ObservedAt,DateTimeOffset.UtcNow);
meaningfulNonzero=receipt is {} nonzero&&DockingValidationProof.OriginalResetZero(nonzero,frame.ShipEntity,target.MarketId!.Value,frame.ObservedAt,DateTimeOffset.UtcNow,requireNonzeroBefore:true)
&&DockingValidationProof.PriorPublishedResetSource(nonzero,publishedBefore.Value,node,output,registry);
await Log(new{at=DateTimeOffset.UtcNow,phase,resetZero,meaningfulNonzero,receipt});break;
}
await Task.Delay(25,token);
}
while(true)
{
var frame=await Read();ai=frame.DockingAssist==NativeAssistState.Engaged;await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry,receipt});
if(resetZero&&ai)break;
if(DateTimeOffset.UtcNow-grantAt>TimeSpan.FromSeconds(2))throw new InvalidOperationException("Original source reset and real AI takeover were not confirmed inside two seconds.");
await Task.Delay(25,token);
}
phase="native-ai-docking";Console.WriteLine(phase);var dockLimit=DateTimeOffset.UtcNow.AddMinutes(5);
while(true)
{
token.ThrowIfCancellationRequested();CheckSession();
if(journal.State.Docked&&journal.State.MarketId==target.MarketId)
{
dockedEvidence=await new NavigationPipeClient(pid).CallAsync(new{op="commerce.docked.status",marketId=target.MarketId},token);
await Log(new{at=DateTimeOffset.UtcNow,phase,dockedEvidence});
var actual=dockedEvidence.Value.GetProperty("actualMarketId").GetInt64();
if(actual!=0&&actual!=target.MarketId)throw new InvalidDataException("Original docked market differs from the selected station.");
if(dockedEvidence.Value.GetProperty("ready").GetBoolean()&&actual==target.MarketId){docked=true;break;}
}
else{var frame=await Read();await Log(new{at=DateTimeOffset.UtcNow,phase,frame,local=driver.LastTelemetry});}
if(DateTimeOffset.UtcNow>dockLimit)throw new TimeoutException("Original AI has not confirmed actual docking.");await Task.Delay(100,token);
}
if(!docked||(requireNonzero?!meaningfulNonzero:!originalStart))throw new InvalidDataException("Actual docking/source or original start evidence is incomplete; an initially zero source is not a reset reproduction.");
phase=requireNonzero?"passed-nonzero-reset-selected-station":"passed-original-ai-docking-selected-station";
}
catch(Exception error)
{
failure=error.ToString();Console.WriteLine(error.Message);await Log(new{at=DateTimeOffset.UtcNow,phase,failure});
try{await driver.ReleaseSystemFlightAsync();}catch(Exception release){await Log(new{releaseFailure=release.ToString()});}
receipt??=driver.LastOriginalDockingResetReceipt;await Save();
if(protection is not null){await protection.DisposeAsync();protection=null;}
exclusivity?.Dispose();exclusivity=null;
if(controlStarted&&!File.Exists(sharedStopFile??report+".stop")&&!journal.State.Docked&&!process.HasExited&&journal.State.CurrentShipId==5&&journal.State.CargoCount==0)
{
try
{
phase="same-process-original-menu-recovery";await EnterPauseAsync(pid,guardian,report+".pause.json");
await SessionRecoveryAcceptance.RunAsync(pid,recoveryPackage,report+".menu-recovery.json",leave:true,protectionWorkRoot:protectionWorkRoot);
await GameSessionAcceptance.StartAsync(settings.PluginGameExecutable,report+".solo-reentry.json",pid);
recovered=journal.State.InGame&&journal.State.LoadGameAt>initial.LoadGameAt&&journal.State.CurrentShipId==5&&journal.State.CargoCount==0;
}
catch(Exception recovery){await Log(new{recoveryFailure=recovery.ToString(),clientTerminated=false});}
}
}
finally
{
journal.JournalEvent-=ObserveAtc;
try{await driver.ReleaseSystemFlightAsync();}catch(Exception release){await Log(new{finalReleaseFailure=release.ToString()});}
if(protection is not null)await protection.DisposeAsync();exclusivity?.Dispose();PersistentProtectionProcess.Current=null;await Save();
}
if(failure is not null)throw new InvalidOperationException("Original reset diagnostic did not pass; original failure was preserved.");
}
internal static int SelfTestAtcWait()
{
var at=DateTimeOffset.FromUnixTimeSeconds(1700000000);var target=new SystemNavigationTarget(1,2,"Original station",SystemTargetKind.Station,7);const ulong entity=42;
SystemFlightFrame Frame(double seconds,DockingClearance? permission=null,ulong ship=entity)=>new(){ObservedAt=at.AddSeconds(seconds),ShipEntity=ship,SelectedTarget=target,TargetDistance=6400,Clearance=permission};
DockingClearance Grant(double seconds,long market=7)=>new(market,DockingPermission.Granted,5,at.AddSeconds(seconds),at.AddSeconds(seconds+1));
bool Refused(Action action){try{action();return false;}catch(Exception error)when(error is InvalidOperationException or InvalidDataException or TimeoutException){return true;}}
var refusal=JsonSerializer.SerializeToElement(new{ @event="DockingDenied",MarketID=7,StationName="Original station",Reason="NoSpace"});
var checks=new[]{!OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6),null),OriginalGrantReady(Frame(6,Grant(6)),target,entity,at,at.AddSeconds(6),null),
Refused(()=>OriginalGrantReady(Frame(15),target,entity,at,at.AddSeconds(15),null)),Refused(()=>OriginalGrantReady(Frame(6,Grant(6,8)),target,entity,at,at.AddSeconds(6),null)),
Refused(()=>OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6),refusal)),Refused(()=>OriginalGrantReady(Frame(6,ship:43),target,entity,at,at.AddSeconds(6),null)),
Refused(()=>OriginalGrantReady(Frame(6),target,entity,at,at.AddSeconds(6).AddMilliseconds(251),null))};
if(checks.Any(value=>!value))throw new InvalidDataException("Original ATC task-window, late-grant or refusal/identity regression failed.");return checks.Length;
}
internal static async Task EnterPauseAsync(int pid,PersistentProtectionProcess guardian,string report)
{
var channel=new NativeRelogChannel(pid,NativeRelogChannel.SupportedGameSha256,t=>{t.ThrowIfCancellationRequested();guardian.RequireReady(pid);return Task.CompletedTask;},returnToMenuTrial:true);
var owner=Guid.NewGuid().ToString("N");var request=Guid.NewGuid().ToString("N");var submitted=false;var paused=false;string? failure=null;
using var stop=new CancellationTokenSource(TimeSpan.FromSeconds(8));
try
{
await channel.BeginAsync(owner,stop.Token);
while(true)
{
var frame=await channel.ReadAsync(owner,stop.Token);
if(frame.Stable&&frame.State=="Pause"){paused=true;break;}
if(frame.Stable&&frame.State=="MainMenu"){paused=true;break;}
if(!submitted&&frame.Stable&&frame.State=="InGame")
{
submitted=true;
try{await channel.SubmitAsync(owner,request,frame,"@pause",stop.Token);}catch(Exception error)when(error is IOException or OperationCanceledException&&!stop.IsCancellationRequested){}
}
await Task.Delay(40,stop.Token);
}
}
catch(Exception error){failure=error.ToString();throw;}
finally{await channel.EndAsync(owner);await File.WriteAllTextAsync(report,JsonSerializer.Serialize(new{pid,paused,submitted,request,failure,clientTerminated=false},ToolboxSettings.JsonOptions));}
}
}