dsh-m 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/lib/client.js +34 -6
- package/package.json +1 -1
- package/registry.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
|
|
|
8
8
|
|
|
9
9
|
## 中文
|
|
10
10
|
|
|
11
|
+
### 0.10.3 修复:操作泵恢复记账对账(挂账 1)+ D3 applied core 直钉(挂账 3)
|
|
12
|
+
|
|
13
|
+
- **需求(2026-10-18,0.10.2 dogfood 收尾盘点挂账)**:面板随宿主换装重载会打断泵的最后落账,残留的 running 记录被恢复流程一律标「进程重启中断」——0.10.2 自升级事件中升级实际成功(intent ledger resolved ok + 三面账写穿)却被记为失败,审计误导;另:D3 `applied → needsRestart=false` 缺 core 层直接钉(此前仅 client 层间接覆盖,评审挂账 3)。
|
|
14
|
+
- **方案**:① `restoreRecords` 增第三参 `installedVersionOf`(账实复读缝,main.jsx 以 `api("installed")` 实读实现,与 stillApplies 同款实读纪律)——升级类 running 残留若账面已到 `meta.toVersion` → 改判 done(`meta.reconciledAfterRestart` 留痕);未到目标保持中断原语义;不传第三参行为不变(既有调用方零迁移)。② 三处升级站点 enqueue meta 携带 `toVersion`(chip=state.latest、已装列表=it.latestVersion、市场卡=it.latest)——中断恢复对账的比对依据。
|
|
15
|
+
- **验证**:typecheck 零错误;全量测试(新增 6:T-D3 applied core 直钉 + 恢复对账改判/未到/向后兼容三形态 + 三站点 meta 单行锚;18 例既有失败 028 本机环境清单零新增)。
|
|
16
|
+
|
|
11
17
|
### 0.10.2 修复:D3 自升级 post-write 伪失败账实改判 + 静默自升级(0.10.0→0.10.1 dogfood 实证轮)
|
|
12
18
|
|
|
13
19
|
- **需求(2026-10-18 凌晨,首次 D3 真机 dogfood——0.10.0→0.10.1 自升级事件)**:自升级报失败(`application=failed、error=already-installed`)但三面账(manifest/node_modules/lock)均已写入 0.10.1——宿主对自身 bundle 换装存在 **post-write 伪失败**:installBundle 写穿后 manifest 含该名,宿主完成路径自触守卫(自指操作伪影;守卫源码 `specPackageName` 对 tarball URL 同样可解析包名)。另:0.10.1 引入的自升级确认框破坏既有「点击即升级」体验(主人裁决撤除)。
|
|
@@ -679,6 +685,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
|
|
|
679
685
|
|
|
680
686
|
## English
|
|
681
687
|
|
|
688
|
+
### Fixes in 0.10.3 — operation-pump restore ledger reconciliation (pending item 1) + D3 applied core-level pin (pending item 3)
|
|
689
|
+
|
|
690
|
+
- **Need (2026-10-18, pending items from the 0.10.2 dogfood wrap-up)**: a panel reload during the host's own bundle swap interrupts the pump's final ledger write, and the leftover running record is unconditionally labeled「进程重启中断」(process-restart interrupted) by the restore flow — in the 0.10.2 self-upgrade event the upgrade had actually succeeded (intent ledger resolved ok + all three ledgers written through) yet was recorded as failed, misleading the audit trail. Separately: D3 `applied → needsRestart=false` lacked a core-level pin (previously covered only indirectly at the client layer; review pending item 3).
|
|
691
|
+
- **Approach**: ① `restoreRecords` gains a third parameter `installedVersionOf` (an account-reality re-read seam implemented in main.jsx via `api("installed")`, same live-read discipline as stillApplies) — an upgrade-kind running leftover whose ledger has reached `meta.toVersion` is re-judged as done (`meta.reconciledAfterRestart` recorded); anything else keeps the interrupted semantics; omitting the third parameter preserves the old behavior (zero migration for existing callers). ② the three upgrade sites now carry `toVersion` in the enqueue meta (chip=state.latest, installed list=it.latestVersion, market card=it.latest) — the comparison basis for the restore reconciliation.
|
|
692
|
+
- **Verification**: typecheck clean; full suite (6 new: T-D3 applied core-level pin + three restore-reconciliation shapes + three site meta anchors; 18 pre-existing failures are the 028 machine-environment set, zero new).
|
|
693
|
+
|
|
682
694
|
### Fixes in 0.10.2 — account-reality reconciliation for D3 self-upgrade post-write pseudo-failure + silent self-upgrade (first D3 dogfood round)
|
|
683
695
|
|
|
684
696
|
- **Need (2026-10-18 early morning, first real-machine D3 dogfood — the 0.10.0→0.10.1 self-upgrade event)**: the self-upgrade reported failure (`application=failed、error=already-installed`) while all three ledgers (manifest/node_modules/lock) had already been written to 0.10.1 — the host has a **post-write pseudo-failure** for its own bundle swap: installBundle writes through, the manifest then contains the name, and the host's completion path trips its own guard (self-referential artifact; the guard's `specPackageName` resolves package names from tarball URLs too). Separately: the 0.10.1 self-upgrade confirmation dialog broke the existing "click to upgrade" experience (owner ordered its removal).
|
package/lib/client.js
CHANGED
|
@@ -1562,7 +1562,7 @@ function createOperationsStore(storage) {
|
|
|
1562
1562
|
}
|
|
1563
1563
|
};
|
|
1564
1564
|
}
|
|
1565
|
-
async function restoreRecords(records, stillApplies) {
|
|
1565
|
+
async function restoreRecords(records, stillApplies, installedVersionOf) {
|
|
1566
1566
|
const list = Array.isArray(records) ? records : [];
|
|
1567
1567
|
const out = [];
|
|
1568
1568
|
for (const rec of list) {
|
|
@@ -1584,6 +1584,24 @@ async function restoreRecords(records, stillApplies) {
|
|
|
1584
1584
|
} else if (rec.status === "input") {
|
|
1585
1585
|
out.push({ ...rec, status: "failed", error: "\u5F85\u51B3\u786E\u8BA4\u4E0D\u53EF\u6062\u590D\uFF0C\u8BF7\u91CD\u65B0\u53D1\u8D77", updatedAt: Date.now() });
|
|
1586
1586
|
} else if (rec.status === "running") {
|
|
1587
|
+
if (rec.kind === "upgrade" && rec.meta && typeof rec.meta.toVersion === "string" && rec.meta.toVersion !== "" && typeof installedVersionOf === "function") {
|
|
1588
|
+
let installed;
|
|
1589
|
+
try {
|
|
1590
|
+
installed = await installedVersionOf(rec);
|
|
1591
|
+
} catch {
|
|
1592
|
+
installed = void 0;
|
|
1593
|
+
}
|
|
1594
|
+
if (installed === rec.meta.toVersion) {
|
|
1595
|
+
out.push({
|
|
1596
|
+
...rec,
|
|
1597
|
+
status: "done",
|
|
1598
|
+
error: void 0,
|
|
1599
|
+
meta: { ...rec.meta, reconciledAfterRestart: true },
|
|
1600
|
+
updatedAt: Date.now()
|
|
1601
|
+
});
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1587
1605
|
out.push({ ...rec, status: "failed", error: "\u8FDB\u7A0B\u91CD\u542F\u4E2D\u65AD", updatedAt: Date.now() });
|
|
1588
1606
|
} else {
|
|
1589
1607
|
out.push({ ...rec });
|
|
@@ -4168,7 +4186,7 @@ function MarketTab({ notify, markets, onMutation, ops, favorites, profileKind, o
|
|
|
4168
4186
|
const r = await api("upgrade", { pkg: it.installedPkg });
|
|
4169
4187
|
const m = opUpgradeMeta2(r);
|
|
4170
4188
|
return m ? { ...r, opMeta: m } : r;
|
|
4171
|
-
});
|
|
4189
|
+
}, { toVersion: it.latest });
|
|
4172
4190
|
const degraded = oc.degradedOutcome(res);
|
|
4173
4191
|
if (degraded) {
|
|
4174
4192
|
notify({ kind: "warn", text: degraded.text });
|
|
@@ -4570,7 +4588,7 @@ function InstalledTab({ notify, installed, updates, onMutation, ops }) {
|
|
|
4570
4588
|
const r = await api("upgrade", { pkg: it.pkg });
|
|
4571
4589
|
const m = opUpgradeMeta2(r);
|
|
4572
4590
|
return m ? { ...r, opMeta: m } : r;
|
|
4573
|
-
});
|
|
4591
|
+
}, { toVersion: it.latestVersion });
|
|
4574
4592
|
const degraded = oc.degradedOutcome(res);
|
|
4575
4593
|
if (degraded) {
|
|
4576
4594
|
notify({ kind: "warn", text: degraded.text });
|
|
@@ -5216,7 +5234,7 @@ function DshmVersionChip({ version, notify, initialCheck, ops }) {
|
|
|
5216
5234
|
const res = await (ops ? ops.runOp("upgrade", "dsh-m", async () => {
|
|
5217
5235
|
const r = await api("self-upgrade");
|
|
5218
5236
|
return { ...r, opMeta: { from: version, to: r.version || "latest" } };
|
|
5219
|
-
}, { npm: "dsh-m" }) : api("self-upgrade"));
|
|
5237
|
+
}, { npm: "dsh-m", toVersion: state.latest }) : api("self-upgrade"));
|
|
5220
5238
|
clearSelfCheckCache2(typeof window !== "undefined" && window.localStorage ? window.localStorage : null);
|
|
5221
5239
|
setCheck({ current: version, latest: null, outdated: false, ahead: false });
|
|
5222
5240
|
notify({
|
|
@@ -5732,19 +5750,29 @@ function MarketPanel({ onClose }) {
|
|
|
5732
5750
|
if (opsPumpCtx && opsPumpCtx.syncOps === syncOps) opsPumpCtx = null;
|
|
5733
5751
|
};
|
|
5734
5752
|
}, [stillApplies, dispatchRestored, syncOps, refreshViews]);
|
|
5753
|
+
const installedVersionOf = useCallback(async (r) => {
|
|
5754
|
+
try {
|
|
5755
|
+
const fresh = await api("installed", { probe: false });
|
|
5756
|
+
const items = fresh && Array.isArray(fresh.items) ? fresh.items : [];
|
|
5757
|
+
const row = items.find((it) => it && it.pkg === r.target);
|
|
5758
|
+
return row && typeof row.version === "string" ? row.version : void 0;
|
|
5759
|
+
} catch {
|
|
5760
|
+
return void 0;
|
|
5761
|
+
}
|
|
5762
|
+
}, []);
|
|
5735
5763
|
const restoredRef = useRef(false);
|
|
5736
5764
|
useEffect(() => {
|
|
5737
5765
|
if (restoredRef.current || !installed.data) return;
|
|
5738
5766
|
restoredRef.current = true;
|
|
5739
5767
|
void (async () => {
|
|
5740
|
-
const restored = await restoreRecords2(opsStore.list(), stillApplies);
|
|
5768
|
+
const restored = await restoreRecords2(opsStore.list(), stillApplies, installedVersionOf);
|
|
5741
5769
|
opsStore.replaceAll(restored);
|
|
5742
5770
|
syncOps();
|
|
5743
5771
|
if (restored.some((r) => r.status === "queued")) {
|
|
5744
5772
|
void opsPump.kick();
|
|
5745
5773
|
}
|
|
5746
5774
|
})();
|
|
5747
|
-
}, [installed.data, stillApplies, syncOps]);
|
|
5775
|
+
}, [installed.data, stillApplies, installedVersionOf, syncOps]);
|
|
5748
5776
|
const counts = {
|
|
5749
5777
|
market: marketCommunity.data ? marketCommunity.data.total : null,
|
|
5750
5778
|
installed: installed.data ? installed.data.items.length : null
|
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"category": "essentials",
|
|
9
9
|
"alsoCategories": ["self-dev"],
|
|
10
10
|
"tags": ["市场", "插件管理"],
|
|
11
|
-
"verified": ["0.1.2-rc.1", "0.1.5-rc.1", "0.1.5-rc.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2"],
|
|
11
|
+
"verified": ["0.1.2-rc.1", "0.1.5-rc.1", "0.1.5-rc.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2", "0.2.1-rc.2"],
|
|
12
12
|
"source": "npm",
|
|
13
13
|
"npm": "dsh-m",
|
|
14
14
|
"github": "iasiv5/dsh-m",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"description": "替换官方 Connection 跳过 BrowserAuth,免 Token;已适配七个已审计精确版本对,详见仓库。仅支持 web profile;desktop 宿主一律自动休眠(多进程树判别),desktop 用户请保持最新版。",
|
|
92
92
|
"category": "self-dev",
|
|
93
93
|
"tags": ["BrowserAuth", "连接", "安全", "工具"],
|
|
94
|
-
"verified": ["0.1.2-rc.1", "0.1.5-rc.1", "0.1.5-rc.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2"],
|
|
94
|
+
"verified": ["0.1.2-rc.1", "0.1.5-rc.1", "0.1.5-rc.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2", "0.2.1-rc.2"],
|
|
95
95
|
"source": "npm",
|
|
96
96
|
"npm": "@iasiv5/dsh-skip-browser-auth",
|
|
97
97
|
"github": "iasiv5/dsh-skip-browser-auth",
|