@dsh-electron/dsh-plugin-multi-root-workspace 0.1.8 → 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 (44) hide show
  1. package/CHANGELOG.en.md +9 -1
  2. package/CHANGELOG.md +9 -1
  3. package/README.en.md +21 -13
  4. package/README.md +29 -21
  5. package/cordis.patch.yml +6 -0
  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.js +1 -1
  11. package/lib/fork-CzbeWxHp.js +670 -0
  12. package/lib/fs.js +1 -1
  13. package/lib/index.js +7 -7
  14. package/lib/{instructions-D19jRxN0.js → instructions-CGNS3H0H.js} +211 -57
  15. package/lib/instructions.js +1 -1
  16. package/lib/lsp.js +1 -1
  17. package/lib/{registry-DCxC5Lay.js → registry-BClm6wfh.js} +6 -6
  18. package/lib/registry.js +1 -1
  19. package/lib/review-context-D-ohSVmA.js +98 -0
  20. package/lib/review-context.js +2 -0
  21. package/lib/{roots-B-0l8mNG.js → roots-Ca_W1S9n.js} +1 -1
  22. package/lib/{sandbox-CVAcT_gy.js → sandbox-CXk5h-ct.js} +3 -3
  23. package/lib/sandbox.js +1 -1
  24. package/lib/scope.js +14 -5
  25. package/lib/types/auto-review/entry.d.ts +5 -0
  26. package/lib/types/compat/auto-review-contract.d.ts +3 -0
  27. package/lib/types/compat/auto-review-loader.d.ts +33 -0
  28. package/lib/types/compat/auto-review-packages.d.ts +1 -0
  29. package/lib/types/compat/instruction-activity.d.ts +17 -0
  30. package/lib/types/compat/review-session.d.ts +2 -0
  31. package/lib/types/instructions.d.ts +18 -1
  32. package/lib/types/review-context.d.ts +49 -0
  33. package/lib/types/scope.d.ts +5 -0
  34. package/lib/windows-runner.js +2 -2
  35. package/lib/workspace-files.js +2 -2
  36. package/package.json +47 -7
  37. package/src/auto-review/FORK.md +26 -0
  38. package/src/auto-review/LICENSE +21 -0
  39. package/src/auto-review/README.en.md +22 -0
  40. package/src/auto-review/README.md +22 -0
  41. package/lib/{compat-DR2LvmYZ.js → compat-CagUNzRB.js} +1 -1
  42. package/lib/{fs-Nlp2AiRX.js → fs-BTXySwSG.js} +1 -1
  43. package/lib/{registry-lease-win32-DTO6QpT9.js → registry-lease-win32-DVTq9d4D.js} +1 -1
  44. package/lib/{windows-runner-contract-CEfmZzu0.js → windows-runner-contract-B5R2K3mM.js} +1 -1
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;
@@ -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;
@@ -0,0 +1,2 @@
1
+ import type { Session } from '@deepseek-ai/dsh-session';
2
+ export declare function nativeInstructionFingerprint(session: Session): string;
@@ -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,9 +1,9 @@
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 { createHash } from "node:crypto";
4
5
  import { basename, dirname, isAbsolute, join, win32 } from "node:path";
5
6
  import { pathToFileURL } from "node:url";
6
- import { createHash } from "node:crypto";
7
7
  import { createConnection } from "node:net";
8
8
  //#region src/compat/windows-native.ts
9
9
  /** Public Win32 process primitives, resolved from the upstream ACL installation.
@@ -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.8",
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,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
- import { Service } from "@deepseek-ai/cordis";
3
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
3
  import { dirname, join, sep } from "node:path";
4
+ import { Service } from "@deepseek-ai/cordis";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region src/compat/dsh-version.ts
7
7
  /**
@@ -1,9 +1,9 @@
1
1
  import { brandMultiRootProvider } from "./providers.js";
2
2
  import { dirname, sep } from "node:path";
3
3
  import { writableRoots } from "@deepseek-ai/dsh-sandbox";
4
+ import { stat } from "node:fs/promises";
4
5
  import { FsError } from "@deepseek-ai/dsh-fs";
5
6
  import { LocalFileSystem } from "@deepseek-ai/dsh-fs-local";
6
- import { stat } from "node:fs/promises";
7
7
  //#region src/containment.ts
8
8
  const MISSING_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]);
9
9
  function isMissing(error) {
@@ -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.
@@ -1,6 +1,6 @@
1
1
  import { existsSync, realpathSync, statSync } from "node:fs";
2
- import { isAbsolute, win32 } from "node:path";
3
2
  import { createHash } from "node:crypto";
3
+ import { isAbsolute, win32 } from "node:path";
4
4
  function assertWindowsDenyCapacity(count) {
5
5
  if (!Number.isInteger(count) || count < 1 || count > 256) throw new DialectUnrecognizedError(`Windows ambient restriction requires 1–256 deny roots including the protected DSH home; got ${count}. Reduce the registered restrictions before launching; no deny roots were dropped`);
6
6
  }