dsh-git-worktree 0.9.3 → 0.11.0

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 (65) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/README.en.md +7 -4
  3. package/README.md +7 -4
  4. package/lib/adapters/project-skill-provider.js +14 -4
  5. package/lib/adapters/project-skill-provider.js.map +1 -1
  6. package/lib/adapters/registry.js +4 -32
  7. package/lib/adapters/registry.js.map +1 -1
  8. package/lib/client/actions.d.ts +3 -3
  9. package/lib/client/actions.js.map +1 -1
  10. package/lib/client/console-remote/adapter.js +1 -1
  11. package/lib/client/console-remote/adapter.js.map +1 -1
  12. package/lib/client/console-remote/index.d.ts +10 -3
  13. package/lib/client/console-remote/index.js +20 -5
  14. package/lib/client/console-remote/index.js.map +1 -1
  15. package/lib/client/pre-session/controller.js +5 -0
  16. package/lib/client/pre-session/controller.js.map +1 -1
  17. package/lib/client/review-console/PreflightStatus.js +5 -2
  18. package/lib/client/review-console/PreflightStatus.js.map +1 -1
  19. package/lib/client/review-console/ReviewActions.js +47 -46
  20. package/lib/client/review-console/ReviewActions.js.map +1 -1
  21. package/lib/client/review-console/ReviewDetailsModal.js +13 -3
  22. package/lib/client/review-console/ReviewDetailsModal.js.map +1 -1
  23. package/lib/client/review-console/review-console.styles.js +22 -11
  24. package/lib/client/review-console/review-console.styles.js.map +1 -1
  25. package/lib/client/target-console/WorktreeReviewStatus.js +7 -7
  26. package/lib/client/target-console/WorktreeReviewStatus.js.map +1 -1
  27. package/lib/client/workspace-sidebar/index.js +46 -5
  28. package/lib/client/workspace-sidebar/index.js.map +1 -1
  29. package/lib/client.js +5200 -2513
  30. package/lib/commit-message.d.ts +2 -0
  31. package/lib/commit-message.js +5 -0
  32. package/lib/commit-message.js.map +1 -0
  33. package/lib/console-contract.d.ts +1 -1
  34. package/lib/console-host/control-plane.js +6 -5
  35. package/lib/console-host/control-plane.js.map +1 -1
  36. package/lib/console-remote/descriptors.js +5 -3
  37. package/lib/console-remote/descriptors.js.map +1 -1
  38. package/lib/console-remote/schemas.d.ts +1 -1
  39. package/lib/console-remote/schemas.js +3 -2
  40. package/lib/console-remote/schemas.js.map +1 -1
  41. package/lib/host-compat.d.ts +1 -1
  42. package/lib/host-compat.js +3 -0
  43. package/lib/host-compat.js.map +1 -1
  44. package/lib/i18n/client-messages.d.ts +8 -4
  45. package/lib/i18n/client-messages.js +2 -4
  46. package/lib/i18n/client-messages.js.map +1 -1
  47. package/lib/i18n/host-messages.d.ts +3 -7
  48. package/lib/i18n/host-messages.js +3 -7
  49. package/lib/i18n/host-messages.js.map +1 -1
  50. package/lib/index.d.ts +13 -10
  51. package/lib/index.js +9 -2
  52. package/lib/index.js.map +1 -1
  53. package/lib/ports.d.ts +1 -1
  54. package/lib/session-checkout-apply.js +6 -5
  55. package/lib/session-checkout-apply.js.map +1 -1
  56. package/lib/session-checkout-module.js +10 -7
  57. package/lib/session-checkout-module.js.map +1 -1
  58. package/lib/workspace-provider-lifecycle.d.ts +15 -1
  59. package/lib/workspace-provider-lifecycle.js +94 -10
  60. package/lib/workspace-provider-lifecycle.js.map +1 -1
  61. package/package.json +45 -41
  62. package/scripts/check-publish.mjs +4 -1
  63. package/scripts/workspace-sidebar-upstream-alpha.mjs +16 -14
  64. package/scripts/workspace-sidebar-upstream-next.mjs +12 -16
  65. package/scripts/workspace-sidebar-upstream.mjs +64 -30
