@ricsam/r5d-worker 0.0.59 → 0.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/main.cjs +303 -381
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/workspace-convergence.cjs +42 -106
- package/dist/cjs/workspace-manifest-admission.cjs +4 -10
- package/dist/cjs/workspace-sync.cjs +2 -8
- package/dist/mjs/main.mjs +310 -396
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/workspace-convergence.mjs +37 -99
- package/dist/mjs/workspace-manifest-admission.mjs +3 -8
- package/dist/mjs/workspace-sync.mjs +2 -8
- package/dist/types/workspace-convergence.d.ts +15 -35
- package/dist/types/workspace-incident-state.d.ts +1 -1
- package/dist/types/workspace-manifest-admission.d.ts +6 -9
- package/dist/types/workspace-sync.d.ts +1 -1
- package/package.json +1 -1
package/dist/mjs/package.json
CHANGED
|
@@ -1,68 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
const
|
|
3
|
+
const WORKSPACE_PUBLICATION_QUIET_MS = 5e3;
|
|
4
4
|
const WORKSPACE_IDLE_SAFETY_SCAN_MS = 6e4;
|
|
5
5
|
const WORKSPACE_MANIFEST_REVISION_PATTERN = /^[0-9a-f]{64}$/;
|
|
6
|
-
class WorkspaceFilesystemWriterGate {
|
|
7
|
-
activeWriters = 0;
|
|
8
|
-
checkpointActive = false;
|
|
9
|
-
waitingWriters = [];
|
|
10
|
-
waitingCheckpoints = [];
|
|
11
|
-
acquireWriter() {
|
|
12
|
-
if (!this.checkpointActive && this.waitingCheckpoints.length === 0) {
|
|
13
|
-
this.activeWriters += 1;
|
|
14
|
-
return Promise.resolve(this.writerRelease());
|
|
15
|
-
}
|
|
16
|
-
return new Promise((resolve) => this.waitingWriters.push(resolve));
|
|
17
|
-
}
|
|
18
|
-
tryAcquireCheckpoint() {
|
|
19
|
-
if (this.checkpointActive || this.activeWriters > 0 || this.waitingCheckpoints.length > 0) return null;
|
|
20
|
-
this.checkpointActive = true;
|
|
21
|
-
return this.checkpointRelease();
|
|
22
|
-
}
|
|
23
|
-
acquireCheckpoint() {
|
|
24
|
-
const immediate = this.tryAcquireCheckpoint();
|
|
25
|
-
if (immediate) return Promise.resolve(immediate);
|
|
26
|
-
return new Promise((resolve) => this.waitingCheckpoints.push(resolve));
|
|
27
|
-
}
|
|
28
|
-
checkpointRelease() {
|
|
29
|
-
let released = false;
|
|
30
|
-
return () => {
|
|
31
|
-
if (released) return;
|
|
32
|
-
released = true;
|
|
33
|
-
this.checkpointActive = false;
|
|
34
|
-
this.drain();
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
writerRelease() {
|
|
38
|
-
let released = false;
|
|
39
|
-
return () => {
|
|
40
|
-
if (released) return;
|
|
41
|
-
released = true;
|
|
42
|
-
this.activeWriters -= 1;
|
|
43
|
-
this.drain();
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
drain() {
|
|
47
|
-
if (this.checkpointActive || this.activeWriters > 0) return;
|
|
48
|
-
const checkpoint = this.waitingCheckpoints.shift();
|
|
49
|
-
if (checkpoint) {
|
|
50
|
-
this.checkpointActive = true;
|
|
51
|
-
checkpoint(this.checkpointRelease());
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
while (this.waitingWriters.length > 0) {
|
|
55
|
-
const resolve = this.waitingWriters.shift();
|
|
56
|
-
if (!resolve) continue;
|
|
57
|
-
this.activeWriters += 1;
|
|
58
|
-
resolve(this.writerRelease());
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const PROCESS_WORKSPACE_FILESYSTEM_WRITERS = new WorkspaceFilesystemWriterGate();
|
|
63
|
-
function processWorkspaceFilesystemWriterGate() {
|
|
64
|
-
return PROCESS_WORKSPACE_FILESYSTEM_WRITERS;
|
|
65
|
-
}
|
|
66
6
|
class WorkspaceManifestRevisionFence {
|
|
67
7
|
sequence = 0;
|
|
68
8
|
requestedRevision = null;
|
|
@@ -88,7 +28,7 @@ class WorkspaceManifestRevisionFence {
|
|
|
88
28
|
return this.completedRevision === this.requestedRevision ? this.completedRevision : null;
|
|
89
29
|
}
|
|
90
30
|
}
|
|
91
|
-
function
|
|
31
|
+
function workspacePublicationTelemetry(input) {
|
|
92
32
|
return {
|
|
93
33
|
totalMs: Math.max(0, input.finishedAt - input.requestedAt),
|
|
94
34
|
queueMs: Math.max(0, input.prepareStartedAt - input.requestedAt),
|
|
@@ -96,21 +36,21 @@ function workspaceCheckpointTelemetry(input) {
|
|
|
96
36
|
synchronizeMs: Math.max(0, input.finishedAt - input.synchronizeStartedAt)
|
|
97
37
|
};
|
|
98
38
|
}
|
|
99
|
-
function
|
|
39
|
+
function workspacePublicationIncidentAction(requestId) {
|
|
100
40
|
return requestId ? "request_terminal_authority" : "defer_automatic";
|
|
101
41
|
}
|
|
102
|
-
class
|
|
42
|
+
class ExplicitWorkspacePublicationQueue {
|
|
103
43
|
scheduled;
|
|
104
44
|
queued = [];
|
|
105
|
-
schedule(
|
|
106
|
-
if (pendingRequestId ===
|
|
45
|
+
schedule(publication, pendingRequestId) {
|
|
46
|
+
if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
|
|
107
47
|
return false;
|
|
108
48
|
}
|
|
109
49
|
if (pendingRequestId || this.scheduled) {
|
|
110
|
-
this.queued.push(
|
|
50
|
+
this.queued.push(publication);
|
|
111
51
|
return false;
|
|
112
52
|
}
|
|
113
|
-
this.scheduled =
|
|
53
|
+
this.scheduled = publication;
|
|
114
54
|
return true;
|
|
115
55
|
}
|
|
116
56
|
hasScheduled() {
|
|
@@ -119,11 +59,11 @@ class ExplicitWorkspaceCheckpointQueue {
|
|
|
119
59
|
consumeScheduled(requestId) {
|
|
120
60
|
if (this.scheduled?.requestId === requestId) this.scheduled = void 0;
|
|
121
61
|
}
|
|
122
|
-
enqueue(
|
|
123
|
-
if (pendingRequestId ===
|
|
62
|
+
enqueue(publication, pendingRequestId) {
|
|
63
|
+
if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
|
|
124
64
|
return;
|
|
125
65
|
}
|
|
126
|
-
this.queued.push(
|
|
66
|
+
this.queued.push(publication);
|
|
127
67
|
}
|
|
128
68
|
next() {
|
|
129
69
|
return this.queued.shift();
|
|
@@ -161,13 +101,13 @@ class WorkspaceConvergenceState {
|
|
|
161
101
|
constructor(statePath) {
|
|
162
102
|
this.statePath = statePath;
|
|
163
103
|
this.state = readWorkspaceConvergenceState(statePath);
|
|
164
|
-
this.
|
|
104
|
+
this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
|
|
165
105
|
}
|
|
166
106
|
statePath;
|
|
167
107
|
state;
|
|
168
|
-
|
|
108
|
+
publicationState;
|
|
169
109
|
snapshot() {
|
|
170
|
-
return { ...this.state,
|
|
110
|
+
return { ...this.state, publicationState: this.publicationState };
|
|
171
111
|
}
|
|
172
112
|
setLocalHead(localHead) {
|
|
173
113
|
if (!validHead(localHead)) throw new Error("Invalid local workspace head");
|
|
@@ -183,39 +123,39 @@ class WorkspaceConvergenceState {
|
|
|
183
123
|
}
|
|
184
124
|
markDirty() {
|
|
185
125
|
this.state.dirtyGeneration += 1;
|
|
186
|
-
if (this.
|
|
126
|
+
if (this.publicationState === "idle") this.publicationState = "scheduled";
|
|
187
127
|
this.persist();
|
|
188
128
|
return this.state.dirtyGeneration;
|
|
189
129
|
}
|
|
190
130
|
schedule() {
|
|
191
|
-
if (this.
|
|
131
|
+
if (this.publicationState === "idle") this.publicationState = "scheduled";
|
|
192
132
|
}
|
|
193
133
|
beginPreparing() {
|
|
194
|
-
if (this.
|
|
195
|
-
throw new Error("A workspace
|
|
134
|
+
if (this.publicationState === "preparing" || this.publicationState === "submitting") {
|
|
135
|
+
throw new Error("A workspace publication is already in flight");
|
|
196
136
|
}
|
|
197
|
-
this.
|
|
137
|
+
this.publicationState = "preparing";
|
|
198
138
|
}
|
|
199
139
|
beginSubmitting() {
|
|
200
|
-
if (this.
|
|
201
|
-
this.
|
|
140
|
+
if (this.publicationState !== "preparing") throw new Error("Workspace publication authority was not prepared");
|
|
141
|
+
this.publicationState = "submitting";
|
|
202
142
|
}
|
|
203
143
|
defer() {
|
|
204
|
-
this.
|
|
144
|
+
this.publicationState = "scheduled";
|
|
205
145
|
}
|
|
206
146
|
block() {
|
|
207
|
-
this.
|
|
147
|
+
this.publicationState = "blocked";
|
|
208
148
|
}
|
|
209
149
|
releaseBlock() {
|
|
210
|
-
this.
|
|
150
|
+
this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
|
|
211
151
|
}
|
|
212
152
|
observeIncidentState(blocked) {
|
|
213
|
-
if (this.
|
|
153
|
+
if (this.publicationState === "preparing" || this.publicationState === "submitting") return;
|
|
214
154
|
if (blocked) this.block();
|
|
215
155
|
else this.releaseBlock();
|
|
216
156
|
}
|
|
217
|
-
|
|
218
|
-
this.
|
|
157
|
+
resetTransientPublicationState() {
|
|
158
|
+
this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
|
|
219
159
|
}
|
|
220
160
|
complete(input) {
|
|
221
161
|
if (!validGeneration(input.generation) || input.generation > this.state.dirtyGeneration) {
|
|
@@ -227,7 +167,7 @@ class WorkspaceConvergenceState {
|
|
|
227
167
|
this.state.localHead = input.canonicalHead;
|
|
228
168
|
this.state.desiredCanonicalHead = input.canonicalHead;
|
|
229
169
|
}
|
|
230
|
-
this.
|
|
170
|
+
this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
|
|
231
171
|
this.persist();
|
|
232
172
|
}
|
|
233
173
|
persist() {
|
|
@@ -247,29 +187,27 @@ function processWorkspaceConvergenceState(statePath) {
|
|
|
247
187
|
PROCESS_WORKSPACE_CONVERGENCE_STATES.set(key, created);
|
|
248
188
|
return created;
|
|
249
189
|
}
|
|
250
|
-
async function
|
|
251
|
-
input.
|
|
190
|
+
async function waitForWorkspacePublicationOnShutdown(input) {
|
|
191
|
+
input.forcePublication();
|
|
252
192
|
const deadline = Date.now() + (input.timeoutMs ?? 1e4);
|
|
253
193
|
const pollMs = input.pollMs ?? 50;
|
|
254
194
|
while (Date.now() < deadline) {
|
|
255
195
|
const snapshot = input.snapshot();
|
|
256
|
-
if (snapshot.
|
|
257
|
-
if (snapshot.
|
|
196
|
+
if (snapshot.publicationState === "blocked") return "blocked";
|
|
197
|
+
if (snapshot.publicationState === "idle" && snapshot.publishedGeneration >= snapshot.dirtyGeneration) return "settled";
|
|
258
198
|
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
259
199
|
}
|
|
260
200
|
return "timed_out";
|
|
261
201
|
}
|
|
262
202
|
export {
|
|
263
|
-
|
|
264
|
-
WORKSPACE_CHECKPOINT_QUIET_MS,
|
|
203
|
+
ExplicitWorkspacePublicationQueue,
|
|
265
204
|
WORKSPACE_IDLE_SAFETY_SCAN_MS,
|
|
205
|
+
WORKSPACE_PUBLICATION_QUIET_MS,
|
|
266
206
|
WorkspaceConvergenceState,
|
|
267
|
-
WorkspaceFilesystemWriterGate,
|
|
268
207
|
WorkspaceManifestRevisionFence,
|
|
269
208
|
processWorkspaceConvergenceState,
|
|
270
|
-
processWorkspaceFilesystemWriterGate,
|
|
271
209
|
readWorkspaceConvergenceState,
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
210
|
+
waitForWorkspacePublicationOnShutdown,
|
|
211
|
+
workspacePublicationIncidentAction,
|
|
212
|
+
workspacePublicationTelemetry
|
|
275
213
|
};
|
|
@@ -5,7 +5,7 @@ function hasNormalGitDirectory(checkoutPath) {
|
|
|
5
5
|
const gitPath = path.join(checkoutPath, ".git");
|
|
6
6
|
return fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory();
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function inspectWorkspaceManifestFilesystem(input) {
|
|
9
9
|
const firstBootstrap = !hasNormalGitDirectory(input.workspaceShadowRoot);
|
|
10
10
|
const missingCheckouts = [];
|
|
11
11
|
const migratedProjectIds = [];
|
|
@@ -22,14 +22,9 @@ function inspectWorkspaceManifestAdmission(input) {
|
|
|
22
22
|
return {
|
|
23
23
|
firstBootstrap,
|
|
24
24
|
missingCheckouts,
|
|
25
|
-
migratedProjectIds
|
|
26
|
-
requiresVisibleLease: firstBootstrap || migratedProjectIds.length > 0
|
|
25
|
+
migratedProjectIds
|
|
27
26
|
};
|
|
28
27
|
}
|
|
29
|
-
async function acquireWorkspaceManifestVisibleLease(gate, admission) {
|
|
30
|
-
return admission.requiresVisibleLease ? await gate.acquireCheckpoint() : void 0;
|
|
31
|
-
}
|
|
32
28
|
export {
|
|
33
|
-
|
|
34
|
-
inspectWorkspaceManifestAdmission
|
|
29
|
+
inspectWorkspaceManifestFilesystem
|
|
35
30
|
};
|
|
@@ -1708,9 +1708,7 @@ function assertWorkspaceQuarantineRef(quarantineRef) {
|
|
|
1708
1708
|
const prefix = quarantineRef.startsWith(WORKSPACE_PUBLICATION_REF_PREFIX) ? WORKSPACE_PUBLICATION_REF_PREFIX : WORKSPACE_INTENT_REF_PREFIX;
|
|
1709
1709
|
const suffix = quarantineRef.slice(prefix.length);
|
|
1710
1710
|
if (!quarantineRef.startsWith(prefix) || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(suffix)) {
|
|
1711
|
-
throw new Error(
|
|
1712
|
-
`Workspace candidate ref must be below ${WORKSPACE_PUBLICATION_REF_PREFIX} or ${WORKSPACE_INTENT_REF_PREFIX}`
|
|
1713
|
-
);
|
|
1711
|
+
throw new Error(`Workspace candidate ref must be below ${WORKSPACE_PUBLICATION_REF_PREFIX} or ${WORKSPACE_INTENT_REF_PREFIX}`);
|
|
1714
1712
|
}
|
|
1715
1713
|
const result = Bun.spawnSync(["git", "check-ref-format", quarantineRef], {
|
|
1716
1714
|
stdout: "pipe",
|
|
@@ -1928,11 +1926,7 @@ async function synchronizeWorkspace(rawInput) {
|
|
|
1928
1926
|
const destructiveReductions = destructiveCheckoutReductions(input, baseRevision);
|
|
1929
1927
|
if (destructiveReductions.length > 0 && !input.confirmedLargeDiff) {
|
|
1930
1928
|
const summary = destructiveReductions.map(({ root, trackedBefore, trackedAfter }) => `${root} (${trackedBefore} -> ${trackedAfter} tracked files)`).join(", ");
|
|
1931
|
-
return preserveLargeDiffCandidate(
|
|
1932
|
-
input,
|
|
1933
|
-
observed,
|
|
1934
|
-
`Workspace safety guard blocked a destructive checkout reduction: ${summary}`
|
|
1935
|
-
);
|
|
1929
|
+
return preserveLargeDiffCandidate(input, observed, `Workspace safety guard blocked a destructive checkout reduction: ${summary}`);
|
|
1936
1930
|
}
|
|
1937
1931
|
if (paths.length > 0 && diffSizeBytes > MAX_WORKSPACE_SYNC_DIFF_BYTES && !input.confirmedLargeDiff && !input.trigger.canonicalCheckoutOnly) {
|
|
1938
1932
|
return preserveLargeDiffCandidate(
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const WORKSPACE_PUBLICATION_QUIET_MS = 5000;
|
|
2
2
|
export declare const WORKSPACE_IDLE_SAFETY_SCAN_MS = 60000;
|
|
3
|
-
export type
|
|
3
|
+
export type WorkspacePublicationState = "idle" | "scheduled" | "preparing" | "submitting" | "blocked";
|
|
4
4
|
export type WorkspaceConvergenceSnapshot = {
|
|
5
5
|
localHead: string | null;
|
|
6
6
|
desiredCanonicalHead: string | null;
|
|
7
7
|
dirtyGeneration: number;
|
|
8
8
|
publishedGeneration: number;
|
|
9
|
-
|
|
9
|
+
publicationState: WorkspacePublicationState;
|
|
10
10
|
};
|
|
11
|
-
export type
|
|
11
|
+
export type ExplicitWorkspacePublication<TTrigger> = {
|
|
12
12
|
requestId: string;
|
|
13
13
|
trigger: TTrigger;
|
|
14
14
|
};
|
|
@@ -16,26 +16,6 @@ export type WorkspaceManifestRevisionToken = {
|
|
|
16
16
|
sequence: number;
|
|
17
17
|
revision: string;
|
|
18
18
|
};
|
|
19
|
-
export type WorkspaceWriterLease = () => void;
|
|
20
|
-
/**
|
|
21
|
-
* Makes checkpoint admission atomic with command startup. Once a checkpoint
|
|
22
|
-
* lease is admitted, later writers wait; once a writer lease is admitted, a
|
|
23
|
-
* checkpoint must defer. Writer acquisition increments synchronously before
|
|
24
|
-
* its promise resolves, covering asynchronous environment setup and spawn.
|
|
25
|
-
*/
|
|
26
|
-
export declare class WorkspaceFilesystemWriterGate {
|
|
27
|
-
private activeWriters;
|
|
28
|
-
private checkpointActive;
|
|
29
|
-
private readonly waitingWriters;
|
|
30
|
-
private readonly waitingCheckpoints;
|
|
31
|
-
acquireWriter(): Promise<WorkspaceWriterLease>;
|
|
32
|
-
tryAcquireCheckpoint(): WorkspaceWriterLease | null;
|
|
33
|
-
acquireCheckpoint(): Promise<WorkspaceWriterLease>;
|
|
34
|
-
private checkpointRelease;
|
|
35
|
-
private writerRelease;
|
|
36
|
-
private drain;
|
|
37
|
-
}
|
|
38
|
-
export declare function processWorkspaceFilesystemWriterGate(): WorkspaceFilesystemWriterGate;
|
|
39
19
|
export declare class WorkspaceManifestRevisionFence {
|
|
40
20
|
private sequence;
|
|
41
21
|
private requestedRevision;
|
|
@@ -45,7 +25,7 @@ export declare class WorkspaceManifestRevisionFence {
|
|
|
45
25
|
complete(token: WorkspaceManifestRevisionToken): boolean;
|
|
46
26
|
readyRevision(): string | null;
|
|
47
27
|
}
|
|
48
|
-
export declare function
|
|
28
|
+
export declare function workspacePublicationTelemetry(input: {
|
|
49
29
|
requestedAt: number;
|
|
50
30
|
prepareStartedAt: number;
|
|
51
31
|
synchronizeStartedAt: number;
|
|
@@ -56,22 +36,22 @@ export declare function workspaceCheckpointTelemetry(input: {
|
|
|
56
36
|
prepareMs: number;
|
|
57
37
|
synchronizeMs: number;
|
|
58
38
|
};
|
|
59
|
-
export declare function
|
|
60
|
-
export declare class
|
|
39
|
+
export declare function workspacePublicationIncidentAction(requestId: string | undefined): "defer_automatic" | "request_terminal_authority";
|
|
40
|
+
export declare class ExplicitWorkspacePublicationQueue<TTrigger> {
|
|
61
41
|
private scheduled;
|
|
62
42
|
private readonly queued;
|
|
63
|
-
schedule(
|
|
43
|
+
schedule(publication: ExplicitWorkspacePublication<TTrigger>, pendingRequestId?: string): boolean;
|
|
64
44
|
hasScheduled(): boolean;
|
|
65
45
|
consumeScheduled(requestId: string): void;
|
|
66
|
-
enqueue(
|
|
67
|
-
next():
|
|
46
|
+
enqueue(publication: ExplicitWorkspacePublication<TTrigger>, pendingRequestId?: string): void;
|
|
47
|
+
next(): ExplicitWorkspacePublication<TTrigger> | undefined;
|
|
68
48
|
}
|
|
69
|
-
type PersistedWorkspaceConvergenceState = Omit<WorkspaceConvergenceSnapshot, "
|
|
49
|
+
type PersistedWorkspaceConvergenceState = Omit<WorkspaceConvergenceSnapshot, "publicationState">;
|
|
70
50
|
export declare function readWorkspaceConvergenceState(statePath: string): PersistedWorkspaceConvergenceState;
|
|
71
51
|
export declare class WorkspaceConvergenceState {
|
|
72
52
|
private readonly statePath;
|
|
73
53
|
private state;
|
|
74
|
-
private
|
|
54
|
+
private publicationState;
|
|
75
55
|
constructor(statePath: string);
|
|
76
56
|
snapshot(): WorkspaceConvergenceSnapshot;
|
|
77
57
|
setLocalHead(localHead: string | null): void;
|
|
@@ -84,7 +64,7 @@ export declare class WorkspaceConvergenceState {
|
|
|
84
64
|
block(): void;
|
|
85
65
|
releaseBlock(): void;
|
|
86
66
|
observeIncidentState(blocked: boolean): void;
|
|
87
|
-
|
|
67
|
+
resetTransientPublicationState(): void;
|
|
88
68
|
complete(input: {
|
|
89
69
|
generation: number;
|
|
90
70
|
canonicalHead: string | null;
|
|
@@ -93,9 +73,9 @@ export declare class WorkspaceConvergenceState {
|
|
|
93
73
|
private persist;
|
|
94
74
|
}
|
|
95
75
|
export declare function processWorkspaceConvergenceState(statePath: string): WorkspaceConvergenceState;
|
|
96
|
-
export declare function
|
|
76
|
+
export declare function waitForWorkspacePublicationOnShutdown(input: {
|
|
97
77
|
snapshot: () => WorkspaceConvergenceSnapshot;
|
|
98
|
-
|
|
78
|
+
forcePublication: () => void;
|
|
99
79
|
timeoutMs?: number;
|
|
100
80
|
pollMs?: number;
|
|
101
81
|
}): Promise<"settled" | "blocked" | "timed_out">;
|
|
@@ -5,7 +5,7 @@ export type WorkspaceIncidentUpdate = {
|
|
|
5
5
|
/**
|
|
6
6
|
* WebSocket writes are ordered, but independent server handlers can decide an
|
|
7
7
|
* incident state under the user lock and write their messages after releasing
|
|
8
|
-
* it. Remember terminal incident IDs so a delayed
|
|
8
|
+
* it. Remember terminal incident IDs so a delayed publication response cannot
|
|
9
9
|
* resurrect a barrier that this connection has already observed as terminal.
|
|
10
10
|
*/
|
|
11
11
|
export declare class WorkspaceIncidentOrderingFence {
|
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
import type { WorkspaceFilesystemWriterGate, WorkspaceWriterLease } from "./workspace-convergence";
|
|
2
1
|
export type WorkspaceManifestCheckout = {
|
|
3
2
|
projectId: string;
|
|
4
3
|
projectPath: string;
|
|
5
4
|
checkoutPathSegments: [namespace: string, project: string];
|
|
6
5
|
branches: string[];
|
|
7
6
|
};
|
|
8
|
-
export type
|
|
7
|
+
export type WorkspaceManifestFilesystemState = {
|
|
9
8
|
firstBootstrap: boolean;
|
|
10
9
|
missingCheckouts: Array<{
|
|
11
10
|
projectId: string;
|
|
12
11
|
branchName: string;
|
|
13
12
|
}>;
|
|
14
13
|
migratedProjectIds: string[];
|
|
15
|
-
requiresVisibleLease: boolean;
|
|
16
14
|
};
|
|
17
15
|
/**
|
|
18
|
-
* Inspects
|
|
19
|
-
*
|
|
20
|
-
*
|
|
16
|
+
* Inspects manifest-related filesystem state without reserving visible paths.
|
|
17
|
+
* Missing checkouts are target-specific pending work and hydrate
|
|
18
|
+
* opportunistically without delaying unrelated targets or running commands.
|
|
21
19
|
*/
|
|
22
|
-
export declare function
|
|
20
|
+
export declare function inspectWorkspaceManifestFilesystem(input: {
|
|
23
21
|
projectsRoot: string;
|
|
24
22
|
workspaceShadowRoot: string;
|
|
25
23
|
projects: WorkspaceManifestCheckout[];
|
|
26
|
-
}):
|
|
27
|
-
export declare function acquireWorkspaceManifestVisibleLease(gate: WorkspaceFilesystemWriterGate, admission: WorkspaceManifestAdmission): Promise<WorkspaceWriterLease | undefined>;
|
|
24
|
+
}): WorkspaceManifestFilesystemState;
|
|
@@ -76,7 +76,7 @@ export type WorkspaceSyncInput = {
|
|
|
76
76
|
* Workers never publish the canonical workspace branch directly.
|
|
77
77
|
*/
|
|
78
78
|
quarantineRef?: string;
|
|
79
|
-
/** Exact canonical head fenced by
|
|
79
|
+
/** Exact canonical head fenced by publication authority. */
|
|
80
80
|
expectedCanonicalHead?: string | null;
|
|
81
81
|
confirmedLargeDiff?: boolean;
|
|
82
82
|
confirmationReason?: string;
|