@lone-wolf-akela/dsh-sandboxie-redirect 0.3.2 → 0.3.4

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 CHANGED
@@ -3,6 +3,39 @@
3
3
  Notable changes per release. The format is loose; the version numbers are what
4
4
  the DSH compatibility gate reads.
5
5
 
6
+ ## 0.3.4 — 2026-10-13
7
+
8
+ **`sandbox_clear` mode `status` no longer answers in `inspect`'s words**
9
+
10
+ - `render` gave every action except `clear` the inspect head line, so a status
11
+ query read `Sandbox copies for <workspace>: 0 found.` — which looks like "this
12
+ workspace has no copy" when the call says nothing about copies at all. `status`
13
+ now has its own head, `Session projection state for <workspace>.`, above the
14
+ projection detail that actually carries the information.
15
+ - `test/tool-execute.mjs` pins the rendered text of all three actions, plus the
16
+ empty and truncated copy lines, so the wording cannot silently fall through
17
+ again.
18
+
19
+ ## 0.3.3 — 2026-10-13
20
+
21
+ **`sandbox_clear` mode `status` never worked**
22
+
23
+ - `execute` referenced `workspace` in the `status` early return while the
24
+ `const workspace = …` that names it was declared below, in the same function
25
+ body. A `const` in its temporal dead zone throws on *any* earlier reference, so
26
+ `mode: "status"` failed on every call with `ReferenceError: Cannot access
27
+ 'workspace' before initialization`. The declaration now precedes every use,
28
+ which is also what `status` was always meant to report: the canonical workspace
29
+ alongside the projection registry's state for the calling session.
30
+ - The defect came in with the 0.2.1 import, so it shipped in 0.3.0, 0.3.1 and
31
+ 0.3.2; `inspect` and `clear` were unaffected, because they use `workspace`
32
+ after the declaration.
33
+ - New `test/tool-execute.mjs` drives all three modes of the real tool offline
34
+ (only the harness loader, the Node lookup and `spawnSync` are redirected), so
35
+ this — and any future runtime failure in a mode nobody exercises by hand — is a
36
+ failed test rather than a report from a user. It reproduces the
37
+ `ReferenceError` on the pre-fix source.
38
+
6
39
  ## 0.3.2 — 2026-10-13
7
40
 
8
41
  **DeepSeek Harness installation lookup**
package/README.md CHANGED
@@ -94,7 +94,7 @@ The preset carries an icon (two overlapping sheets) in the dropdown and the bott
94
94
 
95
95
  ### The `sandbox_clear` tool
96
96
 
97
- In-session, `sandbox_clear` inspects or discards this workspace's copy: `mode: "inspect"` reports (file count, size), `mode: "clear"` deletes the copy and its configuration. It works in every permission mode, and can only ever touch boxes Sandboxie attributes to *this* workspace.
97
+ In-session, `sandbox_clear` inspects or discards this workspace's copy: `mode: "inspect"` reports (file count, size), `mode: "clear"` deletes the copy and its configuration. It works in every permission mode, and can only ever touch boxes Sandboxie attributes to *this* workspace. A diagnostic `mode: "status"` reports what the session projection registry holds for the calling session — it separates "the fold never ran" from "the client never got it", so it is the first thing to look at when the title-bar box name is missing (it only actually worked from 0.3.3 on).
98
98
 
99
99
  ## Notes for users
100
100
 
package/README.zh.md CHANGED
@@ -93,7 +93,7 @@ DSH 的文件工具(读/写/编辑)在盒外运行,仍按「仅工作区
93
93
 
94
94
  ### sandbox_clear 工具
95
95
 
96
- 会话内可用 `sandbox_clear` 查看或清除本工作区的副本:`mode: "inspect"` 仅查看(文件数、占用),`mode: "clear"` 删除副本与配置。任何权限模式下都可用,且只能操作 Sandboxie 认定属于**本工作区**的沙盒。
96
+ 会话内可用 `sandbox_clear` 查看或清除本工作区的副本:`mode: "inspect"` 仅查看(文件数、占用),`mode: "clear"` 删除副本与配置。任何权限模式下都可用,且只能操作 Sandboxie 认定属于**本工作区**的沙盒。另有诊断用的 `mode: "status"`:它报告本会话投影登记的状态,用来分辨"投影没被驱动"和"客户端没收到"——标题栏的沙箱名称不显示时先看它(0.3.3 起才真正可用)。
97
97
 
