fix: report a missing Get-FileHash as "cannot verify", not as a defect

The Windows runner came back red on three check-updates assertions for one
reason: `Get-FileHash` does not exist there, the mirror check threw, and the catch
reported `mirror.json 解析失败` as [注意] — which counts as "needs action". A host
that cannot hash two files therefore looked like a machine with a broken bundle.

That is the same false red this release already removed from the `rea doctor` exit
code and from the bare-major pin comparison, so it gets the same treatment:

- the mirror check asks `Get-Command Get-FileHash` first and says [上游] when the
  capability is absent, rather than implying the mirror is inconsistent
- "mirror.json points at a plugin directory that no longer exists" and a
  mirror.json that will not parse are also [上游]: both are "cannot compare",
  not "compared and differs"

The test that constructs the stale-mirror warning now skips on a host without
Get-FileHash, because that scenario is unreachable there — asserting on a warning
the platform cannot emit would only produce another red that means nothing.

Verified: hardening.test 14/14 locally, full suite 154 (151 pass / 3 skipped).
This commit is contained in:
czcdr committed 2026-11-06 23:31:05 +08:00
1 parent 849863841d
commit 5c71bf87f7
2 files changed
+31 -5

No files matched your search

+15 -5
View File
@@ -463,13 +463,23 @@ if (-not (Test-Path $manifestPath)) {
$record = Get-Content $mirrorRecord -Raw -Encoding UTF8 | ConvertFrom-Json
$pluginShim = if ($record.pluginRoot) { Join-Path $record.pluginRoot 'bin\rea-shim.mjs' } else { $null }
if ($pluginShim -and (Test-Path $pluginShim)) {
$same = (Get-FileHash $mirrored -Algorithm SHA256).Hash -eq (Get-FileHash $pluginShim -Algorithm SHA256).Hash
if ($same) { Ok '镜像 shim 与插件一致(行跑的就是这个版本)' }
else { Warn "镜像 shim 落后于插件($($record.pluginRoot))—— 行仍在跑旧副本;重跑 node scripts/setup.mjs 让它换成新版本" }
# `Get-FileHash` is missing on hosted Windows runners and in any host
# running PowerShell in a restricted language mode. That is a
# "cannot verify" answer, not an "inconsistent" one: reporting it as
# [注意] made such a machine look like it needed action, which is the
# same false red this script was just fixed for in the other
# direction. Ask whether the comparison is even possible first.
if (-not (Get-Command Get-FileHash -ErrorAction SilentlyContinue)) {
Note '本机没有 Get-FileHash,无法比对镜像 shim 是否最新 —— 跳过这一项'
} else {
$same = (Get-FileHash $mirrored -Algorithm SHA256).Hash -eq (Get-FileHash $pluginShim -Algorithm SHA256).Hash
if ($same) { Ok '镜像 shim 与插件一致(行跑的就是这个版本)' }
else { Warn "镜像 shim 落后于插件($($record.pluginRoot))—— 行仍在跑旧副本;重跑 node scripts/setup.mjs 让它换成新版本" }
}
} else {
Warn "mirror.json 指向的插件目录已不存在($($record.pluginRoot))—— 无法比对镜像 shim 是否最新"
Note "mirror.json 指向的插件目录已不存在($($record.pluginRoot))—— 无法比对镜像 shim 是否最新"
}
} catch { Warn "mirror.json 解析失败: $($_.Exception.Message)" }
} catch { Note "mirror.json 解析失败: $($_.Exception.Message)" }
}
}
else { Bad "缺少 MCP 行指向的 shim: $mirrored —— 重跑 setup --reuse" }
+16
View File
@@ -428,12 +428,28 @@ test("check-updates: a pin drift is reported as needing action, not as green", a
assert.match(last, /pin 漂移 1 项/, last);
});
function hasFileHash(command) {
// The stale-mirror warning below is produced by comparing two file hashes, so a
// host without `Get-FileHash` (hosted Windows runners, restricted language mode)
// cannot construct that scenario at all. Skip honestly instead of asserting on a
// warning the platform can never emit — the script itself already reports the
// missing capability as [上游] rather than as "needs action".
const probe = spawnSync(command, ["-NoProfile", "-Command", "if (Get-Command Get-FileHash -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"], {
windowsHide: true,
});
return probe.status === 0;
}
test("check-updates: a warning alone is enough to stop the green verdict", async (t) => {
const command = powerShell();
if (!command) {
t.skip("PowerShell is not available on this host");
return;
}
if (!hasFileHash(command)) {
t.skip("this host has no Get-FileHash, so the stale-mirror warning cannot be produced");
return;
}
const registry = await stubRegistry(t);
const fixture = makeBundleFixture(t, "check-warn");
// Every pin matches; only the mirrored shim is stale (plugin upgraded, setup