@dsh-electron/dsh-plugin-multi-root-workspace 0.1.7 → 0.1.9

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.
Files changed (48) hide show
  1. package/CHANGELOG.en.md +16 -1
  2. package/CHANGELOG.md +16 -1
  3. package/README.en.md +21 -13
  4. package/README.md +29 -21
  5. package/cordis.patch.yml +18 -4
  6. package/lib/auto-review-packages-nRjnb4pU.js +15 -0
  7. package/lib/auto-review.js +166 -0
  8. package/lib/{command-CESuwlVt.js → command-Bwd6EGNV.js} +3 -3
  9. package/lib/command.js +1 -1
  10. package/lib/{compat-DF_yL1bB.js → compat-CagUNzRB.js} +176 -29
  11. package/lib/compat.js +1 -1
  12. package/lib/fork-CzbeWxHp.js +670 -0
  13. package/lib/{fs-9JIzGaf3.js → fs-BTXySwSG.js} +2 -6
  14. package/lib/fs.js +1 -1
  15. package/lib/index.js +8 -8
  16. package/lib/{instructions-D19jRxN0.js → instructions-CGNS3H0H.js} +211 -57
  17. package/lib/instructions.js +1 -1
  18. package/lib/lsp.js +1 -1
  19. package/lib/{registry-DCxC5Lay.js → registry-BClm6wfh.js} +6 -6
  20. package/lib/registry.js +1 -1
  21. package/lib/review-context-D-ohSVmA.js +98 -0
  22. package/lib/review-context.js +2 -0
  23. package/lib/{roots-B-0l8mNG.js → roots-Ca_W1S9n.js} +1 -1
  24. package/lib/{sandbox-Kup4_ZIb.js → sandbox-CXk5h-ct.js} +4 -8
  25. package/lib/sandbox.js +1 -1
  26. package/lib/scope.js +14 -5
  27. package/lib/types/auto-review/entry.d.ts +5 -0
  28. package/lib/types/compat/auto-review-contract.d.ts +3 -0
  29. package/lib/types/compat/auto-review-loader.d.ts +33 -0
  30. package/lib/types/compat/auto-review-packages.d.ts +1 -0
  31. package/lib/types/compat/dsh-version.d.ts +56 -8
  32. package/lib/types/compat/instruction-activity.d.ts +17 -0
  33. package/lib/types/compat/pty-marker.d.ts +1 -1
  34. package/lib/types/compat/review-session.d.ts +2 -0
  35. package/lib/types/compat.d.ts +15 -5
  36. package/lib/types/index.d.ts +1 -1
  37. package/lib/types/instructions.d.ts +18 -1
  38. package/lib/types/review-context.d.ts +49 -0
  39. package/lib/types/scope.d.ts +5 -0
  40. package/lib/windows-runner.js +2 -2
  41. package/lib/workspace-files.js +2 -2
  42. package/package.json +47 -7
  43. package/src/auto-review/FORK.md +26 -0
  44. package/src/auto-review/LICENSE +21 -0
  45. package/src/auto-review/README.en.md +22 -0
  46. package/src/auto-review/README.md +22 -0
  47. package/lib/{registry-lease-win32-DTO6QpT9.js → registry-lease-win32-DVTq9d4D.js} +1 -1
  48. package/lib/{windows-runner-contract-CEfmZzu0.js → windows-runner-contract-B5R2K3mM.js} +1 -1
@@ -1,10 +1,10 @@
1
- import { a as parseWindowsProfile, i as isWindowsNetworkOrDevicePath, n as assertWindowsDenyCapacity, t as DialectUnrecognizedError } from "./windows-runner-contract-CEfmZzu0.js";
2
- import { l as isCanonicallyUnder } from "./roots-B-0l8mNG.js";
1
+ import { a as parseWindowsProfile, i as isWindowsNetworkOrDevicePath, n as assertWindowsDenyCapacity, t as DialectUnrecognizedError } from "./windows-runner-contract-B5R2K3mM.js";
2
+ import { l as isCanonicallyUnder } from "./roots-Ca_W1S9n.js";
3
3
  import { brandMultiRootProvider } from "./providers.js";
4
4
  import { posix } from "node:path";
5
5
  import { SandboxUnavailableError, canonicalPath } from "@deepseek-ai/dsh-sandbox";
6
- import { LocalSandboxProvider } from "@deepseek-ai/dsh-sandbox-local";
7
6
  import { fileURLToPath } from "node:url";
7
+ import { LocalSandboxProvider } from "@deepseek-ai/dsh-sandbox-local";
8
8
  //#region src/compat/sandbox-confine.ts
9
9
  /** Whether a value is a thenable, i.e. whether the installed `confine` is async. */
