@ricsam/r5d-worker 0.0.58 → 0.0.60

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.58",
3
+ "version": "0.0.60",
4
4
  "type": "commonjs"
5
5
  }
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var workspace_convergence_exports = {};
30
+ __export(workspace_convergence_exports, {
31
+ ExplicitWorkspacePublicationQueue: () => ExplicitWorkspacePublicationQueue,
32
+ WORKSPACE_IDLE_SAFETY_SCAN_MS: () => WORKSPACE_IDLE_SAFETY_SCAN_MS,
33
+ WORKSPACE_PUBLICATION_QUIET_MS: () => WORKSPACE_PUBLICATION_QUIET_MS,
34
+ WorkspaceConvergenceState: () => WorkspaceConvergenceState,
35
+ WorkspaceManifestRevisionFence: () => WorkspaceManifestRevisionFence,
36
+ processWorkspaceConvergenceState: () => processWorkspaceConvergenceState,
37
+ readWorkspaceConvergenceState: () => readWorkspaceConvergenceState,
38
+ waitForWorkspacePublicationOnShutdown: () => waitForWorkspacePublicationOnShutdown,
39
+ workspacePublicationIncidentAction: () => workspacePublicationIncidentAction,
40
+ workspacePublicationTelemetry: () => workspacePublicationTelemetry
41
+ });
42
+ module.exports = __toCommonJS(workspace_convergence_exports);
43
+ var import_node_fs = __toESM(require("node:fs"), 1);
44
+ var import_node_path = __toESM(require("node:path"), 1);
45
+ const WORKSPACE_PUBLICATION_QUIET_MS = 5e3;
46
+ const WORKSPACE_IDLE_SAFETY_SCAN_MS = 6e4;
47
+ const WORKSPACE_MANIFEST_REVISION_PATTERN = /^[0-9a-f]{64}$/;
48
+ class WorkspaceManifestRevisionFence {
49
+ sequence = 0;
50
+ requestedRevision = null;
51
+ completedRevision = null;
52
+ begin(revision) {
53
+ if (!WORKSPACE_MANIFEST_REVISION_PATTERN.test(revision)) {
54
+ throw new Error("Workspace manifest revision must be a lowercase SHA-256 hash");
55
+ }
56
+ this.sequence += 1;
57
+ this.requestedRevision = revision;
58
+ this.completedRevision = null;
59
+ return { sequence: this.sequence, revision };
60
+ }
61
+ isCurrent(token) {
62
+ return token.sequence === this.sequence && token.revision === this.requestedRevision;
63
+ }
64
+ complete(token) {
65
+ if (!this.isCurrent(token)) return false;
66
+ this.completedRevision = token.revision;
67
+ return true;
68
+ }
69
+ readyRevision() {
70
+ return this.completedRevision === this.requestedRevision ? this.completedRevision : null;
71
+ }
72
+ }
73
+ function workspacePublicationTelemetry(input) {
74
+ return {
75
+ totalMs: Math.max(0, input.finishedAt - input.requestedAt),
76
+ queueMs: Math.max(0, input.prepareStartedAt - input.requestedAt),
77
+ prepareMs: Math.max(0, input.synchronizeStartedAt - input.prepareStartedAt),
78
+ synchronizeMs: Math.max(0, input.finishedAt - input.synchronizeStartedAt)
79
+ };
80
+ }
81
+ function workspacePublicationIncidentAction(requestId) {
82
+ return requestId ? "request_terminal_authority" : "defer_automatic";
83
+ }
84
+ class ExplicitWorkspacePublicationQueue {
85
+ scheduled;
86
+ queued = [];
87
+ schedule(publication, pendingRequestId) {
88
+ if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
89
+ return false;
90
+ }
91
+ if (pendingRequestId || this.scheduled) {
92
+ this.queued.push(publication);
93
+ return false;
94
+ }
95
+ this.scheduled = publication;
96
+ return true;
97
+ }
98
+ hasScheduled() {
99
+ return this.scheduled !== void 0;
100
+ }
101
+ consumeScheduled(requestId) {
102
+ if (this.scheduled?.requestId === requestId) this.scheduled = void 0;
103
+ }
104
+ enqueue(publication, pendingRequestId) {
105
+ if (pendingRequestId === publication.requestId || this.scheduled?.requestId === publication.requestId || this.queued.some((queued) => queued.requestId === publication.requestId)) {
106
+ return;
107
+ }
108
+ this.queued.push(publication);
109
+ }
110
+ next() {
111
+ return this.queued.shift();
112
+ }
113
+ }
114
+ const EMPTY_STATE = {
115
+ localHead: null,
116
+ desiredCanonicalHead: null,
117
+ dirtyGeneration: 0,
118
+ publishedGeneration: 0
119
+ };
120
+ function validHead(value) {
121
+ return value === null || typeof value === "string" && /^[0-9a-f]{40,64}$/.test(value);
122
+ }
123
+ function validGeneration(value) {
124
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
125
+ }
126
+ function readWorkspaceConvergenceState(statePath) {
127
+ try {
128
+ const parsed = JSON.parse(import_node_fs.default.readFileSync(statePath, "utf8"));
129
+ if (!validHead(parsed.localHead) || !validHead(parsed.desiredCanonicalHead) || !validGeneration(parsed.dirtyGeneration) || !validGeneration(parsed.publishedGeneration) || parsed.publishedGeneration > parsed.dirtyGeneration) {
130
+ return { ...EMPTY_STATE };
131
+ }
132
+ return {
133
+ localHead: parsed.localHead,
134
+ desiredCanonicalHead: parsed.desiredCanonicalHead,
135
+ dirtyGeneration: parsed.dirtyGeneration,
136
+ publishedGeneration: parsed.publishedGeneration
137
+ };
138
+ } catch {
139
+ return { ...EMPTY_STATE };
140
+ }
141
+ }
142
+ class WorkspaceConvergenceState {
143
+ constructor(statePath) {
144
+ this.statePath = statePath;
145
+ this.state = readWorkspaceConvergenceState(statePath);
146
+ this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
147
+ }
148
+ statePath;
149
+ state;
150
+ publicationState;
151
+ snapshot() {
152
+ return { ...this.state, publicationState: this.publicationState };
153
+ }
154
+ setLocalHead(localHead) {
155
+ if (!validHead(localHead)) throw new Error("Invalid local workspace head");
156
+ this.state.localHead = localHead;
157
+ this.persist();
158
+ }
159
+ observeCanonicalHead(canonicalHead) {
160
+ if (!validHead(canonicalHead)) throw new Error("Invalid canonical workspace head");
161
+ if (this.state.desiredCanonicalHead === canonicalHead) return false;
162
+ this.state.desiredCanonicalHead = canonicalHead;
163
+ this.persist();
164
+ return true;
165
+ }
166
+ markDirty() {
167
+ this.state.dirtyGeneration += 1;
168
+ if (this.publicationState === "idle") this.publicationState = "scheduled";
169
+ this.persist();
170
+ return this.state.dirtyGeneration;
171
+ }
172
+ schedule() {
173
+ if (this.publicationState === "idle") this.publicationState = "scheduled";
174
+ }
175
+ beginPreparing() {
176
+ if (this.publicationState === "preparing" || this.publicationState === "submitting") {
177
+ throw new Error("A workspace publication is already in flight");
178
+ }
179
+ this.publicationState = "preparing";
180
+ }
181
+ beginSubmitting() {
182
+ if (this.publicationState !== "preparing") throw new Error("Workspace publication authority was not prepared");
183
+ this.publicationState = "submitting";
184
+ }
185
+ defer() {
186
+ this.publicationState = "scheduled";
187
+ }
188
+ block() {
189
+ this.publicationState = "blocked";
190
+ }
191
+ releaseBlock() {
192
+ this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
193
+ }
194
+ observeIncidentState(blocked) {
195
+ if (this.publicationState === "preparing" || this.publicationState === "submitting") return;
196
+ if (blocked) this.block();
197
+ else this.releaseBlock();
198
+ }
199
+ resetTransientPublicationState() {
200
+ this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
201
+ }
202
+ complete(input) {
203
+ if (!validGeneration(input.generation) || input.generation > this.state.dirtyGeneration) {
204
+ throw new Error("Invalid completed workspace generation");
205
+ }
206
+ if (!validHead(input.canonicalHead)) throw new Error("Invalid completed canonical workspace head");
207
+ if (input.published) {
208
+ this.state.publishedGeneration = Math.max(this.state.publishedGeneration, input.generation);
209
+ this.state.localHead = input.canonicalHead;
210
+ this.state.desiredCanonicalHead = input.canonicalHead;
211
+ }
212
+ this.publicationState = this.state.dirtyGeneration > this.state.publishedGeneration ? "scheduled" : "idle";
213
+ this.persist();
214
+ }
215
+ persist() {
216
+ import_node_fs.default.mkdirSync(import_node_path.default.dirname(this.statePath), { recursive: true });
217
+ const temporaryPath = `${this.statePath}.${process.pid}.${crypto.randomUUID()}.tmp`;
218
+ import_node_fs.default.writeFileSync(temporaryPath, `${JSON.stringify(this.state)}
219
+ `, { mode: 384 });
220
+ import_node_fs.default.renameSync(temporaryPath, this.statePath);
221
+ }
222
+ }
223
+ const PROCESS_WORKSPACE_CONVERGENCE_STATES = /* @__PURE__ */ new Map();
224
+ function processWorkspaceConvergenceState(statePath) {
225
+ const key = import_node_path.default.resolve(statePath);
226
+ const existing = PROCESS_WORKSPACE_CONVERGENCE_STATES.get(key);
227
+ if (existing) return existing;
228
+ const created = new WorkspaceConvergenceState(key);
229
+ PROCESS_WORKSPACE_CONVERGENCE_STATES.set(key, created);
230
+ return created;
231
+ }
232
+ async function waitForWorkspacePublicationOnShutdown(input) {
233
+ input.forcePublication();
234
+ const deadline = Date.now() + (input.timeoutMs ?? 1e4);
235
+ const pollMs = input.pollMs ?? 50;
236
+ while (Date.now() < deadline) {
237
+ const snapshot = input.snapshot();
238
+ if (snapshot.publicationState === "blocked") return "blocked";
239
+ if (snapshot.publicationState === "idle" && snapshot.publishedGeneration >= snapshot.dirtyGeneration) return "settled";
240
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
241
+ }
242
+ return "timed_out";
243
+ }
244
+ // Annotate the CommonJS export names for ESM import in node:
245
+ 0 && (module.exports = {
246
+ ExplicitWorkspacePublicationQueue,
247
+ WORKSPACE_IDLE_SAFETY_SCAN_MS,
248
+ WORKSPACE_PUBLICATION_QUIET_MS,
249
+ WorkspaceConvergenceState,
250
+ WorkspaceManifestRevisionFence,
251
+ processWorkspaceConvergenceState,
252
+ readWorkspaceConvergenceState,
253
+ waitForWorkspacePublicationOnShutdown,
254
+ workspacePublicationIncidentAction,
255
+ workspacePublicationTelemetry
256
+ });
@@ -18,22 +18,51 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var workspace_incident_state_exports = {};
20
20
  __export(workspace_incident_state_exports, {
21
+ WorkspaceIncidentOrderingFence: () => WorkspaceIncidentOrderingFence,
21
22
  applyWorkspaceIncidentUpdate: () => applyWorkspaceIncidentUpdate,
22
23
  releasePendingWorkspaceHead: () => releasePendingWorkspaceHead
23
24
  });