98
98
  ## 用户注意事项
99
99
 
package/lib/tool.mjs CHANGED
@@ -208,10 +208,18 @@ export async function apply(ctx) {
208
208
  (copy) =>
209
209
  `- ${copy.box}: ${copy.files} file(s), ${humanBytes(copy.bytes)}${copy.truncated ? " (counting stopped early)" : ""} at ${copy.root}`
210
210
  );
211
- const head =
212
- value.action === "clear"
213
- ? `Cleared ${value.cleared.length} sandbox copy/copies for ${value.workspace}.`
214
- : `Sandbox copies for ${value.workspace}: ${value.copies.length} found.`;
211
+ // Every action gets its OWN head line. `status` used to fall through
212
+ // to the inspect wording, so a status query answered "N found." —
213
+ // which reads as "this workspace has no copy" when the call says
214
+ // nothing about copies at all; the informative part is the note.
215
+ let head;
216
+ if (value.action === "clear") {
217
+ head = `Cleared ${value.cleared.length} sandbox copy/copies for ${value.workspace}.`;
218
+ } else if (value.action === "status") {
219
+ head = `Session projection state for ${value.workspace}.`;
220
+ } else {
221
+ head = `Sandbox copies for ${value.workspace}: ${value.copies.length} found.`;
222
+ }
215
223
  return [{ type: "text", text: [head, ...lines, value.note].join("\n") }];
216
224
  }
217
225
  },
@@ -220,6 +228,13 @@ export async function apply(ctx) {
220
228
  if (typeof cwd !== "string" || cwd.length === 0) {
221
229
  throw new Error("sandbox_clear needs the calling session's workspace, and this caller has none");
222
230
  }
231
+ // Declared before ANY use. It used to sit below the `status` early
232
+ // return, inside the same function body — a temporal dead zone, so
233
+ // `mode: "status"` threw `ReferenceError: Cannot access 'workspace'
234
+ // before initialization` on every single call. test/tool-execute.mjs
235
+ // drives all three modes, so this class of failure is now a failed
236
+ // test rather than a bug report from a user.
237
+ const workspace = naming.canonicalWorkspace(cwd);
223
238
  if (args.mode === "status") {
224
239
  // Ask the projection registry what it holds for THIS session. The
225
240
  // header chip reads that value, so this separates "the fold never
@@ -236,7 +251,8 @@ export async function apply(ctx) {
236
251
  }
237
252
  log(`status: ${detail}`);
238
253
  return Promise.resolve({ action: "status", workspace, copies: [], cleared: [], note: detail });
239
- } const workspace = naming.canonicalWorkspace(cwd);
254
+ }
255
+
240
256
  const before = copiesFor(host, naming, workspace);
241
257
  if (before === null) {
242
258
  throw new Error(`cannot read ${host.sandboxIniPath()}, so the sandbox state is unknown; refusing to act`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lone-wolf-akela/dsh-sandboxie-redirect",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "DSH bundle adding a copy-on-write permission preset: shell commands run inside a per-workspace Sandboxie box, so writes outside the workspace land in the box's copy while the real disk is untouched.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -76,10 +76,11 @@
76
76
  }
77
77
  },
78
78
  "scripts": {
79
- "test": "node test/unit.mjs && node test/sbie-locate.mjs && node test/dsh-locate.mjs && node test/host-projection.mjs && node test/validate-patch.mjs",
79
+ "test": "node test/unit.mjs && node test/sbie-locate.mjs && node test/dsh-locate.mjs && node test/tool-execute.mjs && node test/host-projection.mjs && node test/validate-patch.mjs",
80
80
  "test:acceptance": "node test/run-tests.mjs",
81
81
  "test:soak": "node test/soak.mjs 30",
82
82
  "test:locate": "node test/sbie-locate.mjs && node test/dsh-locate.mjs",
83
+ "test:tool": "node test/tool-execute.mjs",
83
84
  "validate:patch": "node test/validate-patch.mjs",
84
85
  "pack:check": "npm pack --dry-run"
85
86
  },