@@ -6,11 +6,25 @@ declare module '@deepseek-ai/cordis' {
6
6
  worktreeWorkspaceProvider: boolean;
7
7
  }
8
8
  }
9
+ /** Tuning seams for {@link mountWorkspaceProviderLifecycle} (tests). */
10
+ export interface WorkspaceProviderLifecycleOptions {
11
+ /** Ceiling for a single Loader disable/restore operation in milliseconds. */
12
+ operationTimeoutMs?: number;
13
+ }
9
14
  /**
10
15
  * Reconcile the conditional patch with the public Loader lifecycle. A disabled
11
16
  * expression is evaluated dynamically, but the Web module registry caches rows
12
17
  * by plugin name; a change to the replacement alone does not re-elect Workspace.
13
18
  * Restarting the official entry through Loader operations publishes real module
14
19
  * events without saving any disabled flag or changing the user's profile.
20
+ *
21
+ * Election never blocks (or fails) plugin activation: Host boots start entries
22
+ * concurrently, so the official entry's disable may race a fiber that is still
23
+ * starting, and Loader versions differ in how such a dispose settles. Each
24
+ * operation therefore races a ceiling; a wedged one is reported once and the
25
+ * entry stays guarded until the real operation settles, while the next Loader
26
+ * event retries the election. The disabled expression itself already keeps any
27
+ * not-yet-started official entry out of the Web module graph, so the Web side
28
+ * never observes two `uiWorkspace` providers from a slow reconciliation.
15
29
  */
16
- export declare function mountWorkspaceProviderLifecycle(ctx: Context, flavor?: WorkspaceClientFlavor): Promise<void>;
30
+ export declare function mountWorkspaceProviderLifecycle(ctx: Context, flavor?: WorkspaceClientFlavor, options?: WorkspaceProviderLifecycleOptions): void;
@@ -3,18 +3,33 @@ export const WORKSPACE_PROVIDER_CONDITION = "!!get('worktreeWorkspaceProvider')
3
3
  const OFFICIAL_WORKSPACE = '@deepseek-ai/dsh-client-ui-workspace';
4
4
  // Cordis exposes FiberState as a declaration-only const enum, not a JS export.
5
5
  const UNLOADING = 5;
6
+ // One Loader election operation that has not settled by this ceiling stops
7
+ // blocking the chain: plugin activation must never depend on the Host's
8
+ // concurrent entry startup unwinding first (a wedged official-fiber dispose
9
+ // would otherwise starve every Remote, tool, and command mount).
10
+ const DEFAULT_OPERATION_TIMEOUT_MS = 10_000;
6
11
  /**
7
12
  * Reconcile the conditional patch with the public Loader lifecycle. A disabled
8
13
  * expression is evaluated dynamically, but the Web module registry caches rows
9
14
  * by plugin name; a change to the replacement alone does not re-elect Workspace.
10
15
  * Restarting the official entry through Loader operations publishes real module
11
16
  * events without saving any disabled flag or changing the user's profile.
17
+ *
18
+ * Election never blocks (or fails) plugin activation: Host boots start entries
19
+ * concurrently, so the official entry's disable may race a fiber that is still
20
+ * starting, and Loader versions differ in how such a dispose settles. Each
21
+ * operation therefore races a ceiling; a wedged one is reported once and the
22
+ * entry stays guarded until the real operation settles, while the next Loader
23
+ * event retries the election. The disabled expression itself already keeps any
24
+ * not-yet-started official entry out of the Web module graph, so the Web side
25
+ * never observes two `uiWorkspace` providers from a slow reconciliation.
12
26
  */