10
10
  function isThenable(value) {
@@ -557,11 +557,7 @@ function windowsContained(candidate, root) {
557
557
  * grant mechanics stay the upstream implementation's.
558
558
  */
559
559
  var MultiRootSandboxProvider = class extends LocalSandboxProvider {
560
- static inject = [
561
- "multiRootCompat",
562
- "sandboxPolicy",
563
- "multiRootScope"
564
- ];
560
+ static inject = ["sandboxPolicy", "multiRootScope"];
565
561
  constructor(ctx, config) {
566
562
  super(ctx, config);
567
563
  brandMultiRootProvider(this, "sandbox");
package/lib/sandbox.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as MultiRootSandboxProvider } from "./sandbox-Kup4_ZIb.js";
1
+ import { t as MultiRootSandboxProvider } from "./sandbox-CXk5h-ct.js";
2
2
  import "./providers.js";
3
3
  export { MultiRootSandboxProvider, MultiRootSandboxProvider as default };
package/lib/scope.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
2
2
  import { r as effectiveRootAccess } from "./contract-DZ4zczDT.js";
3
- import { Service } from "@deepseek-ai/cordis";
4
3
  import { statSync } from "node:fs";
5
4
  import { isAbsolute } from "node:path";
6
- import { AsyncLocalStorage } from "node:async_hooks";
5
+ import { Service } from "@deepseek-ai/cordis";
7
6
  import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
8
  //#region src/scope.ts
9
9
  /**
10
10
  * The multi-root workspace scope: the plugin's single home for the question
@@ -210,8 +210,7 @@ var MultiRootScopeService = class extends Service {
210
210
  if (dshHome !== void 0 && (typeof dshHome !== "string" || dshHome.trim() === "" || !isAbsolute(dshHome))) ctx.logger.error(`multi-root-workspace: invalid dshHome config (expected an absolute path, got ${JSON.stringify(dshHome)}); the DSH-home deny boundary is disabled`);
211
211
  else this.dshHome = dshHome;
212
212
  aroundTool(ctx, (exec, next) => {
213
- const parent = toolCapStore.getStore();
214
- return toolCapStore.run({ capped: parent?.capped === true || this.caps[exec.name] === "read-only" }, next);
213
+ return toolCapStore.run({ capped: this.capForTool(exec.name) }, next);
215
214
  });
216
215
  ctx.inject(["systemPrompt", "sandboxPolicy"], (scope) => {
217
216
  scope.systemPrompt.context({
@@ -243,9 +242,19 @@ var MultiRootScopeService = class extends Service {
243
242
  * @returns the canonical scope; `additionalRoots` is empty when none are registered.
244
243
  */
245
244
  resolve(policy) {
245
+ return this.project(policy, this.capped());
246
+ }
247
+ /** Read-only pending-dispatch projection. Does not mint an ALS execution grant. */
248
+ previewForTool(policy, toolName) {
249
+ return this.project(policy, this.capForTool(toolName));
250
+ }
251
+ /** Execution and review use exactly the same parent-narrowing rule. */
252
+ capForTool(toolName) {
253
+ return this.capsInvalid || toolCapStore.getStore()?.capped === true || this.caps[toolName] === "read-only";
254
+ }
255
+ project(policy, capped) {
246
256
  const primaryRoot = canonicalPath(policy.workspaceRoot);
247
257
  const roots = this.membersOf(primaryRoot);
248
- const capped = this.capped();
249
258
  const writable = capped || this.registryAuthority === "unavailable" ? [] : roots.filter((root) => effectivelyWritable(policy.mode, root.access)).map((root) => root.path);
250
259
  const denied = (this.rootsByPrimary.get(primaryRoot) ?? []).filter((root) => typeof root.recordedPath === "string" && root.recordedPath !== "" && root.recordedPath !== primaryRoot && (capped || !effectivelyWritable(policy.mode, root.access))).map((root) => root.recordedPath);
251
260
  const deniedRoots = [...new Set(denied)];
@@ -0,0 +1,5 @@
1
+ import type { Context } from '@deepseek-ai/cordis'
2
+ /** Optional Auto Review Loader entry; supported only on DSH 0.2.1-rc.2. */
3
+ export declare const name: string
4
+ export declare const inject: string[]
5
+ export declare function apply(ctx: Context): Promise<void>
@@ -0,0 +1,3 @@
1
+ /** The companion's joint support contract is deliberately narrower than the ordinary bundle. */
2
+ export declare const AUTO_REVIEW_RELEASE = "0.2.1-rc.2";
3
+ export declare function assertAutoReviewRelease(release: string | undefined): void;
@@ -0,0 +1,33 @@
1
+ /** Scoped takeover of public Loader entries; no profile file is written. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ export declare const OFFICIAL_AUTO_REVIEW = "@deepseek-ai/dsh-experimental-auto-review";
4
+ export declare const LEGACY_AUTO_REVIEW = "@dsh-electron/dsh-plugin-multi-root-auto-review";
5
+ /**
6
+ * internal/plugin is emitted before Fiber checks dependencies or runs apply.
7
+ * Disposing there also stops an import already in flight when takeover began.
8
+ * The group update wrapper preserves desired configuration and drains our
9
+ * owner BEFORE the update that lets the official owner run again.
10
+ */
11
+ export declare class AutoReviewTakeover {
12
+ private readonly ctx;
13
+ private readonly entry;
14
+ private readonly group;
15
+ private readonly restoreUpdate;
16
+ private readonly predecessor;
17
+ private readonly closed;
18
+ private releaseClosed;
19
+ readonly stopHook: () => void;
20
+ private desired;
21
+ private stopOwner;
22
+ private exiting;
23
+ private closing;
24
+ private readonly draining;
25
+ constructor(ctx: Context);
26
+ private isDisabled;
27
+ private suppress;
28
+ suspendOfficial(): Promise<void>;
29
+ /** Called before any asynchronous startup, so early unload also drains it. */
30
+ setOwnerDisposer(stop: () => Promise<void>): void;
31
+ close(restore?: boolean): Promise<void>;
32
+ private finish;
33
+ }
@@ -0,0 +1 @@
1
+ export declare function assertForkPackages(): void;
@@ -43,10 +43,43 @@ export declare const REQUIRED_CORE_PACKAGES: readonly ["@deepseek-ai/dsh-fs", "@
43
43
  * that is the mixed-installation failure this contract exists to catch.
44
44
  */
45
45
  export declare const OPTIONAL_CORE_PACKAGES: readonly ["@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-working-directory", "@deepseek-ai/dsh-lsp", "@deepseek-ai/dsh-lsp-stdio", "@deepseek-ai/dsh-api-workspace-files", "@deepseek-ai/dsh-typert-protocol", "@deepseek-ai/dsh-sandbox-windows-acl", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-subprocess", "@deepseek-ai/dsh-system-prompt"];
46
+ /**
47
+ * The optional packages this plugin loads itself at run time, through dynamic
48
+ * `import()`s inside this package's own modules. The copy this module resolves
49
+ * IS the copy that would execute, so every resolvable hit testifies — a
50
+ * private copy inside this package's own tree genuinely loads, and a version
51
+ * that disagrees with the host is a real mixed installation, not a phantom.
52
+ */
53
+ export declare const RUNTIME_OPTIONAL_PACKAGES: readonly ["@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-typert-protocol"];
54
+ /**
55
+ * The optional packages this plugin consumes only as mounted host services or
56
+ * ambient types — it never imports them, so a copy inside this package's own
57
+ * tree can never execute. The only version that testifies is the one the
58
+ * COMPOSITION resolves (the installation or the profile): a resolution that
59
+ * lands inside this package's own root is a private development or bundled
60
+ * copy and must be reported absent — otherwise a `link:`-installed checkout
61
+ * whose devDependencies carry a newer release phantom-mixes every supported
62
+ * host it is developed against (the report that motivated this split:
63
+ * `dsh-lsp`/`dsh-lsp-stdio`/`dsh-working-directory` resolving to the plugin's
64
+ * devDependencies on a `0.2.0-rc.2` host produced a `mixed` verdict on a
65
+ * uniformly `0.2.0-rc.2` installation).
66
+ */
67
+ export declare const HOST_SERVICE_PACKAGES: readonly ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-api-workspace-files", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-lsp", "@deepseek-ai/dsh-lsp-stdio", "@deepseek-ai/dsh-subprocess", "@deepseek-ai/dsh-system-prompt", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-working-directory"];
68
+ /**
69
+ * Optional packages this plugin executes that are resolved through an anchor
70
+ * OTHER than this module. The standalone Windows ACL runner
71
+ * (`src/windows-runner.ts`) imports `@deepseek-ai/dsh-sandbox-windows-acl` by
72
+ * self-reference from the upstream runner's own install location — a file the
73
+ * installed `dsh-sandbox-local` points at in its confined argv — so the copy
74
+ * that testifies is the one sibling to that required package, not whatever
75
+ * this module can reach. Neither the self-resolution hit nor the
76
+ * `@deepseek-ai/dsh` host anchor reflects execution here: if sandbox-local's
77
+ * own anchor cannot see the package, the runner cannot load it either, and
78
+ * absent is the honest answer.
79
+ */
80
+ export declare const RUNNER_ANCHORED_PACKAGES: readonly ["@deepseek-ai/dsh-sandbox-windows-acl"];
46
81
  /** Every package the contract inspects, required first. */
47
82
  export declare const CORE_PACKAGES: readonly ["@deepseek-ai/dsh-fs", "@deepseek-ai/dsh-fs-local", "@deepseek-ai/dsh-sandbox", "@deepseek-ai/dsh-sandbox-local", "@deepseek-ai/dsh-sandbox-policy", "@deepseek-ai/dsh-storage-domain", "@deepseek-ai/dsh-tools", "@deepseek-ai/dsh-working-directory", "@deepseek-ai/dsh-lsp", "@deepseek-ai/dsh-lsp-stdio", "@deepseek-ai/dsh-api-workspace-files", "@deepseek-ai/dsh-typert-protocol", "@deepseek-ai/dsh-sandbox-windows-acl", "@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-agent-instructions", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-commands", "@deepseek-ai/dsh-llm", "@deepseek-ai/dsh-session", "@deepseek-ai/dsh-subprocess", "@deepseek-ai/dsh-system-prompt"];
48
- /** Services looked up structurally; older runtimes never install these modules. */
49
- export declare const HOST_RESOLVED_PACKAGES: readonly ["@deepseek-ai/dsh-working-directory"];
50
83
  /** How this plugin reacts to an installation it does not support. */
51
84
  export type CompatEnforcement = 'enforce' | 'warn';
52
85
  /** The environment variable that relaxes the gate. */
@@ -85,12 +118,27 @@ export type VersionReader = (packageName: string) => string | undefined;
85
118
  /**
86
119
  * Read one package's declared version through Node resolution.
87
120
  *
88
- * Resolution runs from THIS module, which is what makes the answer meaningful:
89
- * the upstream packages are peer dependencies, so they resolve to the single
90
- * copy the host provides — the same copy the providers will subclass at
91
- * runtime. A package that cannot be resolved is reported absent rather than
92
- * throwing, because "not installed" is a legitimate answer for every optional
93
- * package.
121
+ * Resolution runs from THIS module — for required and runtime-loaded packages
122
+ * the copy found here is the copy that would execute, which is what makes the
123
+ * answer meaningful: the upstream packages are peer dependencies, so they
124
+ * resolve to the single copy the host provides — the same copy the providers
125
+ * will subclass at runtime.
126
+ *
127
+ * {@link HOST_SERVICE_PACKAGES} are different: the plugin never imports them,
128
+ * so a copy inside this package's own tree can never execute, and counting it
129
+ * would report a mixed installation out of a linked checkout's devDependencies
130
+ * alone. Only a hit OUTSIDE this package's root — a copy the composition could
131
+ * mount — testifies; when this module cannot reach the package at all, the
132
+ * `@deepseek-ai/dsh` host manifest supplies a second anchor for host-internal
133
+ * packages that are never plugin peers.
134
+ *
135
+ * {@link RUNNER_ANCHORED_PACKAGES} are a third policy: executed, but resolved
136
+ * from the upstream-runner anchor rather than this module, so only a hit
137
+ * sibling to the installed `dsh-sandbox-local` testifies.
138
+ *
139
+ * A package that cannot be resolved in either place is reported absent rather
140
+ * than throwing, because "not installed" is a legitimate answer for every
141
+ * optional package.
94
142
  * @param packageName - the package to inspect.
95
143
  * @returns the declared version, or `undefined` when the package or its
96
144
  * manifest cannot be resolved.
@@ -0,0 +1,17 @@
1
+ export type FileActivity = {
2
+ kind: 'start';
3
+ id: string;
4
+ name: string;
5
+ arguments: string;
6
+ } | {
7
+ kind: 'end';
8
+ id: string;
9
+ failed: boolean;
10
+ };
11
+ export declare function ptcFileActivity(event: unknown): FileActivity | undefined;
12
+ /** Rebuild read-only discovery candidates from successful durable activity after resume. */
13
+ export declare function replayedInstructionTargets(events: readonly unknown[], origin: string | undefined): readonly string[];
14
+ /** fs tools whose success touches the file at their `file_path` argument. */
15
+ export declare const FILE_TOUCH_TOOL_NAMES: Record<string, true>;
16
+ /** One explicit fs-tool target, shared with live touch capture. */
17
+ export declare function touchedPathOfToolCall(name: string, argumentsJson: string): string | undefined;
@@ -21,7 +21,7 @@
21
21
  * Resolution follows the optional-peer precedent (`agent-instructions.ts`):
22
22
  * the backend is not a peer of this plugin, so the plugin anchor is tried
23
23
  * first (flat layouts) and the `@deepseek-ai/dsh` host anchor second — the
24
- * same `HOST_RESOLVED_PACKAGES` pattern as `dsh-version.ts` — because the
24
+ * same host-anchor fallback pattern as `dsh-version.ts` — because the
25
25
  * backend rides inside the harness meta package's own dependency tree.
26
26
  *
27
27
  * @module @dsh-electron/dsh-plugin-multi-root-workspace/compat/pty-marker
@@ -0,0 +1,2 @@
1
+ import type { Session } from '@deepseek-ai/dsh-session';
2
+ export declare function nativeInstructionFingerprint(session: Session): string;
@@ -2,16 +2,26 @@
2
2
  * `multi-root-compat`: the startup gate that turns the DSH compatibility
3
3
  * contract from documentation into a precondition.
4
4
  *
5
- * The four security-relevant rows of this bundle — `multi-root-fs`,
6
- * `multi-root-sandbox`, `multi-root-registry`, `multi-root-instructions` —
7
- * inject `multiRootCompat`. Cordis will not start a plugin whose injected
8
- * service is absent, so this row is what decides whether they run at all:
5
+ * Every widened-authority row of this bundle — `multi-root-providers`,
6
+ * `multi-root-registry`, `multi-root-instructions`, `multi-root-lsp`,
7
+ * `multi-root-workspace-files`, `multi-root-process-fence` — injects
8
+ * `multiRootCompat`. Cordis will not start a plugin whose injected service is
9
+ * absent, so this row is what decides whether they run at all:
9
10
  *
10
11
  * ```text
11
- * compat check passes → ctx.multiRootCompat exists → the providers start
12
+ * compat check passes → ctx.multiRootCompat exists → the gated rows start
12
13
  * compat check fails → the row throws → they never start
13
14
  * ```
14
15
  *
16
+ * The two PROVIDER rows (`multi-root-fs`, `multi-root-sandbox`) deliberately
17
+ * do NOT inject the gate: their widening is scope-driven, and the gated
18
+ * registry can never populate the scope on a refused installation — so they
19
+ * degenerate to the upstream providers. That is what keeps a refused gate a
20
+ * loud degradation (the plugin's features absent, the profile intact) instead
21
+ * of a dead profile: upstream `fs-sandbox`/`sandbox` are already disabled by
22
+ * the patch, so holding `ctx.fs`/`ctx.sandbox` back would take `ctx.shell`,
23
+ * `permissionPresets` and every confining tool down with them.
24
+ *
15
25
  * That is why the gate is a plain `apply` and not a `Service` subclass mounted
16
26
  * directly: the check has to be able to fail BEFORE the service exists. A
17
27
  * `Service` constructor has already run `super(ctx, name)` — and therefore
@@ -21,7 +21,7 @@
21
21
  * @module @dsh-electron/dsh-plugin-multi-root-workspace
22
22
  */
23
23
  export { DshCompatUnsupportedError, MultiRootCompatService, assertSupportedInstallation } from './compat.ts';
24
- export { classifyInstallation, compatEnforcement, CORE_PACKAGES, OPTIONAL_CORE_PACKAGES, readInstalledVersion, REQUIRED_CORE_PACKAGES, SUPPORTED_DSH_RELEASES, } from './compat/dsh-version.ts';
24
+ export { classifyInstallation, compatEnforcement, CORE_PACKAGES, HOST_SERVICE_PACKAGES, OPTIONAL_CORE_PACKAGES, readInstalledVersion, REQUIRED_CORE_PACKAGES, RUNNER_ANCHORED_PACKAGES, RUNTIME_OPTIONAL_PACKAGES, SUPPORTED_DSH_RELEASES, } from './compat/dsh-version.ts';
25
25
  export type { CompatEnforcement, CompatReport, CompatVerdict, InspectedPackage, SupportedDshRelease, VersionReader, } from './compat/dsh-version.ts';
26
26
  export { instructionsApi, renderInstructions } from './compat/agent-instructions.ts';
27
27
  export type { InstructionsApi, RenderedInstructions } from './compat/agent-instructions.ts';
@@ -46,6 +46,23 @@
46
46
  * @module @dsh-electron/dsh-plugin-multi-root-workspace/instructions
47
47
  */
48
48
  import { Context } from '@deepseek-ai/cordis';
49
+ import type { Agent } from '@deepseek-ai/dsh-agent';
50
+ declare module '@deepseek-ai/cordis' {
51
+ interface Context {
52
+ multiRootInstructions: {
53
+ knownRoots(session: object): readonly string[];
54
+ snapshot(agent: Agent, roots: readonly string[], target: string | undefined, signal: AbortSignal): Promise<readonly CurrentRootInstruction[]>;
55
+ };
56
+ }
57
+ }
58
+ /** Current constraints; never delivery deltas or authorization. */
59
+ export interface CurrentRootInstruction {
60
+ readonly root: string;
61
+ readonly path: string;
62
+ readonly relativeDirectory: string;
63
+ readonly digest: string;
64
+ readonly text: string;
65
+ }
49
66
  /** The `plugin` attribution every message this row produces carries. */
50
67
  export declare const PLUGIN_SOURCE = "@dsh-electron/dsh-plugin-multi-root-workspace";
51
68
  /**
@@ -91,7 +108,7 @@ export interface RemovedScope {
91
108
  * @param argumentsJson - the tool call's raw arguments, exactly as produced.
92
109
  * @returns the trimmed absolute-or-relative path, or `undefined`.
93
110
  */
94
- export declare function touchedPathOfToolCall(name: string, argumentsJson: string): string | undefined;
111
+ export { touchedPathOfToolCall } from './compat/instruction-activity.ts';
95
112
  /**
96
113
  * Compose the model-facing message body for one batch of changes.
97
114
  *
@@ -0,0 +1,49 @@
1
+ import { Context, Service } from '@deepseek-ai/cordis';
2
+ import type { Agent } from '@deepseek-ai/dsh-agent';
3
+ import type { CurrentRootInstruction } from './instructions.ts';
4
+ declare module '@deepseek-ai/cordis' {
5
+ interface Context {
6
+ multiRootReviewContext: MultiRootReviewContext;
7
+ }
8
+ }
9
+ export interface ReviewExecution {
10
+ readonly agent?: Agent;
11
+ readonly name: string;
12
+ readonly arguments: unknown;
13
+ }
14
+ export interface ReviewContext {
15
+ readonly schemaVersion: 1;
16
+ readonly environment: {
17
+ readonly sessionOrigin: string;
18
+ readonly effectiveCwd: string;
19
+ readonly sandboxMode: string;
20
+ readonly registryAuthority: 'available' | 'unavailable';
21
+ readonly roots: readonly {
22
+ readonly path: string;
23
+ readonly access: string;
24
+ readonly effectiveWritable: boolean;
25
+ }[];
26
+ readonly writableRoots: readonly string[];
27
+ readonly deniedRoots: readonly string[];
28
+ readonly protectedHome?: string;
29
+ /** Full access permits unregistered paths subject to the existing deny fence. */
30
+ readonly ambientWrites: boolean;
31
+ readonly readConfinement: false;
32
+ readonly primaryRootWritable: boolean;
33
+ readonly writeBoundary: string;
34
+ };
35
+ /** Provenance from current scope and the existing delivery index; never a grant. */
36
+ readonly instructionProvenanceRoots: readonly string[];
37
+ readonly constraints: readonly CurrentRootInstruction[];
38
+ readonly completeness: 'complete';
39
+ readonly fingerprint: string;
40
+ }
41
+ /** All authority remains in the existing Registry/scope and instruction index. */
42
+ export declare class MultiRootReviewContext extends Service {
43
+ static inject: string[];
44
+ constructor(ctx: Context);
45
+ assertCompatible(): void;
46
+ build(exec: ReviewExecution, signal: AbortSignal): Promise<ReviewContext>;
47
+ assertCurrent(exec: ReviewExecution, snapshot: ReviewContext, signal: AbortSignal): Promise<void>;
48
+ }
49
+ export default MultiRootReviewContext;
@@ -245,6 +245,11 @@ export declare class MultiRootScopeService extends Service {
245
245
  * @returns the canonical scope; `additionalRoots` is empty when none are registered.
246
246
  */
247
247
  resolve(policy: SandboxExecutionPolicy): FilesystemScope;
248
+ /** Read-only pending-dispatch projection. Does not mint an ALS execution grant. */
249
+ previewForTool(policy: SandboxExecutionPolicy, toolName: string): FilesystemScope;
250
+ /** Execution and review use exactly the same parent-narrowing rule. */
251
+ private capForTool;
252
+ private project;
248
253
  /**
249
254
  * Whether THIS call's additional-root writes are capped. Inside a tool
250
255
  * dispatch the AsyncLocalStorage store answers; outside any dispatch (user
@@ -1,8 +1,8 @@
1
- import { a as parseWindowsProfile, i as isWindowsNetworkOrDevicePath, n as assertWindowsDenyCapacity, o as rootDenySid, r as canonicalPath, s as workspaceScopeSid } from "./windows-runner-contract-CEfmZzu0.js";
1
+ import { a as parseWindowsProfile, i as isWindowsNetworkOrDevicePath, n as assertWindowsDenyCapacity, o as rootDenySid, r as canonicalPath, s as workspaceScopeSid } from "./windows-runner-contract-B5R2K3mM.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { closeSync, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, statSync } from "node:fs";
4
- import { basename, dirname, isAbsolute, join, win32 } from "node:path";
5
4
  import { createHash } from "node:crypto";
5
+ import { basename, dirname, isAbsolute, join, win32 } from "node:path";
6
6
  import { pathToFileURL } from "node:url";
7
7
  import { createConnection } from "node:net";
8
8
  //#region src/compat/windows-native.ts
@@ -1,6 +1,6 @@
1
- import { l as isCanonicallyUnder } from "./roots-B-0l8mNG.js";
2
- import { t as routeWorkspacePath } from "./workspace-routing-YPxaQ4V3.js";
3
1
  import { t as wrapMethod } from "./method-wrapper-CFY3p3j2.js";
2
+ import { l as isCanonicallyUnder } from "./roots-Ca_W1S9n.js";
3
+ import { t as routeWorkspacePath } from "./workspace-routing-YPxaQ4V3.js";
4
4
  import { posix, resolve, win32 } from "node:path";
5
5
  //#region src/compat/workspace-files.ts
6
6
  function adaptPathWatch(service, wrap) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dsh-electron/dsh-plugin-multi-root-workspace",
3
3
  "description": "Multi-root Workspace for DeepSeek Harness: adds N additional roots to the workspace sandbox scope as an out-of-tree bundle",
4
- "version": "0.1.7",
4
+ "version": "0.1.9",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -62,6 +62,14 @@
62
62
  "./windows-runner": {
63
63
  "types": "./lib/types/windows-runner.d.ts",
64
64
  "default": "./lib/windows-runner.js"
65
+ },
66
+ "./review-context": {
67
+ "types": "./lib/types/review-context.d.ts",
68
+ "default": "./lib/review-context.js"
69
+ },
70
+ "./auto-review": {
71
+ "types": "./lib/types/auto-review/entry.d.ts",
72
+ "default": "./lib/auto-review.js"
65
73
  }
66
74
  },
67
75
  "files": [
@@ -75,7 +83,11 @@
75
83
  "CHANGELOG.en.md",
76
84
  "LICENSE",
77
85
  "scripts/windows-broker/*.ps1",
78
- "scripts/windows-broker/*.cs"
86
+ "scripts/windows-broker/*.cs",
87
+ "src/auto-review/FORK.md",
88
+ "src/auto-review/LICENSE",
89
+ "src/auto-review/README.md",
90
+ "src/auto-review/README.en.md"
79
91
  ],
80
92
  "publishConfig": {
81
93
  "access": "public"
@@ -109,7 +121,9 @@
109
121
  "@deepseek-ai/dsh-subprocess": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2",
110
122
  "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2",
111
123
  "@deepseek-ai/dsh-tools": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2",
112
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2"
124
+ "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2",
125
+ "@deepseek-ai/dsh-permission-presets": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2",
126
+ "@deepseek-ai/dsh-util-values": "0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.1 || 0.2.1-rc.2"
113
127
  },
114
128
  "peerDependenciesMeta": {
115
129
  "@deepseek-ai/dsh-agent": {
@@ -153,6 +167,12 @@
153
167
  },
154
168
  "@deepseek-ai/dsh-tools": {
155
169
  "optional": true
170
+ },
171
+ "@deepseek-ai/dsh-permission-presets": {
172
+ "optional": true
173
+ },
174
+ "@deepseek-ai/dsh-util-values": {
175
+ "optional": true
156
176
  }
157
177
  },
158
178
  "devDependencies": {
@@ -212,7 +232,25 @@
212
232
  "typescript": "^6.0.3",
213
233
  "vitest": "^4.1.8",
214
234
  "yaml": "^2.9.0",
215
- "zustand": "~4.5.7"
235
+ "zustand": "~4.5.7",
236
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-rc.2",
237
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-rc.2",
238
+ "@deepseek-ai/dsh-bash-sandbox": "0.2.1-rc.2",
239
+ "@deepseek-ai/dsh-compaction": "0.2.1-rc.2",
240
+ "@deepseek-ai/dsh-fs-observation-policy": "0.2.1-rc.2",
241
+ "@deepseek-ai/dsh-llm-deepseek": "0.2.1-rc.2",
242
+ "@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.1-rc.2",
243
+ "@deepseek-ai/dsh-permission-presets": "0.2.1-rc.2",
244
+ "@deepseek-ai/dsh-ptc-runtime-node": "0.2.1-rc.2",
245
+ "@deepseek-ai/dsh-shell": "0.2.1-rc.2",
246
+ "@deepseek-ai/dsh-shell-env": "0.2.1-rc.2",
247
+ "@deepseek-ai/dsh-subagent": "0.2.1-rc.2",
248
+ "@deepseek-ai/dsh-tool-bash": "0.2.1-rc.2",
249
+ "@deepseek-ai/dsh-tool-fs": "0.2.1-rc.2",
250
+ "@deepseek-ai/dsh-tool-subagent": "0.2.1-rc.2",
251
+ "@deepseek-ai/dsh-user-approval": "0.2.1-rc.2",
252
+ "@deepseek-ai/dsh-working-directory": "0.2.1-rc.2",
253
+ "@deepseek-ai/dsh-util-values": "0.2.1-rc.2"
216
254
  },
217
255
  "dsh": {
218
256
  "bundle": {
@@ -236,7 +274,7 @@
236
274
  "scripts": {
237
275
  "bench:roots": "node --experimental-transform-types scripts/bench-root-scale.mjs",
238
276
  "build": "pnpm run build:types && pnpm run bundle",
239
- "build:types": "tsc -p tsconfig.host.json && tsc -p tsconfig.client.json",
277
+ "build:types": "tsc -p tsconfig.host.json && tsc -p tsconfig.client.json && node scripts/build-auto-review.mjs",
240
278
  "bundle": "node scripts/clean-lib.mjs && tsdown",
241
279
  "compat:check": "node scripts/check-dsh-compat.mjs",
242
280
  "docs:check": "node scripts/check-docs.mjs",
@@ -251,7 +289,9 @@
251
289
  "smoke:packed": "node scripts/smoke-packed.mjs",
252
290
  "test": "vitest run",
253
291
  "test:watch": "vitest",
254
- "typecheck": "tsc -p tsconfig.host.json --noEmit && tsc -p tsconfig.client.json --noEmit",
255
- "verify:all": "pnpm lint && pnpm typecheck && pnpm build && pnpm kernel:probe && pnpm test && pnpm smoke && pnpm pack:check && pnpm smoke:packed"
292
+ "typecheck": "tsc -p tsconfig.host.json --noEmit && tsc -p tsconfig.client.json --noEmit && node scripts/build-auto-review.mjs",
293
+ "verify:all": "pnpm lint && pnpm typecheck && pnpm build && pnpm kernel:probe && pnpm test && pnpm smoke && pnpm pack:check && pnpm smoke:packed && pnpm auto-review:fork && pnpm smoke:auto-review",
294
+ "auto-review:fork": "node scripts/check-auto-review-fork.mjs",
295
+ "smoke:auto-review": "node scripts/verify-auto-review.mjs"
256
296
  }
257
297
  }
@@ -0,0 +1,26 @@
1
+ # Auto Review fork
2
+
3
+ 基线:DeepSeek Harness `dsh-v0.2.1-rc.2`,commit `687f282e8625c6b8d11ff58211a90524be2e4317`,`packages/experimental/auto-review/src/index.ts`。原文件保存在 `upstream.ts`;MIT 许可保存在 `LICENSE`。
4
+
5
+ 允许差异:兼容层身份及必需服务;调用只读宿主 context builder;环境数据及当前 constraint 数据;native 副本的 metadata/digest 校验与去重;发送前、模型等待后、后续 gate 后和 dispatch 前的失败关闭/陈旧校验。dispatch 复核使用 registry token,涵盖人工批准等待,并随 owner 生命周期取消和 drain。
6
+
7
+ 风险 policy、human/direct-parent/checkpoint/fact 角色判定、native/PTC 身份、严格输出协议、ask/never、下游 gate 与卸载时 Session 迁移保持官方语义。新增当前项目文本没有授权身份。没有全局 LLM hook、提示词文本匹配或第二 reviewer。
8
+
9
+ 同步:先核对发布包与 tag 源码;人工审阅上游 policy、身份与 lifecycle 差异;更新 `upstream.ts` 和基线哈希;重放最小 context 差异;更新 `fork.patch`;运行差分门禁、官方回归、联合工具/装配/packed 与原生内核验证。绿色测试不能自动扩大联合支持版本。正式 context contribution API 足够后迁移 collector,移除 fork,保留联合测试。
10
+
11
+ Native 协调只使用现有 scope/delivery 索引证明的附加根来源;纯附加根旧帧留作 fact,以新快照替代。混合 native 帧若含陈旧的附加文件,公开接口不足以无损拆出 global/primary 正文,故拒绝本次审查并要求刷新 baseline。未登记 cwd 的 native 项目约束保持官方身份。
12
+
13
+
14
+ 逐文件维护范围:
15
+
16
+ | 文件 | 来源/职责 |
17
+ |---|---|
18
+ | `upstream.ts` | 原始官方入口,哈希固定,不能当实现文件编辑 |
19
+ | `fork.ts` / `fork.patch` | 可执行 fork / 人工审阅的唯一入口差异 |
20
+ | `context.ts` | 当前 native baseline、scope metadata、历史 fact 与新鲜 constraint 分区 |
21
+ | `../compat/auto-review-packages.ts` | 精确执行副本门禁 |
22
+ | `../../tests/auto-review/upstream.spec.ts` / `../../tests/auto-review/parent.ts` | 同一 commit 的官方回归和 parent fixture;只调整导入、context stub 及新增环境字段断言 |
23
+ | `entry.ts` / `../compat/auto-review-loader.ts` | 单开关的 context/owner 生命周期、运行时接管与恢复 |
24
+ | `../../tests/auto-review/` 与 joint smoke | 上下文、工具、接管、启停和单包安装验证 |
25
+
26
+ 主包的 `review-context` 与 instructions facade 是本地接口,不是上游正式 API。不再有独立 companion manifest 或主包 peer;普通 allowlist 的提升不能代替 fork 的同步和联合验收。
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,22 @@
1
+ # Optional Auto Review
2
+
3
+ 中文:[README.md](./README.md)
4
+
5
+ Auto Review is included at `@dsh-electron/dsh-plugin-multi-root-workspace/auto-review` and supports only DSH `0.2.1-rc.2`. After installing the main package, expand Multi-root Workspace's row list in the Plugin Manager and enable the `@dsh-electron/dsh-plugin-multi-root-workspace/auto-review` row (its `cordis.patch.yml` row id is `multi-root-auto-review`). This row ships disabled: while off, it mounts neither the reviewer nor review context and does not register the Auto preset. Profiles without hot reload require a restart, as reported by the manager.
6
+
7
+ The one switch mounts both current multi-root context and the reviewer, taking over the sibling official `@deepseek-ai/dsh-experimental-auto-review` row at runtime. Either bundle order works, and subsequent reloads retain one owner. Takeover does not change the official row's saved configuration. After disabling, reload/restart restores the official owner only if its bundle is still selected and its original configuration allows it to run; an unselected official bundle is not installed or enabled automatically. When the official bundle is not selected, the row still provides the same reviewer standalone (it registers the Auto preset itself); there is simply no official owner to take over.
8
+
9
+ Alternatively, set this in the profile's `cordis.patch.yml`:
10
+
11
+ ```yaml
12
+ - id: multi-root-auto-review
13
+ disabled: false
14
+ ```
15
+
16
+ Unloading a live Auto owner preserves official behavior: Auto sessions move to Full access, and a replacement owner does not automatically switch them back. Select Auto again in the session when needed. Multi-root write fences remain enforced.
17
+
18
+ To migrate from the former companion, stop the profile, remove its bundle selection and `@dsh-electron/dsh-plugin-multi-root-auto-review` dependency, then install/update the main package and enable the row above. The existing `dsh plugin --profile <name> remove @dsh-electron/dsh-plugin-multi-root-auto-review` command can remove the old package; preserve the official bundle's existing selection. The old configure command is retired. Coexistence with a selected legacy companion produces an explicit startup diagnostic and never silently rewrites the user's manifest.
19
+
20
+ Constraint roles, budgets, mixed native frames, and freshness retain the existing fork semantics: current topology and instructions enter the reviewer's data sections; project text only constrains actions. Budget, I/O, cancellation, or snapshot changes fail that call. bash/pwsh collection covers known directory chains and cannot infer every target of an arbitrary script. Automatic source-file reading remains outside scope.
21
+
22
+ See [FORK.md](./FORK.md) for the baseline, permitted differences, and synchronization procedure.
@@ -0,0 +1,22 @@
1
+ # 可选 Auto Review
2
+
3
+ English: [README.en.md](./README.en.md)
4
+
5
+ Auto Review 已内置于 `@dsh-electron/dsh-plugin-multi-root-workspace/auto-review`,仅支持 DSH `0.2.1-rc.2`。安装主包后,在插件管理器中展开 Multi-root Workspace 的行列表,打开 `@dsh-electron/dsh-plugin-multi-root-workspace/auto-review` 行(`cordis.patch.yml` 中的行 id 为 `multi-root-auto-review`)。该行出厂关闭;关闭时不挂载 reviewer 或 review context,也不注册 Auto preset。无热重载的 profile 需要按管理器提示重启。
6
+
7
+ 启用后,同一个开关挂载当前多根 context 与 reviewer,并在运行时停止同组官方 `@deepseek-ai/dsh-experimental-auto-review` 行。官方 bundle 位于主包前后均可;后续 reload 仍保持单一 owner。接管不修改官方的持久配置。关闭后,官方仅在仍被选择且原配置允许启用时随 reload/restart 恢复;官方未被选择时不会自动安装或启用。官方 bundle 未被选择时,该行仍独立提供同一份 reviewer(自带注册 Auto preset),只是没有可接管的官方 owner。
8
+
9
+ 也可在 profile 的 `cordis.patch.yml` 中显式设置:
10
+
11
+ ```yaml
12
+ - id: multi-root-auto-review
13
+ disabled: false
14
+ ```
15
+
16
+ 卸载任何存活的 Auto owner 都保留官方语义:Auto Session 迁移为 Full access;新 owner 不会自动把它们切回 Auto。需要继续使用 Auto 时,在 Session 中重新选择。Multi-root 的写围栏继续执行。
17
+
18
+ 从旧 companion 迁移时,先停止目标 profile,移除其 bundle 选择和 `@dsh-electron/dsh-plugin-multi-root-auto-review` 依赖,再安装/更新主包并打开上述行。可使用现有 `dsh plugin --profile <name> remove @dsh-electron/dsh-plugin-multi-root-auto-review` 清理旧包;保留官方 bundle 的原有选择。旧版 configure 不再使用。残留旧 companion 与内置入口共存时会明确拒绝启动,不会自动重写用户 manifest。
19
+
20
+ 约束、预算、混合 native 帧与 freshness 语义沿用原 fork:当前拓扑和指令进入 reviewer 数据分区,项目文本仅为 constraint;预算、I/O、取消或快照变化使本次调用失败。bash/pwsh 只收集已知目录链,不能推断任意脚本的全部目标;普通源码自动读取不在范围内。
21
+
22
+ Fork 基线、允许差异与同步规则见 [FORK.md](./FORK.md)。
@@ -1,6 +1,6 @@
1
1
  import { realpathSync } from "node:fs";
2
- import { basename, dirname, join, resolve } from "node:path";
3
2
  import { createHash } from "node:crypto";
3
+ import { basename, dirname, join, resolve } from "node:path";
4
4
  //#region src/registry-lease-win32.ts
5
5
  /**
6
6
  * Windows named-kernel-semaphore adapter for the registry authority lease.