返回提交历史
Modified
README.md
+2
-2
Modified
Start-Toolbox.cmd
+8
-0
Modified
XFEEDToolBox.Core/Execution/AutomaticTradeEngine.cs
+6
-6
Modified
XFEEDToolBox.Core/Execution/NativeTradeNavigation.cs
+1
-1
Modified
XFEEDToolBox.Core/Navigation/SystemNavigationRunner.cs
+10
-6
Modified
XFEEDToolBox.Test/AutomaticTradeMenuIntegrationTests.cs
+14
-0
Modified
XFEEDToolBox.Test/NativeTradeCommandDriverTests.cs
+28
-0
Modified
XFEEDToolBox.Test/SystemNavigationRunnerTests.cs
+11
-0
Modified
XFEEDToolBox/XFEEDToolBox.csproj
+1
-1
Added
docs/INTERFACE-0.4.27.md
+9
-0
Added
docs/VALIDATION-0.4.27.md
+9
-0
XFEstudio/XFEEDToolBox
fix: preserve trade recovery budget across telemetry retries
d70f166
代码差异
11 个文件
+99
-16
@@ -1,6 +1,6 @@
1
1
# XFE ED ToolBox
2
2
3
当前 0.4.26 修复 Bernal 空间站的原生停靠请求,并为连续未执行的请求加入有上限的恢复,正常空管等待继续保留。支持在严格核对空舱静止与连续健康状态后,通过原始菜单更新底层插件;原订单、轮数和收益继续累计。详见 [0.4.26 说明](docs/INTERFACE-0.4.26.md)。
3
当前 0.4.27 将普通飞行数据重试与会话恢复次数分别计算,避免正常跃迁和超巡已消耗降落交接失败后的恢复额度;空载和载货航段都保留最多三次真实会话恢复。降落交接的连续相同状态不再每帧刷日志,并保留原始归零诊断。详见 [0.4.27 说明](docs/INTERFACE-0.4.27.md)。
4
4
5
5
0.4.23 修复当前星系原生 3D 合成层为零尺寸的空白问题,并将跑商改为全范围候选、并行计算、真实进度、采购来源类型筛选和按船型核对停机坪;CG 交付候选使用紫色及文字标识。详见 [0.4.23 说明](docs/INTERFACE-0.4.23.md)。当前星系仍支持真实坐标与左侧目录双向选择,实时商品保留报价详情、来源和完整采集时间;两页依据 Imagegen 设计稿实现。重复诊断会合并,跑商实际运行期间可恢复确切的游戏暂停菜单,手动暂停或停止任务后撤销恢复权限。既有范围见 [0.4.22 说明](docs/INTERFACE-0.4.22.md)及[当前星系与星系内驾驶](docs/CURRENT-SYSTEM-NAVIGATION.md)。
6
6
@@ -14,7 +14,7 @@ Elite Dangerous 的 WinUI 3 指挥官工具箱。当前版本提供实时数据
14
14
15
15
## 运行
16
16
17
双击仓库根目录的 `Start-Toolbox.cmd`,优先启动 `dist/XFEEDToolBox-0.4.26-win-x64/XFEEDToolBox.exe`。星图与导航已合并;输入星系名称可自动补全,也可选中/双击星点聚焦,长按恒星待外圈填满后由游戏规划,确认成功后点击“开始自动导航”。航路由游戏计算,软件校验并读取。主页与飞船编辑背景采用本地真实船体的旋转科技线稿。发布包面向 Windows x64,包含 .NET 运行时与 Windows App SDK;源码构建需要 PowerShell 7、.NET 10 SDK、Windows SDK 和 Visual Studio 的 C++ x64 构建工具。`--page Navigation --maximized` 可直接打开最大化星图,`--page Refit` 打开飞船编辑。
17
双击仓库根目录的 `Start-Toolbox.cmd`,优先启动 `dist/XFEEDToolBox-0.4.27-win-x64/XFEEDToolBox.exe`。星图与导航已合并;输入星系名称可自动补全,也可选中/双击星点聚焦,长按恒星待外圈填满后由游戏规划,确认成功后点击“开始自动导航”。航路由游戏计算,软件校验并读取。主页与飞船编辑背景采用本地真实船体的旋转科技线稿。发布包面向 Windows x64,包含 .NET 运行时与 Windows App SDK;源码构建需要 PowerShell 7、.NET 10 SDK、Windows SDK 和 Visual Studio 的 C++ x64 构建工具。`--page Navigation --maximized` 可直接打开最大化星图,`--page Refit` 打开飞船编辑。
18
18
19
19
```powershell
20
20
pwsh -File scripts/Build.ps1
@@ -2,6 +2,14 @@
2
2
setlocal
3
3
cd /d "%~dp0"
4
4
if not defined XFE_TOOLBOX_DATA_DIR if exist "work\toolbox-local-data-dir.txt" set /p "XFE_TOOLBOX_DATA_DIR="<"work\toolbox-local-data-dir.txt"
5
if exist "dist\XFEEDToolBox-0.4.27-win-x64\XFEEDToolBox.exe" (
6
if defined XFE_TOOLBOX_DATA_DIR (
7
start "" "dist\XFEEDToolBox-0.4.27-win-x64\XFEEDToolBox.exe" %* --data-dir "%XFE_TOOLBOX_DATA_DIR%"
8
exit /b
9
)
10
start "" "dist\XFEEDToolBox-0.4.27-win-x64\XFEEDToolBox.exe" %*
11
exit /b
12
)
5
13
if exist "dist\XFEEDToolBox-0.4.26-win-x64\XFEEDToolBox.exe" (
6
14
if defined XFE_TOOLBOX_DATA_DIR (
7
15
start "" "dist\XFEEDToolBox-0.4.26-win-x64\XFEEDToolBox.exe" %* --data-dir "%XFE_TOOLBOX_DATA_DIR%"
@@ -141,11 +141,11 @@ public sealed class AutomaticTradeEngine(AutomaticTradeConfiguration configurati
141
141
Planning.ShipPadPolicy.RequireFits(destination,player().Ship);
142
142
if(player().Docked&&player().MarketId==destination.MarketId){RefreshCompleted();return;}
143
143
await StateAsync("travelling","正在前往 "+destination.DisplayName,destination,token);
144
for(var attempt=0;;attempt++)
144
for(var recoveries=0;;)
145
145
{
146
146
try{await driver.ExecuteAsync(new(TradeActionKind.Travel,new(){From=player().MarketId==source.MarketId?source:configuration.Destination,To=destination},null),CheckAsync,token).ConfigureAwait(false);RefreshCompleted();return;}
147
catch(DockingHandoffException)when(attempt<3&&recoverToSameMode is not null){await RecoverAsync(token).ConfigureAwait(false);}
148
catch(StationDepartureRecoveryException)when(attempt<3&&recoverToSameMode is not null){await RecoverAsync(token).ConfigureAwait(false);}
147
catch(DockingHandoffException)when(recoveries<3&&recoverToSameMode is not null){recoveries++;await RecoverAsync(token).ConfigureAwait(false);}
148
catch(StationDepartureRecoveryException)when(recoveries<3&&recoverToSameMode is not null){recoveries++;await RecoverAsync(token).ConfigureAwait(false);}
149
149
catch(Exception error)when(FlightThreatPauseException.Present(error)&&!token.IsCancellationRequested){await WaitForSafetyAsync(destination,token).ConfigureAwait(false);}
150
150
catch(Exception error)when(NavigationRecovery.CanRetry(error,token))
151
151
{await StateAsync("travelling","正在衔接下一段航程,自动继续",destination,token);await Task.Delay(100,token).ConfigureAwait(false);}
@@ -231,13 +231,13 @@ public sealed class AutomaticTradeEngine(AutomaticTradeConfiguration configurati
231
231
estimate=supplySelection is {} selection&&selection.Source.MarketId==leg.From.MarketId&&selection.Order==leg.Orders.Single()
232
232
?new(selection.EstimatedNetProfit,selection.EstimatedMinutes,selection.Basis):AutomaticTradeEstimate.For(leg,root,initial.CurrentShipId);
233
233
active=directory;await StateAsync("cargo-journey","正在采购、运输并出售本批货物",leg.To,token);
234
for(var attempt=0;;attempt++)
234
for(var recoveries=0;;)
235
235
{
236
236
var journey=new NativeTradeJourney(driver,player,CheckAsync,directory){JournalDirectory=journalDirectory};
237
237
journey.Status+=text=>Progress?.Invoke(new(phase,text,next,completed,profit,active){Estimate=estimate,CompletedRounds=completedRounds,SupplySelection=supplySelection});
238
238
try{await journey.RunAsync(leg,token).ConfigureAwait(false);break;}
239
catch(NativeTradeJourneyIncompleteException error)when(error.InnerException is DockingHandoffException&&attempt<3&&recoverToSameMode is not null){await RecoverAsync(token).ConfigureAwait(false);}
240
catch(NativeTradeJourneyIncompleteException error)when(error.InnerException is StationDepartureRecoveryException&&attempt<3&&recoverToSameMode is not null){await RecoverAsync(token).ConfigureAwait(false);}
239
catch(NativeTradeJourneyIncompleteException error)when(error.InnerException is DockingHandoffException&&recoveries<3&&recoverToSameMode is not null){recoveries++;await RecoverAsync(token).ConfigureAwait(false);}
240
catch(NativeTradeJourneyIncompleteException error)when(error.InnerException is StationDepartureRecoveryException&&recoveries<3&&recoverToSameMode is not null){recoveries++;await RecoverAsync(token).ConfigureAwait(false);}
241
241
catch(NativeTradeJourneyIncompleteException error)when(FlightThreatPauseException.Present(error)&&!token.IsCancellationRequested){await WaitForSafetyAsync(leg.To,token).ConfigureAwait(false);}
242
242
catch(NativeTradeJourneyIncompleteException error)when(error.InnerException is {} cause&&NavigationRecovery.CanRetry(cause,token))
243
243
{await StateAsync("cargo-journey","正在衔接下一段航程,保留原货物继续",leg.To,token);await Task.Delay(100,token).ConfigureAwait(false);}
@@ -94,7 +94,7 @@ public sealed class NativeTradeNavigation(int processId,string gameHash,Func<Pla
94
94
var local=await LocalAsync(token);var arrival=new SystemNavigationRunner(player);string? lastIssue=null;
95
95
arrival.Progress+=value=>{lastIssue=value.Message;Status?.Invoke(value.Message);};
96
96
await WithFlightSafetyAsync(()=>arrival.RunAsync(target,local,token));
97
if(arrival.HandoffFailed)throw new DockingHandoffException(lastIssue??"原生自动降落交接未完成。",destination.MarketId);
97
if(arrival.HandoffFailed)throw new DockingHandoffException(lastIssue??"原生自动降落交接未完成。",destination.MarketId,arrival.Failure);
98
98
if(arrival.State!=NavigationRunState.Completed||!player().Docked||player().MarketId!=destination.MarketId)
99
99
throw new InvalidOperationException(lastIssue??"目的站停靠尚未确认完成。",arrival.Failure);
100
100
}
@@ -13,7 +13,7 @@ public interface ISystemFlightControlDriver
13
13
Task SuspendSystemFlightAsync()=>ReleaseSystemFlightAsync();
14
14
}
15
15
public sealed record SystemNavigationProgress(NavigationRunState State,SystemNavigationTarget Target,SystemNavigationPhase Phase,string Message);
16
public sealed class DockingHandoffException(string message,long marketId):InvalidOperationException(message)
16
public sealed class DockingHandoffException(string message,long marketId,Exception? inner=null):InvalidOperationException(message,inner)
17
17
{public long MarketId{get;}=marketId;}
18
18
public sealed class DockingRequestNotAppliedException():IOException("游戏尚未确认空管请求已执行。");
19
19
public sealed class DockingResetObservationPendingException(string requestId,long marketId,DateTimeOffset requestedAt,Exception inner)
@@ -39,8 +39,12 @@ public sealed class SystemNavigationRunner(Func<PlayerState> player,Func<DateTim
39
39
if(cancellation is not null)throw new InvalidOperationException("星系内导航已在运行。");
40
40
stop=CancellationTokenSource.CreateLinkedTokenSource(token);cancellation=stop;
41
41
}
42
HandoffFailed=false;Failure=null;var phase=SystemNavigationPhase.Preparing;var state=NavigationRunState.Running;var terminal="星系内导航已停止。";
43
void Report(SystemNavigationPhase next,string message){phase=next;State=NavigationRunState.Running;Progress?.Invoke(new(State,target,next,message));}
42
HandoffFailed=false;Failure=null;var phase=SystemNavigationPhase.Preparing;var state=NavigationRunState.Running;var terminal="星系内导航已停止。";string? reportedMessage=null;
43
void Report(SystemNavigationPhase next,string message)
44
{
45
if(State==NavigationRunState.Running&&phase==next&&reportedMessage==message)return;
46
phase=next;reportedMessage=message;State=NavigationRunState.Running;Progress?.Invoke(new(State,target,next,message));
47
}
44
48
try
45
49
{
46
50
var initial=player();var initialShip=initial.CurrentShipId;var initialCommander=initial.CommanderId;var initialSession=initial.LoadGameAt;
@@ -79,13 +83,15 @@ public sealed class SystemNavigationRunner(Func<PlayerState> player,Func<DateTim
79
83
decision=new(SystemNavigationPhase.Stopped,"自动降落未接管,飞船仍在移动,正在保护退出。",null,null,SystemNavigationAction.ExitForFailedHandoff);
80
84
else if(!landingObserved&&!decision.Complete&&now()-pendingReset.RequestedAt>TimeSpan.FromSeconds(30))
81
85
throw new InvalidOperationException("自动降落回执和接管状态仍未确认,原请求未重发。",pendingReset);
86
if(decision.Phase!=SystemNavigationPhase.Stopped&&!decision.Complete)
87
decision=decision with{Phase=SystemNavigationPhase.NativeLanding,Message=landingObserved?"自动降落已接管,正在核对实际停靠。":"正在核对归零回执与自动降落状态,不重发请求。"};
82
88
}
83
89
Report(decision.Phase,decision.Message);
84
90
if(decision.Phase==SystemNavigationPhase.Stopped)
85
91
{
86
92
if(decision.Actions.HasFlag(SystemNavigationAction.ExitForFailedHandoff))
87
93
{
88
HandoffFailed=true;
94
HandoffFailed=true;Failure=pendingReset;
89
95
await driver.ApplySystemFlightAsync(decision,frame,target,frame.ObservedAt.AddMilliseconds(250),stop.Token);
90
96
}
91
97
state=NavigationRunState.Stopped;terminal=decision.Message;break;
@@ -98,8 +104,6 @@ public sealed class SystemNavigationRunner(Func<PlayerState> player,Func<DateTim
98
104
await driver.ApplySystemFlightAsync(decision,frame,target,frame.ObservedAt.AddMilliseconds(250),stop.Token);
99
105
if(decision.Actions.HasFlag(SystemNavigationAction.RequestDocking))requestFailures=0;
100
106
}
101
else if(!decision.Complete)
102
Report(SystemNavigationPhase.NativeLanding,landingObserved?"自动降落已接管,正在核对实际停靠。":"正在核对归零回执与自动降落状态,不重发请求。");
103
107
missingSince=null;
104
108
if(decision.Complete){state=NavigationRunState.Completed;terminal=decision.Message;break;}
105
109
}
@@ -100,6 +100,20 @@ public sealed class AutomaticTradeMenuIntegrationTests
100
100
Check.That(restartObserved&&safetyPause);Check.Equal(1,visits);Check.That(released>=2);
101
101
Check.That(channel.Calls.All(op=>op is "describe" or "commerce.inventory"));
102
102
}
103
[Test]public async Task ActualSessionRecoveriesRemainBoundedAfterManyTransientReads()
104
{
105
using var temporary=new TemporaryDirectory();var current=Player;var channel=new Commerce();var visits=0;var recoveries=0;
106
var driver=new NativeTradeCommandDriver(channel,()=>current,Path.Combine(temporary.Path,"operations"),(_,_,_)=>
107
{
108
if(++visits%5!=0)throw new FlightTelemetryUnavailableException("fixture fresh-frame retry");
109
throw new DockingHandoffException("fixture handoff still unavailable",2);
110
},_=>Task.CompletedTask);
111
var engine=new AutomaticTradeEngine(Configuration(temporary.Path),driver,channel,()=>current,_=>Task.CompletedTask,temporary.Path,_=>
112
{recoveries++;current=current with{LoadGameAt=current.LoadGameAt!.Value.AddSeconds(1)};return Task.CompletedTask;});
113
var refused=false;try{await engine.RunAsync(default).WaitAsync(TimeSpan.FromSeconds(5));}catch(DockingHandoffException){refused=true;}
114
Check.That(refused);Check.Equal(3,recoveries);Check.Equal(20,visits);
115
Check.That(channel.Calls.All(op=>op is "describe" or "commerce.inventory"));
116
}
103
117
[Test]public async Task EngineInterfaceAndFlightPreparationFailuresNeverCreateARunningScope()
104
118
{
105
119
foreach(var rejectDescribe in new[]{true,false})
@@ -367,6 +367,34 @@ public class NativeTradeCommandDriverTests
367
367
Check.That(refusals>=3);Check.Equal(2,channel.Mutations);Check.Equal(0,channel.Cargo);
368
368
Check.Equal(1,Directory.GetFiles(directory.Path,"settled.json",SearchOption.AllDirectories).Length);
369
369
}
370
[Test] public async Task TransientFlightReadsDoNotSpendEmptyOrLoadedSessionRecoveryAttempts()
371
{
372
foreach(var loaded in new[]{false,true})foreach(var departure in new[]{false,true})
373
{
374
using var directory=new TemporaryDirectory();var channel=new Channel{Credits=10000000,BatchSupported=true,FuelNeeded=false};
375
channel.Player=channel.Player with{CargoCapacity=752,Credits=channel.Credits,Ship="type9",Rebuy=1000};
376
var reads=0;var recovered=0;
377
var driver=new NativeTradeCommandDriver(channel,()=>channel.Player,Path.Combine(directory.Path,"operations"),
378
(station,_,_)=>
379
{
380
if((channel.Cargo>0)==loaded&&++reads<=5)
381
{
382
if(reads<=4)throw new FlightTelemetryUnavailableException("fixture transient during scene transition");
383
channel.Player=channel.Player with{Docked=false};
384
if(departure)throw new StationDepartureRecoveryException((long)channel.ActualMarket,TimeSpan.FromMinutes(3));
385
throw new DockingHandoffException("fixture landing handoff",station.MarketId);
386
}
387
channel.Player=channel.Player with{MarketId=station.MarketId,Docked=true};channel.ActualMarket=(ulong)station.MarketId;return Task.CompletedTask;
388
},_=>Task.CompletedTask,batchPolicy:new(752,1000));
389
driver.WalletObserved+=o=>channel.Player=o.Project(channel.Player);
390
var configuration=new AutomaticTradeConfiguration{Source=new(){MarketId=1,Name="One",SystemName="A",MaxLandingPad=LandingPad.Large},Destination=new(){MarketId=99,Name="Other",SystemName="B",MaxLandingPad=LandingPad.Large},WorkingDirectory=directory.Path};
391
var engine=new AutomaticTradeEngine(configuration,driver,channel,()=>channel.Player,_=>Task.CompletedTask,directory.Path,_=>
392
{recovered++;channel.Player=channel.Player with{Docked=true,LoadGameAt=channel.Player.LoadGameAt!.Value.AddSeconds(1)};return Task.CompletedTask;}){MaximumCycles=1};
393
await engine.RunAsync(default).WaitAsync(TimeSpan.FromSeconds(8));
394
Check.Equal(1,recovered);Check.That(reads>=6);Check.Equal(2,channel.Mutations);Check.Equal(0,channel.Cargo);
395
Check.Equal(1,Directory.GetFiles(directory.Path,"settled.json",SearchOption.AllDirectories).Length);
396
}
397
}
370
398
[Test] public async Task CgEngineUsesUserDestinationAndConfirmsItsActualContribution()
371
399
{
372
400
using var directory=new TemporaryDirectory();var channel=new Channel{Credits=10000000,BatchSupported=true,FuelNeeded=false,Goals=true};
@@ -60,6 +60,17 @@ public class SystemNavigationRunnerTests
60
60
if(d.Actions.HasFlag(SystemNavigationAction.ExitForFailedHandoff))exits++;}};
61
61
var runner=new SystemNavigationRunner(()=>Player,()=>at);await runner.RunAsync(Target,driver);
62
62
Check.Equal(NavigationRunState.Stopped,runner.State);Check.That(runner.HandoffFailed);Check.Equal(1,arms);Check.Equal(1,exits);
63
Check.That(runner.Failure is DockingResetObservationPendingException{InnerException:IOException});
64
}
65
[Test]public async Task PendingResetKeepsReadingWithoutAlternatingOrRepeatingProgressEveryFrame()
66
{
67
var at=Now;var arms=0;var messages=new List<string>();
68
var driver=new Fake{Frame=n=>{at=Now.AddMilliseconds((n-1)*100);return n==13?Docked with{Sequence=n,ObservedAt=at}:Landing(n,at,NativeAssistState.Ready);},
69
OnDecision=d=>{if(d.Actions.HasFlag(SystemNavigationAction.EnableDockingAssist)){arms++;throw new DockingResetObservationPendingException("immutable-request",20,Now,new IOException("Lost status reply"));}}};
70
var runner=new SystemNavigationRunner(()=>Player,()=>at);runner.Progress+=p=>messages.Add(p.Message);
71
await runner.RunAsync(Target,driver);
72
Check.Equal(NavigationRunState.Completed,runner.State);Check.Equal(1,arms);Check.Equal(13,driver.Calls.Count(x=>x=="read"));
73
Check.Equal(1,messages.Count(x=>x=="正在核对归零回执与自动降落状态,不重发请求。"));Check.That(messages.Count<=6);
63
74
}
64
75
[Test] public async Task AResetReceiptForAnotherMarketCannotBecomeAnObservedHandoff()
65
76
{
@@ -2,7 +2,7 @@
2
2
<PropertyGroup>
3
3
<OutputType>WinExe</OutputType>
4
4
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
5
<Version>0.4.26</Version>
5
<Version>0.4.27</Version>
6
6
<TargetFramework>net10.0-windows10.0.22621.0</TargetFramework>
7
7
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
8
8
<ApplicationManifest>app.manifest</ApplicationManifest>
@@ -0,0 +1,9 @@
1
# 0.4.27:飞行数据重试与会话恢复计数
2
3
CG 循环载货抵达 Homer Platform 时,归零请求尚未确认,原有两秒移动保护停止了本次驾驶交接。游戏原生降落随后完成靠港,但工具箱没有自动核对原订单继续出售。原因是航段循环中的计数同时累计普通飞行数据重试和真实会话恢复;此前几次正常瞬时遥测重试已耗尽“最多三次恢复”的额度。
4
5
空载与载货航段现在只在实际开始同模式会话恢复时消耗额度,普通遥测恢复与威胁等待不会占用它。最多三次真实会话恢复仍然有效;取消、身份、货物、健康和资金核对继续约束恢复。
6
7
归零回执未确认时只报告一个当前观察状态,连续相同状态不再每帧重复刷日志;飞行观测和保护检查仍逐帧执行。若最终交接失败,异常保留不可重发请求的原始原因,便于区分请求没有进入原生接口、确认丢失和真实接管失败。
8
9
原有两秒移动保护、原生请求时限和一次性归零语义保持生效。此次更新只涉及托管程序,底层仍为 0.5.21-dev。原 CG 工作目录、交易键、货物和账本继续使用。
@@ -0,0 +1,9 @@
1
# 0.4.27 验证记录
2
3
- 顺序全量回归:1,523 项,1,517 通过、0 失败、6 跳过,125.145 秒。报告位于本地忽略目录 `work/tests/toolbox-0.4.27-sequential`。新增场景覆盖空载/载货以及进站/离站在四次普通遥测重试后仍能恢复,最多三次真实会话恢复,以及归零观察逐帧继续但不重复刷状态日志。原两秒移动保护、归零不重发与伤害/取消保护继续通过。
4
- 先前一次完整运行中的既有 `ManualVisualDamageStopsInputsWithoutExitOrRestart` 测试超时,保留了失败记录;随后单项复测在 78.372 毫秒通过,无并行发布构建的完整复核也通过。未修改保护逻辑或该测试的时限。
5
- Windows x64 自包含发布成功,958 个部署文件与发布目录逐一核对 SHA256,记录在 `work/release-0.4.27/deployment.json`。底层支持仍经正式项目引用生成并内嵌,接口版本为 0.5.21-dev;游戏进程未重启。
6
- 官方日志确认工具箱停止后,游戏原生降落于 2026-10-25 21:34:52 UTC 实际停靠 Homer Platform。程序更新后从原工作目录接续,原采购键 `81e30853b0ba427482a43de9de3d5e98` 和完整买入回执保持不变;1,104 吨铀以唯一出售键 `7ee329716be644bbb1d8c486db9a0230` 完成服务器与客户端确认。原余额与费用闭合,第 8 轮净收益为 55,323,345 Cr。
7
- CG 864 的服务器响应与原文哈希确认贡献从 22,685 增至 23,789 吨,原有 21 份已完成批次的旅程、结算与贡献文件保持不变。累计已确认净利润为 460,052,599 Cr,程序随后独立选择 Wolf 1453 / Cartier City 并开始下一趟。
8
- `background-visual-check` 在最终进程后台取得 3862×2110 原图,实际查看原图及原比例分块,使用 OCR 交叉核对目标、货源、运行状态与利润。运行文字、布局和原订单恢复三项均通过,证据位于 `work/visual/docking-handoff-0.4.27`,取图前后台窗口未变化。
9
- 行情仍使用中心周边 500 ly 缓存,没有全量下载或完整数据库校验。连续数天运行尚未确认,仍需后续巡检积累证据。旧 SDK 的最后一份归零记录不足以完整分类本次初始请求拒绝,新异常已保留原始诊断;没有通过放宽移动保护或重发未知请求掩盖它。