13
- export async function mountWorkspaceProviderLifecycle(ctx, flavor = hostWorkspaceClientFlavor()) {
27
+ export function mountWorkspaceProviderLifecycle(ctx, flavor = hostWorkspaceClientFlavor(), options = {}) {
14
28
  if (flavor === 'unsupported') {
15
29
  ctx.logger.warn('No pinned Workspace Browser for this Host generation; leaving the official Workspace provider active.');
16
30
  return;
17
31
  }
32
+ const operationTimeoutMs = options.operationTimeoutMs ?? DEFAULT_OPERATION_TIMEOUT_MS;
18
33
  const loader = ctx.loader;
19
34
  const owned = () => [...loader.entries()].filter(entry => {
20
35
  const disabled = entry.options.disabled;
@@ -24,36 +39,103 @@ export async function mountWorkspaceProviderLifecycle(ctx, flavor = hostWorkspac
24
39
  });
25
40
  let released = false;
26
41
  let pending = Promise.resolve();
42
+ // Entries whose real Loader operation is still in flight (possibly past the
43
+ // ceiling). Later reconciles skip them until the operation itself settles,
44
+ // which keeps at most one Loader mutation per entry alive at any time.
45
+ const inFlight = new Set();
46
+ const operate = (entry, kind) => new Promise(resolve => {
47
+ const key = entry.id;
48
+ const label = kind === 'disable' ? 'official Workspace disable' : 'official Workspace restore';
49
+ let operation;
50
+ try {
51
+ const fiber = entry.fiber;
52
+ operation = kind === 'disable'
53
+ ? entry.update({}, false, true).then(() => fiber?.await())
54
+ // Loader 1.0.6 retains disposed fibers; refresh() treats any reference
55
+ // as running, whereas init() replaces the dead generation.
56
+ : fiber?.uid === null ? entry.init() : entry.refresh();
57
+ }
58
+ catch (error) {
59
+ ctx.logger.warn(`dsh-git-worktree: ${label} threw during Loader reconciliation`, error);
60
+ resolve();
61
+ return;
62
+ }
63
+ const settle = () => { inFlight.delete(key); };
64
+ inFlight.add(key);
65
+ void operation.then(settle, settle);
66
+ const timer = setTimeout(() => {
67
+ ctx.logger.warn(`dsh-git-worktree: ${label} did not settle within ${String(operationTimeoutMs)}ms; `
68
+ + 'plugin activation continues and election retries on the next Loader event.');
69
+ resolve();
70
+ }, operationTimeoutMs);
71
+ timer.unref?.();
72
+ void operation.then(() => { clearTimeout(timer); settle(); resolve(); }, error => {
73
+ clearTimeout(timer);
74
+ settle();
75
+ ctx.logger.warn(`dsh-git-worktree: ${label} failed during Loader reconciliation`, error);
76
+ resolve();
77
+ });
78
+ });
27
79
  const reconcile = () => {
28
80
  pending = pending.then(async () => {
29
81
  if (released)
30
82
  return;
31
83
  for (const entry of owned()) {
32
- if (entry.disabled) {
84
+ if (inFlight.has(entry.id))
85
+ continue;
86
+ let disabled;
87
+ try {
88
+ disabled = entry.disabled;
89
+ }
90
+ catch (error) {
91
+ ctx.logger.warn('dsh-git-worktree: could not evaluate the official Workspace disabled expression', error);
92
+ continue;
93
+ }
94
+ if (disabled) {
33
95
  if (!released)
34
- await entry.update({}, false, true);
96
+ await operate(entry, 'disable');
35
97
  }
36
98
  else {
37
- await entry.refresh();
99
+ await operate(entry, 'restore');
38
100
  }
39
101
  }
40
102
  });
41
103
  return pending;
42
104
  };
105
+ const releaseMarker = ctx.provide('worktreeWorkspaceProvider', true);
43
106
  ctx.effect(() => async () => {
44
107
  released = true;
108
+ // Cordis 4.0.5 unloads effects concurrently, not in LIFO order. Explicitly
109
+ // withdraw the marker before evaluating the official disabled expression.
110
+ await releaseMarker();
111
+ // Loader retains failed/disposed fibers and the Web registry only checks
112
+ // the entry reference, not fiber state. Withdraw this generation alone and
113
+ // publish the same owning-fiber event the registry consumes on disposal.
114
+ // A later activation must never be cleared by this generation's cleanup.
115
+ const withdraw = () => {
116
+ const replacement = ctx.fiber.entry;
117
+ if (replacement?.fiber !== ctx.fiber)
118
+ return;
119
+ replacement.fiber = undefined;
120
+ ctx.emit('internal/plugin', ctx.fiber);
121
+ };
122
+ if (ctx.fiber.uid === null)
123
+ withdraw();
124
+ // A restart also unloads effects, but reuses its live fiber. Only withdraw
125
+ // that reference if activation actually failed, after unload settles.
126
+ // Do not await our own cleanup from inside this disposer.
127
+ else
128
+ void ctx.fiber.await().catch(withdraw);
45
129
  // Root/Include teardown owns these entries; do not resurrect that tree.
46
130
  if (ctx.root.fiber.uid === null || ctx.root.fiber.state === UNLOADING)
47
131
  return;
48
132
  await pending.catch(() => { });
49
133
  for (const entry of owned()) {
50
- if (entry.parent.ctx.fiber.uid !== null && entry.parent.ctx.fiber.state !== UNLOADING && !entry.disabled)
51
- await entry.refresh();
134
+ if (entry.parent.ctx.fiber.uid !== null && entry.parent.ctx.fiber.state !== UNLOADING && !entry.disabled
135
+ && !inFlight.has(entry.id))
136
+ await operate(entry, 'restore');
52
137
  }
53
138
  });
54
- // Registered after the fallback so LIFO teardown releases the selection
55
- // before restoring Workspace, including when the replacement apply fails.
56
- ctx.provide('worktreeWorkspaceProvider', true);
57
139
  // Includes may add the official row after the replacement has activated.
58
140
  ctx.on('internal/status', fiber => {
59
141
  if (fiber === ctx.fiber && !released) {
@@ -65,6 +147,8 @@ export async function mountWorkspaceProviderLifecycle(ctx, flavor = hostWorkspac
65
147
  void reconcile().catch(error => ctx.logger.warn(error));
66
148
  }
67
149
  });
68
- await reconcile();
150
+ // Deliberately fire-and-forget: this pass only stops an official fiber that
151
+ // raced ahead during concurrent boot; activation itself must not wait on it.
152
+ void reconcile().catch(error => ctx.logger.warn(error));
69
153
  }
70
154
  //# sourceMappingURL=workspace-provider-lifecycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-provider-lifecycle.js","sourceRoot":"","sources":["../src/workspace-provider-lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace-provider-lifecycle.js","sourceRoot":"","sources":["../src/workspace-provider-lifecycle.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-git-worktree",
3
- "version": "0.9.3",
3
+ "version": "0.11.0",
4
4
  "description": "Experimental Git worktree Session Targets for DeepSeek Harness with isolated sessions, review checkpoints, human-confirmed delivery, and safe recovery.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -50,7 +50,8 @@
50
50
  "@deepseek-ai/dsh-client-locale",
51
51
  "@deepseek-ai/dsh-client-ui-conversation",
52
52
  "@deepseek-ai/dsh-client-ui-tool",
53
- "@deepseek-ai/dsh-api-gateway"
53
+ "@deepseek-ai/dsh-api-gateway",
54
+ "@deepseek-ai/dsh-api-remote-access"
54
55
  ],
55
56
  "platform": "web"
56
57
  }
@@ -81,63 +82,66 @@
81
82
  "prepublishOnly": "pnpm run check:sidebar-version && pnpm run build && pnpm run check:publish:release && pnpm run test"
82
83
  },
83
84
  "dependencies": {
84
- "@deepseek-ai/schemastery": "3.18.2",
85
+ "@deepseek-ai/schemastery": "3.18.5",
85
86
  "lucide-react": "1.43.0",
86
87
  "zod": "4.4.3"
87
88
  },
88
89
  "peerDependencies": {
89
- "@deepseek-ai/cordis": "^4.0.2",
90
- "@deepseek-ai/cordis-plugin-loader": "^1.0.3",
91
- "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
92
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.7-rc.2",
93
- "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
94
- "@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
95
- "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
96
- "@deepseek-ai/dsh-skill": "^0.1.2-rc.1",
97
- "@deepseek-ai/dsh-skill-filesystem": "^0.1.2-rc.1",
98
- "@deepseek-ai/dsh-subprocess": "^0.1.2-rc.1",
99
- "@deepseek-ai/dsh-system-prompt": "^0.1.2-rc.1",
100
- "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
101
- "@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1",
102
- "@deepseek-ai/dsh-typert-registry": "^0.1.2-rc.1",
90
+ "@deepseek-ai/cordis": "~4.0.5",
91
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6",
92
+ "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
93
+ "@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
94
+ "@deepseek-ai/dsh-commands": "0.2.1-rc.2",
95
+ "@deepseek-ai/dsh-fs": "0.2.1-rc.2",
96
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
97
+ "@deepseek-ai/dsh-skill": "0.2.1-rc.2",
98
+ "@deepseek-ai/dsh-skill-filesystem": "0.2.1-rc.2",
99
+ "@deepseek-ai/dsh-subprocess": "0.2.1-rc.2",
100
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
101
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
102
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
103
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-rc.2",
103
104
  "react": "^18.2.0"
104
105
  },
105
106
  "devDependencies": {
106
- "@deepseek-ai/cordis": "4.0.2",
107
- "@deepseek-ai/cordis-plugin-include": "1.0.7",
108
- "@deepseek-ai/cordis-plugin-loader": "1.0.3",
109
- "@deepseek-ai/dsh-agent": "0.1.2-rc.1",
110
- "@deepseek-ai/dsh-api-gateway": "0.1.2-rc.1",
111
- "@deepseek-ai/dsh-api-session-controller": "0.1.2-rc.1",
112
- "@deepseek-ai/dsh-api-workspace-controller": "0.1.2-rc.1",
113
- "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1",
114
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
115
- "@deepseek-ai/dsh-client-modules": "0.1.2-rc.1",
116
- "@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
117
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
118
- "@deepseek-ai/dsh-client-ui-workspace": "0.1.2-rc.1",
107
+ "@deepseek-ai/cordis": "4.0.5",
108
+ "@deepseek-ai/cordis-plugin-include": "1.0.10",
109
+ "@deepseek-ai/cordis-plugin-loader": "1.0.6",
110
+ "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
111
+ "@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
112
+ "@deepseek-ai/dsh-api-remote-access": "0.2.1-rc.2",
113
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
114
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-rc.2",
115
+ "@deepseek-ai/dsh-client-connection": "0.2.1-rc.2",
116
+ "@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
117
+ "@deepseek-ai/dsh-client-modules": "0.2.1-rc.2",
118
+ "@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
119
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
120
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-rc.2",
119
121
  "@deepseek-ai/dsh-client-ui-workspace-alpha": "npm:@deepseek-ai/dsh-client-ui-workspace@0.1.6-alpha.2",
120
122
  "@deepseek-ai/dsh-client-ui-workspace-next": "npm:@deepseek-ai/dsh-client-ui-workspace@0.1.7-rc.2",
121
- "@deepseek-ai/dsh-commands": "0.1.2-rc.1",
122
- "@deepseek-ai/dsh-fs": "0.1.2-rc.1",
123
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
124
- "@deepseek-ai/dsh-skill": "0.1.2-rc.1",
125
- "@deepseek-ai/dsh-skill-filesystem": "0.1.2-rc.1",
126
- "@deepseek-ai/dsh-subprocess": "0.1.2-rc.1",
127
- "@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
128
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
129
- "@deepseek-ai/dsh-typert-loader": "0.1.2-rc.1",
130
- "@deepseek-ai/dsh-typert-protocol": "0.1.2-rc.1",
131
- "@deepseek-ai/dsh-typert-registry": "0.1.2-rc.1",
123
+ "@deepseek-ai/dsh-commands": "0.2.1-rc.2",
124
+ "@deepseek-ai/dsh-fs": "0.2.1-rc.2",
125
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
126
+ "@deepseek-ai/dsh-skill": "0.2.1-rc.2",
127
+ "@deepseek-ai/dsh-skill-filesystem": "0.2.1-rc.2",
128
+ "@deepseek-ai/dsh-subprocess": "0.2.1-rc.2",
129
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
130
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
131
+ "@deepseek-ai/dsh-typert-loader": "0.2.1-rc.2",
132
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
133
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-rc.2",
132
134
  "@testing-library/react": "^16.3.2",
133
135
  "@types/node": "^22.0.0",
134
136
  "@types/react": "~18.3.31",
135
137
  "@types/react-dom": "~18.3.7",
138
+ "immer": "^10.1.1",
136
139
  "jsdom": "^24.1.3",
137
140
  "react": "^18.3.1",
138
141
  "react-dom": "^18.3.1",
139
142
  "tsdown": "^0.17.2",
140
143
  "typescript": "^5.6.0",
144
+ "zustand": "~4.4.7",
141
145
  "vitest": "^2.1.0"
142
146
  },
143
147
  "keywords": [
@@ -161,6 +161,7 @@ if (!client || client.platform !== 'web' || !Array.isArray(client.inject) || cli
161
161
  fail('package.json must declare dsh.client { platform: "web", inject: [...] }')
162
162
  }
163
163
  const requiredClientPackages = [
164
+ '@deepseek-ai/dsh-api-remote-access',
164
165
  '@deepseek-ai/dsh-api-session-controller',
165
166
  '@deepseek-ai/dsh-api-workspace-controller',
166
167
  '@deepseek-ai/dsh-client-ui-conversation',
@@ -216,8 +217,10 @@ try {
216
217
  if (!clientExports || typeof clientExports.apply !== 'function' || !Array.isArray(clientExports.inject)) {
217
218
  fail('client bundle factory did not return apply + inject')
218
219
  }
220
+ if (!clientExports.inject.includes('remoteAccess')) fail('client bundle must inject the official remoteAccess service')
219
221
  if (!clientExports.inject.includes('remote')) fail('client bundle must inject the official Remote service before $mount')
220
- if (!clientExports.inject.includes('remote.directoryPicker')) fail('client bundle must wait for the official directory-picker Remote before restoring uiWorkspace')
222
+ if (clientExports.inject.includes('remote.directoryPicker')) fail('client bundle entry must not wait for the directory-picker Remote: its provider entry waits for uiWorkspace, so requiring it here deadlocks the 0.2.x web boot')
223
+ if (!clientSource.includes("'remote.directoryPicker'") && !clientSource.includes('"remote.directoryPicker"')) fail('client bundle must resolve the directory-picker lazily at call time through the managed context (deferred facade)')
221
224
  if (clientExports.inject.includes('conversation')) fail('client bundle root must not wait for conversation: uiConversation depends on the uiWorkspace restored by this plugin')
222
225
  if (clientExports.inject.includes('connection')) fail('client bundle root must keep connection-dependent Worktree views in the deferred child fiber')
223
226
  ok(`${clientRel} registers ${manifest.name} through the browser ModuleLoader contract without a uiWorkspace/uiConversation boot cycle`)
@@ -43,26 +43,23 @@ export function decorateAlphaWorkspaceClient(source) {
43
43
  '\t\t\t\t\tlabel: g.label,\n\t\t\t\t\t...g.__dshGitWorktreeProtected === true ? { __dshGitWorktreeProtected: true } : {},\n\t\t\t\t\tsessionCount: g.sessions.length,',
44
44
  'protected workspace row',
45
45
  )
46
+ // Cordis Service derives its own Context; capture the instance-local guard
47
+ // from the constructor argument rather than looking it up on this.ctx later.
46
48
  replace(
47
- '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tconst navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);',
48
- '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tif (this.ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tconst navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);',
49
- 'managed Session fork',
49
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
50
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.managedWorktreeGuard = ctx.get("__dshGitWorktreeManagedGuard");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
51
+ 'instance-local managed guard',
50
52
  )
51
53
  replace(
52
- '\t\t\tasync archiveSession(sessionId) {\n\t\t\t\tawait this.workspaces.archiveSession(sessionId);',
53
- '\t\t\tasync archiveSession(sessionId) {\n\t\t\t\tif (this.ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tawait this.workspaces.archiveSession(sessionId);',
54
- 'managed Session archive',
54
+ '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tconst navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);',
55
+ '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tif (this.managedWorktreeGuard.blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tconst navigation = AbortSignal.any([this.ctx.layout.beginNavigation(), this.lifetime.signal]);',
56
+ 'managed Session fork',
55
57
  )
56
58
  replace(
57
59
  '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target === void 0) {',
58
- '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target !== void 0 && this.ctx.get("__dshGitWorktreeManagedGuard").blockWorkspace(target)) return;\n\t\t\t\tif (target === void 0) {',
60
+ '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target !== void 0 && this.managedWorktreeGuard.blockWorkspace(target)) return;\n\t\t\t\tif (target === void 0) {',
59
61
  'managed Workspace new Session shortcut',
60
62
  )
61
- replace(
62
- '\t\t\t\trenameSession: async (sessionId, title) => {\n\t\t\t\t\tconst result = await sessions.using(',
63
- '\t\t\t\trenameSession: async (sessionId, title) => {\n\t\t\t\t\tif (ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\t\tconst result = await sessions.using(',
64
- 'managed Session rename',
65
- )
66
63
  replace(
67
64
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
68
65
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t__dshGitWorktree: s.__dshGitWorktree,\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
@@ -83,7 +80,12 @@ export function decorateAlphaWorkspaceClient(source) {
83
80
  'managed Session row guard',
84
81
  )
85
82
  replace('\t\t\tconst draggable = drag !== void 0 && !row.blank;', '\t\t\tconst draggable = drag !== void 0 && !row.blank && !protectedManagedSession;', 'managed Session drag')
86
- replace('\t\t\t\t\t\t!row.blank && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.rowActions,', '\t\t\t\t\t\t!row.blank && !protectedManagedSession && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.rowActions,', 'managed Session actions')
83
+ replace(
84
+ '\t\t\t];\n\t\t\treturn (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {',
85
+ '\t\t\t];\n\t\t\tconst visibleSessionMenuItems = protectedManagedSession ? sessionMenuItems.filter((item) => item.id !== "fork") : sessionMenuItems;\n\t\t\treturn (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {',
86
+ 'managed Session safe menu items',
87
+ )
88
+ replace('\t\t\t\t\t\t\t\titems: sessionMenuItems,', '\t\t\t\t\t\t\t\titems: visibleSessionMenuItems,', 'managed Session menu')
87
89
  replace(
88
90
  '\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tref: titleRef,\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.title,',
89
91
  '\t\t\t\t\t\tprotectedManagedSession && (0, react_jsx_runtime.jsx)("span", { title: node.__dshGitWorktree.label, "aria-label": node.__dshGitWorktree.label, style: { flexShrink: 0, display: "inline-flex" }, children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, {}) }),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tref: titleRef,\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.title,',
@@ -91,7 +93,7 @@ export function decorateAlphaWorkspaceClient(source) {
91
93
  )
92
94
  replace(
93
95
  '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\trow.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, { t }),',
94
- '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tprotectedManagedSession && (0, react_jsx_runtime.jsx)("span", { className: "dsh-git-worktree-sidebar-badge", "data-worktree-state": node.__dshGitWorktree.state, children: node.__dshGitWorktree.label }),\n\t\t\t\t\t\trow.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, { t }),',
96
+ '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tprotectedManagedSession && node.__dshGitWorktree.state !== "working" && (0, react_jsx_runtime.jsx)("span", { className: "dsh-git-worktree-sidebar-badge", "data-worktree-state": node.__dshGitWorktree.state, children: node.__dshGitWorktree.label }),\n\t\t\t\t\t\trow.hasActiveSchedule && (0, react_jsx_runtime.jsx)(ActiveScheduleIndicator, { t }),',
95
97
  'managed Session status badge',
96
98
  )
97
99
  return derived
@@ -42,26 +42,23 @@ export function decorateNextWorkspaceClient(source) {
42
42
  '\t\t\t\t\tlabel: g.label,\n\t\t\t\t\t...g.__dshGitWorktreeProtected === true ? { __dshGitWorktreeProtected: true } : {},\n\t\t\t\t\tsessionCount: g.sessions.length,',
43
43
  'protected workspace row',
44
44
  )
45
+ // Cordis Service derives its own Context; capture the instance-local guard
46
+ // from the constructor argument rather than looking it up on this.ctx later.
45
47
  replace(
46
- '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tawait this.sessions.fork({',
47
- '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tif (this.ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tawait this.sessions.fork({',
48
- 'managed Session fork from official menu and shortcuts',
48
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
49
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.managedWorktreeGuard = ctx.get("__dshGitWorktreeManagedGuard");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
50
+ 'instance-local managed guard',
49
51
  )
50
52
  replace(
51
- '\t\t\tasync archiveSession(sessionId, options = {}) {\n\t\t\t\tawait this.workspaces.archiveSession(sessionId, options);',
52
- '\t\t\tasync archiveSession(sessionId, options = {}) {\n\t\t\t\tif (this.ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tawait this.workspaces.archiveSession(sessionId, options);',
53
- 'managed Session archive from official menu and shortcuts',
53
+ '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tawait this.sessions.fork({',
54
+ '\t\t\tasync forkSession(sessionId) {\n\t\t\t\tif (this.managedWorktreeGuard.blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tawait this.sessions.fork({',
55
+ 'managed Session fork from official menu and shortcuts',
54
56
  )
55
57
  replace(
56
58
  '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target === void 0) {',
57
- '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target !== void 0 && this.ctx.get("__dshGitWorktreeManagedGuard").blockWorkspace(target)) return;\n\t\t\t\tif (target === void 0) {',
59
+ '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target !== void 0 && this.managedWorktreeGuard.blockWorkspace(target)) return;\n\t\t\t\tif (target === void 0) {',
58
60
  'managed Workspace new Session shortcut',
59
61
  )
60
- replace(
61
- '\t\t\tconst renameSession = async (sessionId, title) => {\n\t\t\t\tconst result = await sessions.using(',
62
- '\t\t\tconst renameSession = async (sessionId, title) => {\n\t\t\t\tif (ctx.get("__dshGitWorktreeManagedGuard").blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\tconst result = await sessions.using(',
63
- 'managed Session rename dialog',
64
- )
65
62
  replace(
66
63
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
67
64
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t__dshGitWorktree: s.__dshGitWorktree,\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
@@ -82,9 +79,8 @@ export function decorateNextWorkspaceClient(source) {
82
79
  'managed Session row guard',
83
80
  )
84
81
  replace('\t\t\tconst draggable = drag !== void 0 && !row.blank && !row.archived;', '\t\t\tconst draggable = drag !== void 0 && !row.blank && !row.archived && !protectedManagedSession;', 'managed Session drag')
85
- replace('\t\t\t\t\t\t\tonDoubleClick: row.blank ? void 0 : (e) => {', '\t\t\t\t\t\t\tonDoubleClick: row.blank || protectedManagedSession ? void 0 : (e) => {', 'managed Session rename')
86
- // Keep the official hover container: the guarded Slot seats render only pin
87
- // for managed Sessions, while ordinary Sessions retain every official action.
82
+ // Keep the official hover container. The Slot proxy preserves pin, rename
83
+ // and archive on managed owners while filtering ownership-changing actions.
88
84
  replace(
89
85
  '\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tref: titleRef,\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.title,',
90
86
  '\t\t\t\t\t\tprotectedManagedSession && (0, react_jsx_runtime.jsx)("span", { title: node.__dshGitWorktree.label, "aria-label": node.__dshGitWorktree.label, style: { flexShrink: 0, display: "inline-flex" }, children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { size: 16 }) }),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tref: titleRef,\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.title,',
@@ -92,7 +88,7 @@ export function decorateNextWorkspaceClient(source) {
92
88
  )
93
89
  replace(
94
90
  '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t!row.blank && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.time,',
95
- '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tprotectedManagedSession && (0, react_jsx_runtime.jsx)("span", { className: "dsh-git-worktree-sidebar-badge", "data-worktree-state": node.__dshGitWorktree.state, children: node.__dshGitWorktree.label }),\n\t\t\t\t\t\t!row.blank && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.time,',
91
+ '\t\t\t\t\t\t\tchildren: title\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tprotectedManagedSession && node.__dshGitWorktree.state !== "working" && (0, react_jsx_runtime.jsx)("span", { className: "dsh-git-worktree-sidebar-badge", "data-worktree-state": node.__dshGitWorktree.state, children: node.__dshGitWorktree.label }),\n\t\t\t\t\t\t!row.blank && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.time,',
96
92
  'managed Session status badge',
97
93
  )
98
94
  return derived