mirror of
https://github.com/czcdr/dsh-plugin-rea.git
synced 2026-11-07 10:25:59 -10:00
fix: the setup card must say what setup resets
Restarting dsh with the 2.0.12 copy still in the profile re-provisioned the bundle to 2.0.12's pin: REA went back to 6.7.0, the Ghidra gate override went with it, and the MCP row failed with "REA could not start". That is the card doing its job on a machine whose plugin copy was stale — but the card never said the aligned run also wipes the override. - client.js: third note in both languages. It names the override case and the command that restores it, so the card is not advice that silently undoes a deliberate choice. - README (both): the "you must run setup" block says the same thing. - ghidra-gate-override.mjs: judge a recorded override by the files on disk. Re-provisioning replaces rea-agents while leaving the record behind, so --enable now replaces a stale record instead of refusing, and --disable counts already-lost files instead of throwing. - CHANGELOG: 2.0.13 records both, plus the failure that prompted them. Verified after re-aligning this machine: setup --reuse reached "setup complete" with its Ghidra smoke importing java.exe in 28 s on 12.2, the shim resolves REA 6.8.0, and the MCP path through the shim returns the same segments / procedure inventory / entry pseudocode as the 12.1.4 baseline with provider.version = 12.2. Gates: audit 24/24 hash-pinned clean, 88 tests (85 pass / 3 skipped), verify-branch ALL CHECKS PASSED, host-compat 10 covered / 5 outside.
This commit is contained in:
1 parent
10572a7958
commit
c55768233c
5 files changed
+53
-4
No files matched your search
@@ -38,6 +38,15 @@
|
||||
- **`check-updates.ps1` 认得这份记录**:盘上跑 12.2 时打印「本机覆盖 Ghidra 闸门」,而不是劝用户「重跑 setup 对齐」
|
||||
—— 后者正好会把覆盖悄悄抹掉。
|
||||
|
||||
### 修复
|
||||
|
||||
- **「还要跑一次 setup」卡片的说明补上覆盖这一条**:这张卡片出现在每次升级之后,而它就是叫你去跑 setup 的。
|
||||
setup 会重新供给内置 REA,**Ghidra 闸门覆盖随之消失** —— 卡片现在明写这一点并给出恢复命令。踩到的实例:
|
||||
本机重启后,profile 里还是 2.0.12 的旧副本,它的 shim 按自己的 pin 把 bundle 重新供给回 6.7.0,
|
||||
覆盖与 6.8.0 一起被抹掉,MCP 行随之 `REA could not start`。
|
||||
- **`ghidra-gate-override.mjs` 处理「记录还在、补丁已被 re-provision 抹掉」的半状态**:`--enable` 现在按盘上
|
||||
实际内容判断记录是否仍成立,陈旧记录直接替换而不是报错;`--disable` 对已失去补丁的文件只计数不抛错。
|
||||
|
||||
### 验证
|
||||
|
||||
- 单测 **88 条**(85 过 / 3 平台跳过 / 0 失败);`audit-manifest` **24/24 hash-pinned clean**;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
> does **not** move the bundle to the new pins — REA and the engines stay at the versions recorded by the last
|
||||
> setup run. Skip it on a first install and the row exits `MODULE_NOT_FOUND` with no tools and no message;
|
||||
> skip it after an upgrade and you keep running the old REA silently (`check-updates.ps1` reports the drift).
|
||||
> If you had enabled the Ghidra gate override (see §9 of the 2026-10-26 review), that setup run re-provisions the
|
||||
> bundled REA and the patch goes with it — re-enable it afterwards, or accept the pinned Ghidra again.
|
||||
> The full rule set is under [Updating](#updating--three-independent-things).
|
||||
|
||||
> **A first install and every plugin upgrade also show a one-time guide in the Web GUI.** It says whether the
|
||||
|
||||
+2
-1
@@ -29,7 +29,8 @@
|
||||
> 市场里的安装/更新只替换包,然后到此为止。从 **2.0.8** 起,市场升级能保证**那一行**继续可用(镜像启动器会
|
||||
> 转发执行新的那份),但它**不会**把 bundle 换到新的钉子 —— REA 与引擎仍是上一次 setup 时记下的版本。
|
||||
> 首次安装不跑:行以 `MODULE_NOT_FOUND` 退出,工具消失且没有任何提示;升级后不跑:仍旧跑旧 REA 且没有症状
|
||||
>(`check-updates.ps1` 会报出这条漂移)。完整规则见[更新](#更新--三件互相独立的事)。
|
||||
>(`check-updates.ps1` 会报出这条漂移)。若你开过 Ghidra 闸门覆盖,这一次 setup 会重新供给内置 REA、覆盖随之
|
||||
> 消失 —— 跑完再 `--enable` 恢复,或者接受回到钉住的那一版。完整规则见[更新](#更新--三件互相独立的事)。
|
||||
|
||||
> **首次安装与每次升级插件后,Web GUI 会显示一次操作指南。** 它会说明运行时是缺失、还是落后于本插件钉的版本,
|
||||
> 给出这次安装对应的完整 `node "<安装路径>/scripts/setup.mjs"` 命令,并按插件版本记住“已看过”。
|
||||
|
||||
@@ -56,6 +56,7 @@ window.__ModuleLoader__.load({
|
||||
hint: "跑完重启 dsh。这一步只对齐运行时,不会更新插件包本身;升级后同样再跑一次。",
|
||||
noteSmoke: "setup 结束时会用 JDK 自带的 java 跑一次真实分析来验证引擎 —— 那里 30–60 秒没有任何输出是正常的。",
|
||||
noteLock: "若它报 “another provisioning run holds …”,说明后台已有一个 setup 在跑,等它结束再试即可。",
|
||||
noteOverride: "若你开过 Ghidra 闸门覆盖(让本机跑 REA 未验证的 Ghidra),setup 会重新供给内置 REA,那层覆盖随之消失 —— 跑完执行 node scripts/ghidra-gate-override.mjs --enable --version 12.2 恢复。",
|
||||
},
|
||||
en: {
|
||||
badge: "ONE-TIME SETUP",
|
||||
@@ -77,6 +78,7 @@ window.__ModuleLoader__.load({
|
||||
hint: "Restart dsh afterwards. This only aligns the runtime; it does not update the plugin package — run it again after the next upgrade.",
|
||||
noteSmoke: "It finishes by importing a small file to prove the analysis engine works — 30–60 s with no output there is normal.",
|
||||
noteLock: "If it reports “another provisioning run holds …”, a setup is already running in the background; wait for it.",
|
||||
noteOverride: "If you had enabled the Ghidra gate override (running a Ghidra REA has not verified), setup re-provisions the bundled REA and the patch goes with it — run node scripts/ghidra-gate-override.mjs --enable --version 12.2 afterwards to restore it.",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -354,6 +356,7 @@ window.__ModuleLoader__.load({
|
||||
},
|
||||
h("li", null, t.noteSmoke),
|
||||
h("li", null, t.noteLock),
|
||||
h("li", null, t.noteOverride),
|
||||
),
|
||||
|
||||
h(
|
||||
|
||||
@@ -138,11 +138,30 @@ function main() {
|
||||
console.log("no override is recorded; nothing to restore");
|
||||
return;
|
||||
}
|
||||
let restored = 0;
|
||||
let stale = 0;
|
||||
for (const entry of active.files) {
|
||||
replaceValue(path.join(vendor, entry.file), entry.patched, entry.original);
|
||||
const file = path.join(vendor, entry.file);
|
||||
if (!existsSync(file)) {
|
||||
stale += 1;
|
||||
continue;
|
||||
}
|
||||
const text = readFileSync(file, "utf8");
|
||||
if (new RegExp(`${CONSTANT}\\s*=\\s*"${entry.patched.replace(/\./g, "\\.")}"`).test(text)) {
|
||||
replaceValue(file, entry.patched, entry.original);
|
||||
restored += 1;
|
||||
} else if (new RegExp(`${CONSTANT}\\s*=\\s*"${entry.original.replace(/\./g, "\\.")}"`).test(text)) {
|
||||
stale += 1;
|
||||
} else {
|
||||
throw new Error(`${entry.file} declares neither ${entry.patched} nor ${entry.original}; inspect it before restoring`);
|
||||
}
|
||||
}
|
||||
unlinkSync(record);
|
||||
console.log(`restored ${CONSTANT} = "${active.originalVersion}" in ${active.files.length} file(s); override record removed`);
|
||||
console.log(
|
||||
`restored ${CONSTANT} = "${active.originalVersion}" in ${restored} file(s)` +
|
||||
(stale > 0 ? `; ${stale} file(s) had already been replaced by a re-provision` : "") +
|
||||
"; override record removed",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -155,7 +174,22 @@ function main() {
|
||||
console.log(`already ${version} — nothing to do`);
|
||||
return;
|
||||
}
|
||||
if (active) throw new Error(`an override is already recorded (→ ${active.requestedVersion}); run --disable first`);
|
||||
if (active) {
|
||||
// Re-provisioning rea-agents replaces the tree, so a record can outlive the patch
|
||||
// it describes. That stale record must not block the next --enable, and it must
|
||||
// not be trusted by --disable either: judge it by the files on disk.
|
||||
const stillApplied = active.files.every((entry) => {
|
||||
const file = path.join(vendor, entry.file);
|
||||
if (!existsSync(file)) return false;
|
||||
const text = readFileSync(file, "utf8");
|
||||
return new RegExp(`${CONSTANT}\\s*=\\s*"${entry.patched.replace(/\./g, "\\.")}"`).test(text);
|
||||
});
|
||||
if (stillApplied) {
|
||||
throw new Error(`an override is already recorded (→ ${active.requestedVersion}); run --disable first`);
|
||||
}
|
||||
console.log(`previous record is stale (rea-agents was re-provisioned); replacing it`);
|
||||
unlinkSync(record);
|
||||
}
|
||||
|
||||
const files = [];
|
||||
for (const entry of declarations) {
|
||||
|
||||
Reference in new issue
Block a user