24
25
  module.exports = __toCommonJS(workspace_incident_state_exports);
26
+ const DEFAULT_TERMINAL_INCIDENT_HISTORY_LIMIT = 32;
27
+ function isTerminalWorkspaceIncidentUpdate(update) {
28
+ return update.incidentId !== null && (update.status === "resolved" || update.status === "confirmed" || update.status === "reset");
29
+ }
30
+ class WorkspaceIncidentOrderingFence {
31
+ constructor(historyLimit = DEFAULT_TERMINAL_INCIDENT_HISTORY_LIMIT) {
32
+ this.historyLimit = historyLimit;
33
+ if (!Number.isSafeInteger(historyLimit) || historyLimit < 1) {
34
+ throw new Error("Workspace incident history limit must be a positive integer");
35
+ }
36
+ }
37
+ historyLimit;
38
+ terminalIncidentIds = /* @__PURE__ */ new Set();
39
+ terminalIncidentOrder = [];
40
+ observe(update) {
41
+ if (!isTerminalWorkspaceIncidentUpdate(update) || this.terminalIncidentIds.has(update.incidentId)) return;
42
+ this.terminalIncidentIds.add(update.incidentId);
43
+ this.terminalIncidentOrder.push(update.incidentId);
44
+ while (this.terminalIncidentOrder.length > this.historyLimit) {
45
+ const expired = this.terminalIncidentOrder.shift();
46
+ if (expired) this.terminalIncidentIds.delete(expired);
47
+ }
48
+ }
49
+ permitsBlockedResponse(incidentId) {
50
+ if (!incidentId) return false;
51
+ return !this.terminalIncidentIds.has(incidentId);
52
+ }
53
+ }
25
54
  function applyWorkspaceIncidentUpdate(currentIncidentId, update) {
26
55
  if (update.status === "remediating" || update.status === "waiting_for_worker") return update.incidentId;
27
56
  if (currentIncidentId && update.incidentId && update.incidentId !== currentIncidentId) return currentIncidentId;
28
57
  return null;
29
58
  }
