@ricsam/r5d-worker 0.0.136 → 0.0.137

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.
@@ -0,0 +1,372 @@
1
+ import { z } from "zod";
2
+ export declare const EXECUTOR_CAPABILITY = "host-executor-v1";
3
+ export declare const MAX_FRAME_BYTES: number;
4
+ export declare const Lane: z.ZodEnum<{
5
+ control: "control";
6
+ general: "general";
7
+ utility: "utility";
8
+ }>;
9
+ export declare const ShellPayload: z.ZodObject<{
10
+ argv: z.ZodArray<z.ZodString>;
11
+ cwd: z.ZodString;
12
+ env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
13
+ lane: z.ZodDefault<z.ZodEnum<{
14
+ control: "control";
15
+ general: "general";
16
+ utility: "utility";
17
+ }>>;
18
+ interactive: z.ZodDefault<z.ZodBoolean>;
19
+ pty: z.ZodOptional<z.ZodObject<{
20
+ cols: z.ZodNumber;
21
+ rows: z.ZodNumber;
22
+ }, z.core.$strict>>;
23
+ credentials: z.ZodDefault<z.ZodArray<z.ZodObject<{
24
+ id: z.ZodString;
25
+ generation: z.ZodNumber;
26
+ }, z.core.$strict>>>;
27
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
28
+ }, z.core.$strict>;
29
+ export type ShellPayload = z.input<typeof ShellPayload>;
30
+ export declare const RunIdentity: z.ZodObject<{
31
+ operationId: z.ZodString;
32
+ userId: z.ZodString;
33
+ sessionId: z.ZodOptional<z.ZodString>;
34
+ fence: z.ZodObject<{
35
+ installationId: z.ZodString;
36
+ resourceType: z.ZodString;
37
+ resourceId: z.ZodString;
38
+ ownerId: z.ZodString;
39
+ epoch: z.ZodNumber;
40
+ }, z.core.$strict>;
41
+ }, z.core.$strict>;
42
+ export type RunIdentity = z.infer<typeof RunIdentity>;
43
+ export declare const ExecutorCommand: z.ZodDiscriminatedUnion<[z.ZodObject<{
44
+ method: z.ZodLiteral<"status">;
45
+ }, z.core.$strict>, z.ZodObject<{
46
+ method: z.ZodLiteral<"authority">;
47
+ fence: z.ZodObject<{
48
+ installationId: z.ZodString;
49
+ resourceType: z.ZodString;
50
+ resourceId: z.ZodString;
51
+ ownerId: z.ZodString;
52
+ epoch: z.ZodNumber;
53
+ }, z.core.$strict>;
54
+ validUntil: z.ZodNumber;
55
+ }, z.core.$strict>, z.ZodObject<{
56
+ method: z.ZodLiteral<"start">;
57
+ operation: z.ZodObject<{
58
+ protocol: z.ZodLiteral<1>;
59
+ installationId: z.ZodString;
60
+ operationId: z.ZodString;
61
+ userId: z.ZodString;
62
+ sessionId: z.ZodOptional<z.ZodString>;
63
+ kind: z.ZodString;
64
+ fence: z.ZodObject<{
65
+ installationId: z.ZodString;
66
+ resourceType: z.ZodString;
67
+ resourceId: z.ZodString;
68
+ ownerId: z.ZodString;
69
+ epoch: z.ZodNumber;
70
+ }, z.core.$strict>;
71
+ payload: z.ZodUnknown;
72
+ }, z.core.$strict>;
73
+ }, z.core.$strict>, z.ZodObject<{
74
+ method: z.ZodLiteral<"poll">;
75
+ run: z.ZodObject<{
76
+ operationId: z.ZodString;
77
+ userId: z.ZodString;
78
+ sessionId: z.ZodOptional<z.ZodString>;
79
+ fence: z.ZodObject<{
80
+ installationId: z.ZodString;
81
+ resourceType: z.ZodString;
82
+ resourceId: z.ZodString;
83
+ ownerId: z.ZodString;
84
+ epoch: z.ZodNumber;
85
+ }, z.core.$strict>;
86
+ }, z.core.$strict>;
87
+ stdoutOffset: z.ZodDefault<z.ZodNumber>;
88
+ stderrOffset: z.ZodDefault<z.ZodNumber>;
89
+ maxBytes: z.ZodDefault<z.ZodNumber>;
90
+ }, z.core.$strict>, z.ZodObject<{
91
+ method: z.ZodLiteral<"write">;
92
+ run: z.ZodObject<{
93
+ operationId: z.ZodString;
94
+ userId: z.ZodString;
95
+ sessionId: z.ZodOptional<z.ZodString>;
96
+ fence: z.ZodObject<{
97
+ installationId: z.ZodString;
98
+ resourceType: z.ZodString;
99
+ resourceId: z.ZodString;
100
+ ownerId: z.ZodString;
101
+ epoch: z.ZodNumber;
102
+ }, z.core.$strict>;
103
+ }, z.core.$strict>;
104
+ actionId: z.ZodString;
105
+ data: z.ZodString;
106
+ eof: z.ZodDefault<z.ZodBoolean>;
107
+ }, z.core.$strict>, z.ZodObject<{
108
+ method: z.ZodLiteral<"resize">;
109
+ run: z.ZodObject<{
110
+ operationId: z.ZodString;
111
+ userId: z.ZodString;
112
+ sessionId: z.ZodOptional<z.ZodString>;
113
+ fence: z.ZodObject<{
114
+ installationId: z.ZodString;
115
+ resourceType: z.ZodString;
116
+ resourceId: z.ZodString;
117
+ ownerId: z.ZodString;
118
+ epoch: z.ZodNumber;
119
+ }, z.core.$strict>;
120
+ }, z.core.$strict>;
121
+ actionId: z.ZodString;
122
+ cols: z.ZodNumber;
123
+ rows: z.ZodNumber;
124
+ }, z.core.$strict>, z.ZodObject<{
125
+ method: z.ZodLiteral<"cancel">;
126
+ run: z.ZodObject<{
127
+ operationId: z.ZodString;
128
+ userId: z.ZodString;
129
+ sessionId: z.ZodOptional<z.ZodString>;
130
+ fence: z.ZodObject<{
131
+ installationId: z.ZodString;
132
+ resourceType: z.ZodString;
133
+ resourceId: z.ZodString;
134
+ ownerId: z.ZodString;
135
+ epoch: z.ZodNumber;
136
+ }, z.core.$strict>;
137
+ }, z.core.$strict>;
138
+ actionId: z.ZodString;
139
+ }, z.core.$strict>], "method">;
140
+ export type ExecutorCommand = z.input<typeof ExecutorCommand>;
141
+ export declare const ExecutorRequest: z.ZodObject<{
142
+ protocol: z.ZodLiteral<1>;
143
+ requestId: z.ZodString;
144
+ auth: z.ZodObject<{
145
+ principalId: z.ZodString;
146
+ token: z.ZodString;
147
+ }, z.core.$strict>;
148
+ hello: z.ZodObject<{
149
+ installationId: z.ZodString;
150
+ instanceId: z.ZodString;
151
+ releaseId: z.ZodString;
152
+ role: z.ZodEnum<{
153
+ web: "web";
154
+ scheduler: "scheduler";
155
+ runner: "runner";
156
+ gateway: "gateway";
157
+ "worker-adapter": "worker-adapter";
158
+ "browser-adapter": "browser-adapter";
159
+ executor: "executor";
160
+ keeper: "keeper";
161
+ storage: "storage";
162
+ }>;
163
+ protocol: z.ZodObject<{
164
+ min: z.ZodNumber;
165
+ max: z.ZodNumber;
166
+ }, z.core.$strict>;
167
+ capabilities: z.ZodArray<z.ZodString>;
168
+ }, z.core.$strict>;
169
+ command: z.ZodDiscriminatedUnion<[z.ZodObject<{
170
+ method: z.ZodLiteral<"status">;
171
+ }, z.core.$strict>, z.ZodObject<{
172
+ method: z.ZodLiteral<"authority">;
173
+ fence: z.ZodObject<{
174
+ installationId: z.ZodString;
175
+ resourceType: z.ZodString;
176
+ resourceId: z.ZodString;
177
+ ownerId: z.ZodString;
178
+ epoch: z.ZodNumber;
179
+ }, z.core.$strict>;
180
+ validUntil: z.ZodNumber;
181
+ }, z.core.$strict>, z.ZodObject<{
182
+ method: z.ZodLiteral<"start">;
183
+ operation: z.ZodObject<{
184
+ protocol: z.ZodLiteral<1>;
185
+ installationId: z.ZodString;
186
+ operationId: z.ZodString;
187
+ userId: z.ZodString;
188
+ sessionId: z.ZodOptional<z.ZodString>;
189
+ kind: z.ZodString;
190
+ fence: z.ZodObject<{
191
+ installationId: z.ZodString;
192
+ resourceType: z.ZodString;
193
+ resourceId: z.ZodString;
194
+ ownerId: z.ZodString;
195
+ epoch: z.ZodNumber;
196
+ }, z.core.$strict>;
197
+ payload: z.ZodUnknown;
198
+ }, z.core.$strict>;
199
+ }, z.core.$strict>, z.ZodObject<{
200
+ method: z.ZodLiteral<"poll">;
201
+ run: z.ZodObject<{
202
+ operationId: z.ZodString;
203
+ userId: z.ZodString;
204
+ sessionId: z.ZodOptional<z.ZodString>;
205
+ fence: z.ZodObject<{
206
+ installationId: z.ZodString;
207
+ resourceType: z.ZodString;
208
+ resourceId: z.ZodString;
209
+ ownerId: z.ZodString;
210
+ epoch: z.ZodNumber;
211
+ }, z.core.$strict>;
212
+ }, z.core.$strict>;
213
+ stdoutOffset: z.ZodDefault<z.ZodNumber>;
214
+ stderrOffset: z.ZodDefault<z.ZodNumber>;
215
+ maxBytes: z.ZodDefault<z.ZodNumber>;
216
+ }, z.core.$strict>, z.ZodObject<{
217
+ method: z.ZodLiteral<"write">;
218
+ run: z.ZodObject<{
219
+ operationId: z.ZodString;
220
+ userId: z.ZodString;
221
+ sessionId: z.ZodOptional<z.ZodString>;
222
+ fence: z.ZodObject<{
223
+ installationId: z.ZodString;
224
+ resourceType: z.ZodString;
225
+ resourceId: z.ZodString;
226
+ ownerId: z.ZodString;
227
+ epoch: z.ZodNumber;
228
+ }, z.core.$strict>;
229
+ }, z.core.$strict>;
230
+ actionId: z.ZodString;
231
+ data: z.ZodString;
232
+ eof: z.ZodDefault<z.ZodBoolean>;
233
+ }, z.core.$strict>, z.ZodObject<{
234
+ method: z.ZodLiteral<"resize">;
235
+ run: z.ZodObject<{
236
+ operationId: z.ZodString;
237
+ userId: z.ZodString;
238
+ sessionId: z.ZodOptional<z.ZodString>;
239
+ fence: z.ZodObject<{
240
+ installationId: z.ZodString;
241
+ resourceType: z.ZodString;
242
+ resourceId: z.ZodString;
243
+ ownerId: z.ZodString;
244
+ epoch: z.ZodNumber;
245
+ }, z.core.$strict>;
246
+ }, z.core.$strict>;
247
+ actionId: z.ZodString;
248
+ cols: z.ZodNumber;
249
+ rows: z.ZodNumber;
250
+ }, z.core.$strict>, z.ZodObject<{
251
+ method: z.ZodLiteral<"cancel">;
252
+ run: z.ZodObject<{
253
+ operationId: z.ZodString;
254
+ userId: z.ZodString;
255
+ sessionId: z.ZodOptional<z.ZodString>;
256
+ fence: z.ZodObject<{
257
+ installationId: z.ZodString;
258
+ resourceType: z.ZodString;
259
+ resourceId: z.ZodString;
260
+ ownerId: z.ZodString;
261
+ epoch: z.ZodNumber;
262
+ }, z.core.$strict>;
263
+ }, z.core.$strict>;
264
+ actionId: z.ZodString;
265
+ }, z.core.$strict>], "method">;
266
+ }, z.core.$strict>;
267
+ export declare const ExecutorConfig: z.ZodObject<{
268
+ installationId: z.ZodString;
269
+ workerId: z.ZodString;
270
+ instanceId: z.ZodString;
271
+ releaseId: z.ZodString;
272
+ stateDir: z.ZodString;
273
+ capacity: z.ZodObject<{
274
+ general: z.ZodNumber;
275
+ utility: z.ZodNumber;
276
+ control: z.ZodNumber;
277
+ }, z.core.$strict>;
278
+ maxLeaseMs: z.ZodDefault<z.ZodNumber>;
279
+ maxRunMs: z.ZodDefault<z.ZodNumber>;
280
+ maxLogBytes: z.ZodDefault<z.ZodNumber>;
281
+ principals: z.ZodArray<z.ZodObject<{
282
+ id: z.ZodString;
283
+ tokenHash: z.ZodString;
284
+ role: z.ZodEnum<{
285
+ controller: "controller";
286
+ adapter: "adapter";
287
+ }>;
288
+ ownerId: z.ZodString;
289
+ userIds: z.ZodArray<z.ZodString>;
290
+ cwdRoots: z.ZodArray<z.ZodString>;
291
+ lanes: z.ZodArray<z.ZodEnum<{
292
+ control: "control";
293
+ general: "general";
294
+ utility: "utility";
295
+ }>>;
296
+ credentialIds: z.ZodArray<z.ZodString>;
297
+ }, z.core.$strict>>;
298
+ credentials: z.ZodDefault<z.ZodArray<z.ZodObject<{
299
+ id: z.ZodString;
300
+ installationId: z.ZodString;
301
+ userId: z.ZodString;
302
+ generation: z.ZodNumber;
303
+ env: z.ZodRecord<z.ZodString, z.ZodString>;
304
+ files: z.ZodRecord<z.ZodString, z.ZodString>;
305
+ }, z.core.$strict>>>;
306
+ }, z.core.$strict>;
307
+ export type ExecutorConfig = z.input<typeof ExecutorConfig>;
308
+ export type ResolvedConfig = z.output<typeof ExecutorConfig>;
309
+ export type Principal = ResolvedConfig["principals"][number];
310
+ export declare const AdapterConfig: z.ZodObject<{
311
+ socketPath: z.ZodString;
312
+ principalId: z.ZodString;
313
+ token: z.ZodString;
314
+ hello: z.ZodObject<{
315
+ installationId: z.ZodString;
316
+ instanceId: z.ZodString;
317
+ releaseId: z.ZodString;
318
+ role: z.ZodEnum<{
319
+ web: "web";
320
+ scheduler: "scheduler";
321
+ runner: "runner";
322
+ gateway: "gateway";
323
+ "worker-adapter": "worker-adapter";
324
+ "browser-adapter": "browser-adapter";
325
+ executor: "executor";
326
+ keeper: "keeper";
327
+ storage: "storage";
328
+ }>;
329
+ protocol: z.ZodObject<{
330
+ min: z.ZodNumber;
331
+ max: z.ZodNumber;
332
+ }, z.core.$strict>;
333
+ capabilities: z.ZodArray<z.ZodString>;
334
+ }, z.core.$strict>;
335
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
336
+ }, z.core.$strict>;
337
+ export type AdapterConfig = z.input<typeof AdapterConfig>;
338
+ export type RunReceipt = {
339
+ operationId: string;
340
+ userId: string;
341
+ sessionId: string | null;
342
+ payloadHash: string;
343
+ state: "accepted" | "running" | "completed" | "cancelled" | "unknown";
344
+ pid: number | null;
345
+ pty: boolean;
346
+ lane: z.infer<typeof Lane>;
347
+ stdoutBytes: number;
348
+ stderrBytes: number;
349
+ stdinClosed: boolean;
350
+ exitCode: number | null;
351
+ signal: string | null;
352
+ reason: string | null;
353
+ };
354
+ export type ActionReceipt = {
355
+ actionId: string;
356
+ state: "accepted" | "completed" | "unknown";
357
+ };
358
+ export type PollResult = {
359
+ receipt: RunReceipt;
360
+ stdout: {
361
+ base64: string;
362
+ nextOffset: number;
363
+ };
364
+ stderr: {
365
+ base64: string;
366
+ nextOffset: number;
367
+ };
368
+ };
369
+ export declare class ExecutorError extends Error {
370
+ readonly code: string;
371
+ constructor(code: string, message?: string);
372
+ }
@@ -0,0 +1,29 @@
1
+ /** Node native FD keeper is a daemon child; replacing adapters cannot signal it. */
2
+ export declare class PtySession {
3
+ pid: number;
4
+ private sequence;
5
+ private readonly pending;
6
+ private readonly child;
7
+ private onDataCallback?;
8
+ private onExitCallback?;
9
+ private readonly buffered;
10
+ private exit?;
11
+ readonly ready: Promise<void>;
12
+ constructor(input: {
13
+ argv: string[];
14
+ cwd: string;
15
+ env: Record<string, string>;
16
+ cols: number;
17
+ rows: number;
18
+ });
19
+ private deliverExit;
20
+ onData(callback: (data: Buffer) => void): void;
21
+ onExit(callback: (event: {
22
+ exitCode: number;
23
+ signal: number;
24
+ }) => void): void;
25
+ private request;
26
+ write(data: string): Promise<void>;
27
+ resize(cols: number, rows: number): Promise<void>;
28
+ kill(signal?: string): void;
29
+ }
@@ -0,0 +1,21 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { type RunReceipt } from "./protocol";
3
+ export declare function privateDirectory(path: string): void;
4
+ export declare function readPrivateJson(path: string): unknown;
5
+ /** Single host authority: a separate rollback-mode SQLite exclusive lock survives no process death. */
6
+ export declare class ExecutorStore {
7
+ readonly root: string;
8
+ readonly db: Database;
9
+ private readonly lock;
10
+ constructor(root: string, installationId: string, workerId: string);
11
+ all(): RunReceipt[];
12
+ get(id: string): RunReceipt | null;
13
+ put(receipt: RunReceipt): void;
14
+ outputPath(id: string, stream: "stdout" | "stderr"): string;
15
+ append(id: string, stream: "stdout" | "stderr", data: Buffer): void;
16
+ read(id: string, stream: "stdout" | "stderr", offset: number, end: number, max: number): {
17
+ base64: string;
18
+ nextOffset: number;
19
+ };
20
+ close(): void;
21
+ }
@@ -0,0 +1,53 @@
1
+ import { type ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import { HostExecutorClient } from "./client";
3
+ import { type ExecutorCommand, type ExecutorConfig } from "./protocol";
4
+ import type { OperationEnvelope, OwnershipFence } from "@ricsam/r5d-api/runtime-protocol";
5
+ export declare const testEnvironment: {
6
+ PATH: string;
7
+ HOME: string;
8
+ LANG: string;
9
+ };
10
+ export declare const delay: (ms: number) => Promise<void>;
11
+ export declare function eventually<T>(read: () => Promise<T>, accept: (value: T) => boolean, timeoutMs?: number): Promise<T>;
12
+ export declare function stop(child: ChildProcessWithoutNullStreams, signal?: NodeJS.Signals): Promise<void>;
13
+ export declare class AdapterProcess {
14
+ readonly process: ChildProcessWithoutNullStreams;
15
+ private pending;
16
+ constructor(configPath: string);
17
+ request<T = {
18
+ state: string;
19
+ }>(command: ExecutorCommand): Promise<T>;
20
+ }
21
+ export declare class Harness {
22
+ readonly root: string;
23
+ readonly cwd: string;
24
+ readonly stateDir: string;
25
+ readonly daemonPath: string;
26
+ readonly tokens: {
27
+ [k: string]: string;
28
+ };
29
+ readonly config: ExecutorConfig;
30
+ readonly clients: Record<string, HostExecutorClient>;
31
+ readonly adapterPaths: Record<string, string>;
32
+ readonly adapters: AdapterProcess[];
33
+ daemon?: ChildProcessWithoutNullStreams;
34
+ constructor(options?: Partial<ExecutorConfig>);
35
+ startDaemon(): Promise<void>;
36
+ adapter(id: "blue" | "green" | "third"): AdapterProcess;
37
+ fence(ownerId?: string, epoch?: number): OwnershipFence;
38
+ promote(ownerId?: string, epoch?: number, leaseMs?: number): Promise<unknown>;
39
+ operation(operationId?: string, argv?: string[], ownerId?: string, epoch?: number): OperationEnvelope;
40
+ run(operationId: string, ownerId?: string, epoch?: number): {
41
+ operationId: string;
42
+ userId: string;
43
+ sessionId: string;
44
+ fence: {
45
+ installationId: string;
46
+ resourceType: string;
47
+ resourceId: string;
48
+ ownerId: string;
49
+ epoch: number;
50
+ };
51
+ };
52
+ close(): Promise<void>;
53
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ProjectWorktreeBranch, ProjectWorktreeSnapshot, ProjectWorktreeSnapshotProgress, ProjectWorktreeSnapshotScope, ProjectWorktreeWorkingTreeMode } from "./project-worktrees";
2
2
  import type { ProjectedWorkingTreeEntry, WorkingTreeGitlink } from "./working-tree-mirror";
3
+ import type { WorkspaceHydrationLedgerEntry } from "./workspace-hydration-ledger";
3
4
  import type { WorkspaceGitMountData, WorkspaceHydrationReceipt, WorkspaceHydrationRecoveryRequired, WorkspaceHydrationPreservationResult, WorkspaceHydrationMountSkip } from "./workspace-git-sync";
4
5
  import type { WorkspaceHydrationMergeBasis } from "./workspace-hydration-merge";
5
6
  import type { WorkspaceMergeProjectionMount, WorkspaceMergeProjectionResult } from "./workspace-merge-projection";
@@ -64,8 +65,13 @@ export type WorkspaceFilesystemJobTable = {
64
65
  result: {
65
66
  hydratedMountIds: string[];
66
67
  skippedMounts: WorkspaceHydrationMountSkip[];
67
- /** Per merge-hydrated mount, the blob each replaced path held before hydration (the stale-rewrite detector's input). */
68
- hydratedPreBlobs: Record<string, Record<string, string>>;
68
+ /**
69
+ * Per merge-hydrated mount, what hydration replaced at each path: the
70
+ * previous and written blobs and the `lstat` it left behind (the
71
+ * hydration ledger's record, minus the process-liveness flag the
72
+ * control thread adds).
73
+ */
74
+ hydratedEntries: Record<string, Record<string, Omit<WorkspaceHydrationLedgerEntry, "processLiveAcrossHydration">>>;
69
75
  };
70
76
  };
71
77
  /** Pre-clone hydration of visible mounts without a transaction (no outer Git directory yet). */
@@ -107,8 +113,8 @@ export type WorkspaceFilesystemJobTable = {
107
113
  basisHead: string;
108
114
  currentHead: string;
109
115
  attemptId: string;
110
- /** Blob ids the last merge hydration replaced, by mount-relative path; a changed file hashing to one is a stale rewrite. */
111
- staleRewriteBlobs?: Record<string, string>;
116
+ /** What the last merge hydration replaced, by mount-relative path (see WorkspaceHydrationLedger). */
117
+ hydrationLedger?: Record<string, WorkspaceHydrationLedgerEntry>;
112
118
  };
113
119
  result: WorkspaceMergeProjectionResult;
114
120
  };
