# SCO 共享热池与来源分账 这次模型使用游戏原生共享热池、原生产热请求和散热曲线,区分 SCO 开启、立即停机和到期停机。SCO 停机后,其后续热输入立即为零;已经进入共享热池的能量仍然存在,由原生散热和其他热源共同决定下一步热量。不会把开启时的温升斜率继续当作停机后的 SCO 热源,也不会虚构每个模块独立的温度。 ## 已核对的静态路径 当前固定游戏 SHA-256 为 `ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63`。本轮新增反汇编仅从 EXE 文件读取,保存在 `artifacts/sco-thermal-source-review-20261025/`;没有执行游戏函数或启动游戏。早期 `artifacts/navigation-live-20261021-1133/` 的采样属于另一个游戏哈希,不能直接把其中旧地址当作当前构建证据。 | 项目 | 当前证据 | 含义与单位 | | --- | --- | --- | | SCO 状态与 Active 调用 | `2EADB40` 的接口指针减 `0x58` 得组件基址;状态 `interface+0x228==2` 时调用 `2EADE60` | 状态 2 才进入这条 Active 产热路径 | | SCO 热曲线 | `2EADE60` 对 `root+0x2E0` 求曲线,参数为 `root+0x298` pressure | 不是燃油曲线;燃油使用独立 `root+0x2C0` | | SCO 产热增量 | `2EADE60` 经 `root+0x168` 的接口槽 `+0x50` 调用 AddHeat | 请求能量 `curve2E0(pressure) × moduleParameter[+0x214] × simulationDt` | | 明确来源标记 | 第三个参数为 `image+0x533E808`,固定文件字节为 `FSD Overcharge` | 可区分该来源;仍须同时验证接收器和主船组件 | | SCO 请求上限参数 | 第四个参数的常量 `image+0x4DE95BC` 为 `float.MaxValue` | 此调用不使用较低的来源热上限;原 AddHeat 自身其他许可检查仍保留 | | 总热输入入口 | `3813740`,接收器为主船 `heatManager+0x60` | 原方法可能限制或忽略请求;前置观察记录的是 requested energy,不能称为已接受能量 | | 原生热更新 | `38144A0`,参数为真实 simulation dt | 遍历 `heatManager+0x160/+0x168` 的热修正器,并通过槽 `+0x28` 更新能量 | | 当前存储能量 | AddHeat 接口的 `+0x130`,即 `heatManager+0x190`,为两个 32 位值异或解码的浮点值 | 热池能量,与 HUD 百分比不同 | | 热容 | 已验证 getter `38139A0`;接口 `heatManager+0x58` 的槽 `+0x28` | 当前装配的原生热容;没有固定写死 289 | | 原生 radiator | 修正器槽 `+0x28==4398F40`,其内部调用 `4399D90` | 读取原生配置、开关及修正比例;不是凭温升斜率推测散热 | | HUD 归一化 | `Navigation.HeatNormalization.cs` 的已验证 scale | HUD 百分比率为 `energyRate × 100 / (heatCapacity × heatDisplayScale)`;已观察的 289 与 1.5 不替代实时读取 | 热曲线的当前 pressure 点输出一个考虑原插值和浮点误差的区间。`scoInputUpper` 暂使用完整 pressure `[0,1]` 曲线界乘热倍率,它是未来产热上界,不是“当前精确产热率”。若要收紧到单个 lease 的 pressure 区间,仍需核对 pressure 增长曲线、模块倍率和输入范围;不能擅自假设 pressure 恒定或线性增长。 当前固定文件另已确认 `0x4DE28B8` 的常量是 **0.5**。`2EADE60` 在 pressure 不高于原目标时使用 `curve2A0(P) × module[+0x210] × simulationDt`;高于目标时使用 `(input[+0x10] − 0.5)` 乘上述增量,再夹在目标与 1 之间。因此不能据“输入不超过 1”宣称高于目标后不会增长。输入构造 `2AA0280` 只清零 Float4 数据,未证明后续所有写入的范围。即使在全程低于目标的子区间可以绕开这个输入分支,仍缺少将 UTC lease 时长换成未来累计 simulation 时间的严格上界。因此没有启用新的压力短界,也没有仅为诊断增加复杂 helper。 ## 来源账本与跨模块读取 `ScoThermalSourceLedger` 将每次 AddHeat 的请求按第三参数来源标记分账,分母使用 HeatTick 真实累计 simulation dt。首个不完整时间段丢弃,完整窗口至少 0.1 simulation 秒。来源上界包含当前部分窗口和最近 0.2 simulation 秒内的正请求峰值;新的来源立即计入,不等待下一个完整窗口。负请求会保留在原始账本,但不会作为未经验证的未来散热能力。 SCO 分账要求同时匹配:固定来源标记、主船接收器、原 SCO 组件表、该组件的热接收器和 Active 状态。其他可读标记仅作为来源类别保存;相同标记可能聚合多个模块实例。未知或不可读标记保留为未识别来源,其能量仍计入其他输入。当前没有把“其他来源”命名为环境热,也没有声称已经分别识别恒星、吸油环境、推进器、发电站等全部模块。 主 Loader 发布固定大小、版本化的 POD 快照,导出只读复制入口 `XFEReadScoThermalSnapshot`。CruiseControl 用函数指针读取同进程快照,核对 schema、大小、主船实体、参考系、热管理器和 200 ms 新鲜度。每帧守卫不等待 named pipe。逐来源明细和模型范围在 `sample.thermal` 诊断字段内保留。 散热公式按内部热比例计算: ```text fraction = clamp((HUDheat × HUDscale / 100 − heatLower) / (heatUpper − heatLower), 0, 1) cooling = coolingScale × (passive + (maximum − passive) × fraction²) ``` 已有原生校验允许实际散热至少达到公式的 97%。因此对外 `coolingScale` 明确为原值乘 `0.97`,并同时输出 `nativeCoolingScale` 和 `coolingLowerBoundFactor`;消费者不再重复乘一次。 ## 预测与停止 `ScoThermalPredictor` 接收共享热池当前 HUD 热量、热容、HUD scale、原生散热曲线和逐来源能量率上界。热样本年龄与来源年龄分别处理:当前热量已经现读时,不能把来源年龄再次算作未经观察的升温时间。 预测窗口来自剩余 lease(最多 250 ms)、实际响应/帧延迟,以及调用方明确指定的停机后观察窗口。来源超过 200 ms 或模型不匹配时不能授权 SCO。不会使用固定两秒继续产热,也不使用 75% 停机、60% 启动或 55% 复位阈值。停止判断检查保持到截止后立即移除 SCO、仍保留其他来源的完整显式窗口;到达 100% 前应按实际延迟和测量误差停止。 这里的来源率使用 simulation 秒,lease 和样本时效使用 UTC 秒;当前没有证明二者在未来整段 lease 内存在固定倍率关系。因此整段 lease 的持续散热预测只是显式来源包络下的预测,不是累计 simulation 时间的形式化上界。原生实际保证来自每次调用的顺序:`CruiseControlRuntime.Observe` 先保存本次收到的真实 simulation dt,再执行守卫,最后才调用原 `2EADB40`。未知或大于 250 ms 的步长拒绝,成功的原 false 调用立即把状态变为 3,所以随后本次原函数不会进入 Active 产热路径。 每帧另外检查 **gross 输入上界**,不预支随后 HeatTick 的散热。基线取现读 `heatManager+0x190` 归一化后的 HUD 热量与当前 HUD 样本的较大值,再加本次实际 simulation dt 对应的 SCO 上界和近期其他来源包络。这样不会把“98% + 本步 3% 产热 − 稍后 3% 散热”误判成从未到过 100%。这一逐帧联锁独立于 UTC lease 与 simulation 时间映射;对尚未识别的其他模块或环境,它仍只覆盖近期观察包络,不是未知未来热源的绝对上界。温升斜率字段已明确 `usedForControl=false`,仅保留诊断。 上升阶段使用显式 Euler 上界,下降阶段使用隐式 Euler 上界,既允许计算停机后的降温,也保留数学方向上的保守性。另输出保持到截止的峰值、截止停机后的峰值/终值、立即停机的峰值/终值,以及当前来源包络下到 100% 的时间下界。时间下界不是未来模块状态不会变化的保证。 ## 已验证与尚未确认 - 新增 18 项托管针对性测试通过,覆盖独立解析解、能量到 HUD 单位、SCO 立即停源、其他来源继续加热、停机后到达 100% 的反例、实际 lease 延迟、来源分账、部分窗口、历史峰值及时过期、过期拒绝,以及本步 gross 输入不能预支散热的反例。 - 联合原生编译已通过。`live08-thermal-cycles` 已在当前固定游戏构建、Type-9 Heavy、542 吨原货物、AD Leonis B 7 远航段完成两个真实热循环;桥接、来源账本、生产策略预测停机、原生 false 回执、实际降温及冷却后再启均有实机记录。 - 每个来源的数值是原生请求能量及其近期包络;除 SCO 的原曲线范围外,其他来源目前没有逐部件完整的未来物理最大值。模块状态或环境突然变化时需要新采样,不应把近期最大值描述为全环境永久上界。 - 当前尚未完整分离环境热,也没有建立或使用每个模块独立温度。SCO 停机移除的是未来输入,不是抹去共享热池已有能量。 ## 2026-10-25 本船实机记录 结果为 `work/sco-fix-20261025/live08-thermal-cycles/result.json`,完整逐帧记录为同目录 `frames.jsonl`;独立复核保存在 `artifacts/sco-physical-context-20261025/live08-audit.json`。本轮 `passed=true`,两次 enable 使用不同 `startRequestId`,各自对应真实 Active、匹配的原生 false 调用及之后的非 Active 观测。 | 周期 | 实际 Active 时间 | Active 样本 | 有效续租 | 停机原因 | | --- | ---: | ---: | ---: | --- | | 1 | 5.154 秒 | 139 | 114 | 生产热模型预测到下一控制期限将达 100% | | 2 | 5.092 秒 | 125 | 114 | 同上 | 累计实际 Active 为 10.246 秒,Active 峰值速度约 `2.1257×10¹¹ m/s`,实测朝目标推进约 `1.5686×10¹² m`。两次生产策略停止决策的 HUD 热量分别为 95.136% 与 95.713%,对应截止停机峰值预测 100.061% 与 100.653%;原生 Active/停机后样本中的最高 HUD 热量为 96.095%。本轮按仍剩余的控制时间提前停止,没有刻意让飞船越过 100%。486 个不同原生逐帧 gross 联锁快照均使用已知真实 simulation dt;例如本步 0.005409 秒、gross 峰值上界 96.203%,并未预支后续散热。两次实飞停止由上层热预测先请求原生 false,本轮没有触发原生独立 gross 拒绝分支,不能将它描述为已实飞覆盖该触发分支。 第一周期原生 false 后,SCO 由状态 2 进入状态 3;随后真实降温约 57.805 个百分点,原始 `CanEngage` 从冷却拒绝恢复为允许,第二次在 HUD 约 37.836% 时重新 enable。该低温来自此次原生冷却时间和真实散热,不是新增固定重启温度。第二周期停止后也观察到约 1.783 个百分点的实际降温。来源账本中的近期 SCO 请求率可以在停止后的窗口内暂时保留历史请求;停机预测移除未来 SCO 输入,不将这段历史均值继续作为停机后的热源。 本轮另验证了输入来源修复:116 个已记录的 Active 时刻,原生混合角轴偏差超过旧 0.18 门限,但独立物理来源幅度为零、分类为 `None`;冷却或 Off 时也有 29 个此类时刻。所有记录的 raw 帧均未出现 `playerOverride`。五条原始飞行/鼠标生产图的关闭状态经过原生 VM、空优先层与跨帧确认;不会把缺失来源默认当零,图重新激活会使证明失效。本轮未用实际人工按键验证前台接管,相关来源匹配及持续接管由自身内存 fixture 覆盖。 结束时两次原生 false 调用均匹配各自周期,SCO 非 Active,最终处于原生冷却状态 3;油门零已确认,控制租约已释放,`controlApplied=false`。零油门不等于飞船已经静止,结束帧仍在 SC 且正在减速。原货物 542 吨、容量 752 吨、目标身份及钱包 `690235635 Cr` 前后保持一致,没有交易、服务购买、重新选目标或测试结束重启游戏。 这些结果只覆盖该构建、该船装配、该远航段及当时来源包络。其他船、其他环境、未知热源突变、压力未来短界及前台真实人工接管仍需各自证据,不能由这两次周期推及全部场景,也不代表任意单次 20 秒 SCO。