30
59
  function releasePendingWorkspaceHead(previousIncidentId, currentIncidentId, terminalIncidentId) {
31
- if (!previousIncidentId || currentIncidentId) return { syncHead: null };
32
- if (terminalIncidentId === previousIncidentId) return { syncHead: "authoritative" };
33
- return { syncHead: null };
60
+ if (!previousIncidentId || currentIncidentId) return { fetchAuthoritativeHead: false };
61
+ return { fetchAuthoritativeHead: terminalIncidentId === previousIncidentId };
34
62
  }
35
63
  // Annotate the CommonJS export names for ESM import in node:
36
64
  0 && (module.exports = {
65
+ WorkspaceIncidentOrderingFence,
37
66
  applyWorkspaceIncidentUpdate,
38
67
  releasePendingWorkspaceHead
39
68
  });
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var workspace_manifest_admission_exports = {};
30
+ __export(workspace_manifest_admission_exports, {
31
+ inspectWorkspaceManifestFilesystem: () => inspectWorkspaceManifestFilesystem
32
+ });
33
+ module.exports = __toCommonJS(workspace_manifest_admission_exports);
34
+ var import_node_fs = __toESM(require("node:fs"), 1);
35
+ var import_node_path = __toESM(require("node:path"), 1);
36
+ var import_managed_paths = require("./managed-paths.cjs");
37
+ function hasNormalGitDirectory(checkoutPath) {
38
+ const gitPath = import_node_path.default.join(checkoutPath, ".git");
39
+ return import_node_fs.default.existsSync(gitPath) && import_node_fs.default.statSync(gitPath).isDirectory();
40
+ }
41
+ function inspectWorkspaceManifestFilesystem(input) {
42
+ const firstBootstrap = !hasNormalGitDirectory(input.workspaceShadowRoot);
43
+ const missingCheckouts = [];
44
+ const migratedProjectIds = [];
45
+ for (const project of input.projects) {
46
+ const projectRoot = (0, import_managed_paths.managedProjectRoot)(input.projectsRoot, project.checkoutPathSegments);
47
+ const legacyRoot = import_node_path.default.join(input.projectsRoot, (0, import_managed_paths.legacyProjectSlug)(project.projectPath, project.projectId));
48
+ if (import_node_fs.default.existsSync(legacyRoot)) migratedProjectIds.push(project.projectId);
49
+ for (const branchName of project.branches) {
50
+ if (!hasNormalGitDirectory(import_node_path.default.join(projectRoot, branchName))) {
51
+ missingCheckouts.push({ projectId: project.projectId, branchName });
52
+ }
53
+ }
54
+ }
55
+ return {
56
+ firstBootstrap,
57
+ missingCheckouts,
58
+ migratedProjectIds
59
+ };
60
+ }
61
+ // Annotate the CommonJS export names for ESM import in node:
62
+ 0 && (module.exports = {
63
+ inspectWorkspaceManifestFilesystem
64
+ });
@@ -32,11 +32,13 @@ __export(workspace_sync_exports, {
32
32
  WORKSPACE_BRANCH: () => WORKSPACE_BRANCH,
33
33
  WORKSPACE_INTENT_REF_PREFIX: () => WORKSPACE_INTENT_REF_PREFIX,
34
34
  WORKSPACE_NATIVE_PLANS_RELATIVE_PATH: () => WORKSPACE_NATIVE_PLANS_RELATIVE_PATH,
35
- WORKSPACE_PERIODIC_SCAN_INTERVAL_MS: () => WORKSPACE_PERIODIC_SCAN_INTERVAL_MS,
35
+ WORKSPACE_PUBLICATION_REF_PREFIX: () => WORKSPACE_PUBLICATION_REF_PREFIX,
36
36
  WorkspaceSyncSingleFlight: () => WorkspaceSyncSingleFlight,
37
37
  assertCanonicalCheckoutIndexMatchesWorktree: () => assertCanonicalCheckoutIndexMatchesWorktree,
38
38
  assertWorkspaceQuarantineRef: () => assertWorkspaceQuarantineRef,
39
39
  calculateWorkspaceDiffFingerprint: () => calculateWorkspaceDiffFingerprint,
40
+ calculateWorkspaceLocalDiffFingerprint: () => calculateWorkspaceLocalDiffFingerprint,
41
+ convergeWorkspaceHead: () => convergeWorkspaceHead,
40
42
  encodeWorkspaceBranch: () => encodeWorkspaceBranch,
41
43
  mirrorShadowWorkspaceToVisible: () => mirrorShadowWorkspaceToVisible,
42
44
  mirrorVisibleWorkspaceToShadow: () => mirrorVisibleWorkspaceToShadow,
@@ -54,8 +56,8 @@ var import_managed_paths = require("./managed-paths.cjs");
54
56
  var import_workspace_mutation_gate = require("./workspace-mutation-gate.cjs");
55
57
  const WORKSPACE_BRANCH = "main";
56
58
  const WORKSPACE_INTENT_REF_PREFIX = "refs/r5d/workspace-intents/";
59
+ const WORKSPACE_PUBLICATION_REF_PREFIX = "refs/r5d/workspace-publications/";
57
60
  const MAX_WORKSPACE_SYNC_DIFF_BYTES = 5 * 1024 * 1024;
58
- const WORKSPACE_PERIODIC_SCAN_INTERVAL_MS = 5e3;
59
61
  const MAX_REPORTED_WORKSPACE_PATHS = 2e3;
60
62
  const MAX_REPORTED_WORKSPACE_STATUS_BYTES = 256 * 1024;
61
63
  const MAX_MIRROR_COMPARISON_CACHE_ENTRIES = 2e5;
@@ -1754,9 +1756,10 @@ function commitMessage(input) {
1754
1756
  });
1755
1757
  }