@@ -121,7 +127,9 @@ export type WorkspaceFilesystemJobTable = {
121
127
  input: {
122
128
  workspacePath: string;
123
129
  mount: WorkspaceGitMountData;
124
- staleRewriteBlobs?: Record<string, string>;
130
+ hydrationLedger?: Record<string, WorkspaceHydrationLedgerEntry>;
131
+ /** Stop after the ledger pass; mirror nothing. */
132
+ checkOnly?: boolean;
125
133
  };
126
134
  result: {
127
135
  gitlinks: WorkingTreeGitlink[];
@@ -129,6 +137,12 @@ export type WorkspaceFilesystemJobTable = {
129
137
  /** Wall-clock time the mirror finished reading; projected stats younger than this minus a window are not trusted. */
130
138
  readAtMs: number;
131
139
  staleRewritePaths: string[];
140
+ /**
141
+ * Ledger paths a process alive across their hydration rewrote: nothing
142
+ * was mirrored, and the mount must be projected through the merge path
143
+ * with those paths merged against what the process read.
144
+ */
145
+ ledgerMergePaths: string[];
132
146
  /** Ledger paths whose checkout content moved on from both the replaced and the hydrated bytes. */
133
147
  staleRewriteCleared: string[];
134
148
  };
@@ -1,6 +1,6 @@
1
1
  import { type PreparedWorkingTreeMirror, type ProjectedWorkingTreeEntry, type WorkingTreeGitlink, type WorkingTreeMirrorPlan, type WorkingTreeMirrorScope, type WorkingTreeSourceMode } from "./working-tree-mirror";
2
2
  import { type WorkspaceHydrationMergeBasis, type WorkspaceHydrationMergeDecision, type WorkspaceHydrationMountSkip as WorkspaceHydrationMountSkipBase } from "./workspace-hydration-merge";
3
- import { WorkspaceHydrationPreBlobLedger } from "./workspace-hydration-ledger";
3
+ import { WorkspaceHydrationLedger, type WorkspaceHydrationLedgerEntry } from "./workspace-hydration-ledger";
4
4
  export declare const WORKSPACE_GIT_BRANCH = "main";
5
5
  export declare const MAX_WORKSPACE_GIT_DIFF_BYTES: number;
6
6
  export declare const WORKSPACE_GIT_CONFIRMED_LARGE_DIFF_PUSH_OPTION = "r5d-confirm-large-diff-v1";
@@ -10,11 +10,13 @@ export declare const WORKSPACE_GIT_HYDRATION_RECOVERIES = "r5d/workspace-hydrati
10
10
  export declare const WORKSPACE_GIT_CHECKOUT_DURABILITY = "r5d/workspace-checkout-durability";
11
11
  /** `R5D_MERGE_HYDRATION=0` restores the plain byte mirror for post-publication hydration (docs/merge-hydration-design.md §4). */
12
12
  export declare const WORKSPACE_MERGE_HYDRATION_SWITCH = "R5D_MERGE_HYDRATION";
13
- declare function hydrationPreBlobLedger(workspacePath: string): WorkspaceHydrationPreBlobLedger;
13
+ /** `R5D_PROCESS_BUSY_FENCE=1` makes a live process or PTY skip its mount again, as every cycle did before merge hydration. */
14
+ export declare const WORKSPACE_PROCESS_BUSY_FENCE_SWITCH = "R5D_PROCESS_BUSY_FENCE";
15
+ declare function hydrationPreBlobLedger(workspacePath: string): WorkspaceHydrationLedger;
14
16
  export type WorkspaceHydrationMountSkip = WorkspaceHydrationMountSkipBase & {
15
17
  retainedPaths?: string[];
16
18
  };
17
- export type WorkspaceMountSkipReason = WorkspaceHydrationMountSkip["reason"] | "stale_rewrite_detected";
19
+ export type WorkspaceMountSkipReason = WorkspaceHydrationMountSkip["reason"] | "stale_rewrite_detected" | "projection_conflict_deferred";
18
20
  /** Why a mount was left at its recorded basis this cycle, with the paths involved; a diagnostic beside `skippedMountIds`. */
19
21
  export type WorkspaceMountSkipReasons = Record<string, {
20
22
  reason: WorkspaceMountSkipReason;
@@ -124,6 +126,16 @@ export type WorkspaceGitMount = {
124
126
  /** Remove the outer-workspace subtree when the mounted source was intentionally deleted. */
125
127
  deleteWhenSourceMissing?: boolean;
126
128
  busy?: () => boolean;
129
+ /**
130
+ * True while a worker-tracked process or PTY targets this mount. Not a
131
+ * fence (a busy checkout is still projected and hydrated; merge hydration
132
+ * folds the inbound change into it): a conflict found on a mount with a
133
+ * live process is deferred instead of reported, and the hydration ledger
134
+ * records the liveness so a stale-read rewrite by that process is merged
135
+ * at the next projection. `R5D_PROCESS_BUSY_FENCE=1` folds it back into
136
+ * `busy` (see `mountBusy`).
137
+ */
138
+ processLive?: () => boolean;
127
139
  /** Control-thread diagnostics only; never sent to a filesystem job. */
128
140
  describeHolders?: () => string;
129
141
  /** Monotonic/opaque visible-mutation token used to catch short writes that begin and end between busy checks. */
@@ -359,7 +371,7 @@ export declare function runHydrationTransactionJob(input: {
359
371
  }): {
360
372
  hydratedMountIds: string[];
361
373
  skippedMounts: WorkspaceHydrationMountSkip[];
362
- hydratedPreBlobs: Record<string, Record<string, string>>;
374
+ hydratedEntries: Record<string, Record<string, Omit<WorkspaceHydrationLedgerEntry, "processLiveAcrossHydration">>>;
363
375
  };
364
376
  /** Executor job body: hydrate visible mounts before an outer clone exists (no transaction to record). */
365
377
  export declare function runHydrationRawJob(input: {
@@ -454,16 +466,23 @@ export type SynchronizeWorkspaceGitInput = {
454
466
  hydrationHooks?: WorkspaceHydrationTransactionHooks;
455
467
  };
456
468
  export declare function synchronizeWorkspaceGit(input: SynchronizeWorkspaceGitInput): Promise<WorkspaceGitSyncResult>;
457
- /** Executor job body: byte-mirror one visible mount into the outer checkout, recording what it read. */
469
+ /**
470
+ * Executor job body: byte-mirror one visible mount into the outer checkout,
471
+ * recording what it read. With `checkOnly` it stops after the ledger pass:
472
+ * the cycle decides the mount's route (mirror, merge, or a stale-rewrite
473
+ * refusal) before any outer write.
474
+ */
458
475
  export declare function runProjectionMirrorJob(input: {
459
476
  workspacePath: string;
460
477
  mount: WorkspaceGitMountData;
461
- staleRewriteBlobs?: Record<string, string>;
478
+ hydrationLedger?: Record<string, WorkspaceHydrationLedgerEntry>;
479
+ checkOnly?: boolean;
462
480
  }): {
463
481
  gitlinks: WorkingTreeGitlink[];
464
482
  projectedFiles: Record<string, ProjectedWorkingTreeEntry>;
465
483
  readAtMs: number;
466
484
  staleRewritePaths: string[];
485
+ ledgerMergePaths: string[];
467
486
  staleRewriteCleared: string[];
468
487
  };
469
488
  /** Executor job body: outer-tree edits that follow the mirrors, in the cycle's order. */