1756
1758
  function assertWorkspaceQuarantineRef(quarantineRef) {
1757
- const suffix = quarantineRef.slice(WORKSPACE_INTENT_REF_PREFIX.length);
1758
- if (!quarantineRef.startsWith(WORKSPACE_INTENT_REF_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)) {
1759
- throw new Error(`Workspace candidate ref must be below ${WORKSPACE_INTENT_REF_PREFIX}`);
1759
+ const prefix = quarantineRef.startsWith(WORKSPACE_PUBLICATION_REF_PREFIX) ? WORKSPACE_PUBLICATION_REF_PREFIX : WORKSPACE_INTENT_REF_PREFIX;
1760
+ const suffix = quarantineRef.slice(prefix.length);
1761
+ 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)) {
1762
+ throw new Error(`Workspace candidate ref must be below ${WORKSPACE_PUBLICATION_REF_PREFIX} or ${WORKSPACE_INTENT_REF_PREFIX}`);
1760
1763
  }
1761
1764
  const result = Bun.spawnSync(["git", "check-ref-format", quarantineRef], {
1762
1765
  stdout: "pipe",
@@ -1876,6 +1879,36 @@ function preserveWorkspaceConflictCandidate(input, observed, options) {
1876
1879
  };
1877
1880
  }
1878
1881
  }
1882
+ function preserveLargeDiffCandidate(input, observed, error) {
1883
+ try {
1884
+ if (stagedPaths(input).length > 0) {
1885
+ runGit(input, input.shadowRoot, ["commit", "-m", commitMessage(input)], "commit blocked workspace candidate");
1886
+ }
1887
+ const candidateHead = revParse(input, "HEAD");
1888
+ if (!candidateHead) throw new Error("the blocked workspace candidate does not have a commit");
1889
+ assertUnscopedCanonicalCheckoutSubtreesMatchRemote(input, candidateHead);
1890
+ const upload = uploadWorkspaceCandidate(input, candidateHead);
1891
+ if (upload.exitCode !== 0) {
1892
+ throw new Error(upload.stderr || upload.stdout || "blocked workspace candidate upload failed");
1893
+ }
1894
+ return {
1895
+ ...observed,
1896
+ outcome: "large_diff_blocked",
1897
+ expectedHead: revParse(input, `origin/${WORKSPACE_BRANCH}`),
1898
+ candidateHead,
1899
+ quarantineRef: input.quarantineRef,
1900
+ error,
1901
+ gitStatus: gitStatus(input)
1902
+ };
1903
+ } catch (candidateError) {
1904
+ return {
1905
+ ...observed,
1906
+ outcome: "failed",
1907
+ error: `Workspace safety guard blocked publication but could not preserve a durable candidate: ${candidateError instanceof Error ? candidateError.message : String(candidateError)}`,
1908
+ gitStatus: gitStatus(input)
1909
+ };
1910
+ }
1911
+ }
1879
1912
  async function synchronizeWorkspace(rawInput) {
1880
1913
  let input = { ...rawInput, attemptId: rawInput.attemptId ?? crypto.randomUUID() };
1881
1914
  try {
@@ -1887,6 +1920,15 @@ async function synchronizeWorkspace(rawInput) {
1887
1920
  let hydrationPreimages = input.skipVisibleMirror ? hydrationPreimagesFromShadowRevision(input, shadowWasCreated ? null : revParse(input, "HEAD")) : /* @__PURE__ */ new Map();
1888
1921
  const remoteHeadAtStart = revParse(input, `origin/${WORKSPACE_BRANCH}`);
1889
1922
  const result = baseResult(input, remoteHeadAtStart);
1923
+ if (input.expectedCanonicalHead !== void 0 && remoteHeadAtStart !== input.expectedCanonicalHead) {
1924
+ return {
1925
+ ...result,
1926
+ outcome: "failed",
1927
+ expectedHead: input.expectedCanonicalHead,
1928
+ publishedHead: remoteHeadAtStart ?? void 0,
1929
+ error: `canonical_head_advanced: expected ${input.expectedCanonicalHead ?? "unborn"}, fetched ${remoteHeadAtStart ?? "unborn"}`
1930
+ };
1931
+ }
1890
1932
  const inboundConflictsAtStart = input.skipVisibleMirror && !isCanonicalRemediationSync && remoteHeadAtStart ? visibleHydrationConflictPaths(input, hydrationPreimages, `origin/${WORKSPACE_BRANCH}`) : [];
1891
1933
  if (input.resetToCanonical) {
1892
1934
  if (input.trigger.canonicalCheckoutOnly) {
@@ -1935,18 +1977,14 @@ async function synchronizeWorkspace(rawInput) {
1935
1977
  const destructiveReductions = destructiveCheckoutReductions(input, baseRevision);
1936
1978
  if (destructiveReductions.length > 0 && !input.confirmedLargeDiff) {
1937
1979
  const summary = destructiveReductions.map(({ root, trackedBefore, trackedAfter }) => `${root} (${trackedBefore} -> ${trackedAfter} tracked files)`).join(", ");
1938
- return {
1939
- ...observed,
1940
- outcome: "large_diff_blocked",
1941
- error: `Workspace safety guard blocked a destructive checkout reduction: ${summary}`
1942
- };
1980
+ return preserveLargeDiffCandidate(input, observed, `Workspace safety guard blocked a destructive checkout reduction: ${summary}`);
1943
1981
  }
1944
1982
  if (paths.length > 0 && diffSizeBytes > MAX_WORKSPACE_SYNC_DIFF_BYTES && !input.confirmedLargeDiff && !input.trigger.canonicalCheckoutOnly) {
1945
- return {
1946
- ...observed,
1947
- outcome: "large_diff_blocked",
1948
- error: `Workspace safety guard blocked a ${diffSizeBytes}-byte diff above the ${MAX_WORKSPACE_SYNC_DIFF_BYTES}-byte automatic publication limit.`
1949
- };
1983
+ return preserveLargeDiffCandidate(
1984
+ input,
1985
+ observed,
1986
+ `Workspace safety guard blocked a ${diffSizeBytes}-byte diff above the ${MAX_WORKSPACE_SYNC_DIFF_BYTES}-byte automatic publication limit.`
1987
+ );
1950
1988
  }
1951
1989
  if (stagedWorkingPaths.length > 0) {
1952
1990
  runGit(input, input.shadowRoot, ["commit", "-m", commitMessage(input)], "commit workspace changes");
@@ -2111,6 +2149,79 @@ async function synchronizeWorkspace(rawInput) {
2111
2149
  };
2112
2150
  }
2113
2151
  }
2152
+ async function convergeWorkspaceHead(rawInput, options) {
2153
+ const input = {
2154
+ ...rawInput,
2155
+ projects: workspaceProjectsForSync(rawInput.projects, rawInput.trigger)
2156
+ };
2157
+ if (input.trigger.canonicalCheckoutOnly) {
2158
+ throw new Error("Ordinary inbound convergence cannot target a canonical resolver checkout");
2159
+ }
2160
+ ensureShadowWorkspace(input);
2161
+ const fetchedLocalHead = revParse(input, "HEAD");
2162
+ const fetchedCanonicalHead = revParse(input, `origin/${WORKSPACE_BRANCH}`);
2163
+ if (!options.hydrateVisible) {
2164
+ return {
2165
+ localHead: fetchedLocalHead,
2166
+ canonicalHead: fetchedCanonicalHead,
2167
+ localChanges: false,
2168
+ hydrated: false,
2169
+ hydrationConflicts: []
2170
+ };
2171
+ }
2172
+ resetUncommittedShadowSnapshot(input);
2173
+ restoreUnscopedCanonicalCheckoutSubtrees(input);
2174
+ const localHead = fetchedLocalHead;
2175
+ const canonicalHead = fetchedCanonicalHead;
2176
+ const projection = mirrorVisibleWorkspaceToShadow(input);
2177
+ runGit(
2178
+ input,
2179
+ input.shadowRoot,
2180
+ ["add", "-A", "--", ".", ...projection.opaqueRoots.map((root) => `:(exclude,literal)${root}`)],
2181
+ "stage inbound workspace observation"
2182
+ );
2183
+ forceStageCanonicalCheckoutFiles(input, projection.entries, projection.opaqueRoots);
2184
+ const stagedTree = runGit(input, input.shadowRoot, ["write-tree"], "write inbound workspace observation tree");
2185
+ const headTree = localHead ? revParse(input, `${localHead}^{tree}`) : null;
2186
+ const localChanges = stagedTree !== headTree;
2187
+ if (!options.hydrateVisible || localChanges || !canonicalHead || localHead === canonicalHead) {
2188
+ resetUncommittedShadowSnapshot(input);
2189
+ return { localHead, canonicalHead, localChanges, hydrated: false, hydrationConflicts: [] };
2190
+ }
2191
+ const preimages = projection.visiblePreimages ?? hydrationPreimagesFromShadowRevision(input, localHead);
2192
+ const hydrationConflicts = localHead ? hydrationConflictPaths(input, preimages, localHead, canonicalHead) : [];
2193
+ if (hydrationConflicts.length > 0) {
2194
+ resetUncommittedShadowSnapshot(input);
2195
+ return { localHead, canonicalHead, localChanges: true, hydrated: false, hydrationConflicts };
2196
+ }
2197
+ runGit(input, input.shadowRoot, ["reset", "--hard", canonicalHead], "fast-forward workspace to available canonical head");
2198
+ runGit(input, input.shadowRoot, ["clean", "-fd"], "clean fast-forwarded workspace");
2199
+ mirrorShadowWorkspaceToVisible(input, projection.opaqueRoots, preimages);
2200
+ return { localHead: canonicalHead, canonicalHead, localChanges: false, hydrated: true, hydrationConflicts: [] };
2201
+ }
2202
+ function calculateWorkspaceLocalDiffFingerprint(rawInput) {
2203
+ const input = {
2204
+ ...rawInput,
2205
+ projects: workspaceProjectsForSync(rawInput.projects, rawInput.trigger)
2206
+ };
2207
+ if (!import_node_fs.default.existsSync(import_node_path.default.join(input.shadowRoot, ".git"))) {
2208
+ throw new Error("Cannot inspect local workspace changes before first bootstrap");
2209
+ }
2210
+ resetUncommittedShadowSnapshot(input);
2211
+ restoreUnscopedCanonicalCheckoutSubtrees(input);
2212
+ const projection = mirrorVisibleWorkspaceToShadow(input);
2213
+ runGit(
2214
+ input,
2215
+ input.shadowRoot,
2216
+ ["add", "-A", "--", ".", ...projection.opaqueRoots.map((root) => `:(exclude,literal)${root}`)],
2217
+ "stage local workspace fingerprint"
2218
+ );
2219
+ forceStageCanonicalCheckoutFiles(input, projection.entries, projection.opaqueRoots);
2220
+ const stagedTree = runGit(input, input.shadowRoot, ["write-tree"], "write local workspace fingerprint tree");
2221
+ const headTree = revParse(input, "HEAD^{tree}");
2222
+ resetUncommittedShadowSnapshot(input);
2223
+ return stagedTree === headTree ? (0, import_node_crypto.createHash)("sha256").update("").digest("hex") : (0, import_node_crypto.createHash)("sha256").update(stagedTree).digest("hex");
2224
+ }
2114
2225
  function calculateWorkspaceDiffFingerprint(rawInput) {
2115
2226
  const input = {
2116
2227
  ...rawInput,
@@ -2183,11 +2294,13 @@ class WorkspaceSyncSingleFlight {
2183
2294
  WORKSPACE_BRANCH,
2184
2295
  WORKSPACE_INTENT_REF_PREFIX,
2185
2296
  WORKSPACE_NATIVE_PLANS_RELATIVE_PATH,
2186
- WORKSPACE_PERIODIC_SCAN_INTERVAL_MS,
2297
+ WORKSPACE_PUBLICATION_REF_PREFIX,
2187
2298
  WorkspaceSyncSingleFlight,
2188
2299
  assertCanonicalCheckoutIndexMatchesWorktree,
2189
2300
  assertWorkspaceQuarantineRef,
2190
2301
  calculateWorkspaceDiffFingerprint,
2302
+ calculateWorkspaceLocalDiffFingerprint,
2303
+ convergeWorkspaceHead,
2191
2304
  encodeWorkspaceBranch,
2192
2305
  mirrorShadowWorkspaceToVisible,
2193
2306
  mirrorVisibleWorkspaceToShadow,