@ricsam/r5d-worker 0.0.161 → 0.0.163

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.
@@ -11,6 +11,7 @@ import {
11
11
  WorkspaceConfig,
12
12
  WorkspaceError
13
13
  } from "./contracts.mjs";
14
+ import { OuterRepository, OuterSnapshotRefusal, OUTER_BRANCH, OUTER_CONFLICT_CODE } from "./outer.mjs";
14
15
  import { SessionArtifactStore, SessionArtifactChunk, RESERVED_ARTIFACT_ENV } from "./artifacts.mjs";
15
16
  import { WorkspaceFileWrite, WorkspaceFileWriteLookup } from "./file-write.mjs";
16
17
  import { WorkspaceStorageClient } from "./storage-client.mjs";
@@ -18,15 +19,19 @@ import {
18
19
  durableJson,
19
20
  ensureAuthorityGitRepositoryLayout,
20
21
  git,
22
+ gitResult,
21
23
  materializeTree,
22
24
  noSymlinkAncestors,
25
+ PLATFORM_COMMIT_EMAIL,
23
26
  privateRoot,
27
+ PROJECT_COMMIT_IDENTITY,
24
28
  readHostRegular,
25
29
  readRegular,
26
30
  selectedTree,
27
31
  sha256,
28
32
  snapshotTree,
29
- sourceBytes
33
+ sourceBytes,
34
+ WORKBENCH_CONFLICT_CODES
30
35
  } from "./files.mjs";
31
36
  const GITHUB_CREDENTIAL_HELPER = '!f() { if [ "$1" = get ] && [ -n "$R5D_GIT_CREDENTIAL" ]; then git credential-store --file="$R5D_GIT_CREDENTIAL" get; else return 0; fi; }; f';
32
37
  class WorkspaceAuthority {
@@ -44,6 +49,7 @@ class WorkspaceAuthority {
44
49
  closeTask;
45
50
  actions = /* @__PURE__ */ new Set();
46
51
  repositoryInitializations = /* @__PURE__ */ new Map();
52
+ outerRepository;
47
53
  pending = 0;
48
54
  expectedCwd(config) {
49
55
  const workspaceRoot = this.config.workspaceRoot ?? this.config.root;
@@ -226,7 +232,10 @@ class WorkspaceAuthority {
226
232
  hydrations = /* @__PURE__ */ new Map();
227
233
  async ensureHydrated(identity) {
228
234
  const b = await this.bench(identity);
229
- if (b.config.rootProfile === "account") return;
235
+ if (b.config.rootProfile === "account") {
236
+ if (this.outerEnabled()) await this.synchronizeOuter(b.config.userId, { bootstrapOnly: true });
237
+ return;
238
+ }
230
239
  if (b.state.initialized) return;
231
240
  let task = this.hydrations.get(b.config.id);
232
241
  if (!task) {
@@ -311,10 +320,12 @@ class WorkspaceAuthority {
311
320
  async inspectGit(identity, command) {
312
321
  const b = await this.bench(identity);
313
322
  return this.serial(b, async () => {
314
- if (!b.state.initialized || !b.state.head) throw new WorkspaceError("not_initialized", "Initialize workspace first");
315
- const head = b.state.head;
323
+ if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Initialize workspace first");
324
+ const innerHead = this.outerEnabled(b) && this.linkedWorkbench(b) ? await this.innerHead(b) : void 0;
325
+ const head = innerHead === void 0 ? b.state.head : innerHead ?? (await git(b.repo, ["hash-object", "-t", "tree", "--stdin"], "")).toString().trim();
326
+ if (!head) throw new WorkspaceError("not_initialized", "Initialize workspace first");
316
327
  const base = command.base ? GitOid.parse(command.base) : head;
317
- const treeHash = await snapshotTree(b.repo, b.config.cwd, head);
328
+ const treeHash = await snapshotTree(b.repo, b.config.cwd, innerHead === void 0 ? head : innerHead);
318
329
  if (command.method === "history") {
319
330
  const history = (await git(b.repo, ["log", "-100", "--format=%H%x00%P%x00%s%x00%an%x00%ae%x00%aI%x00%cI", head])).toString();
320
331
  return { head, treeHash, commits: history.trimEnd().split("\n").filter(Boolean).map((line) => {
@@ -362,10 +373,12 @@ class WorkspaceAuthority {
362
373
  if (owner.lockId !== this.lockId) throw new WorkspaceError("authority_lost", "Workspace authority lock changed");
363
374
  }
364
375
  serial(b, fn, admitted = false) {
376
+ return this.serialKey(this.linkedWorkbench(b) ? b.repo : b.config.id, fn, admitted);
377
+ }
378
+ serialKey(queueKey, fn, admitted = false) {
365
379
  if (this.closing && !admitted) return Promise.reject(new WorkspaceError("authority_closed", "Workspace authority is closing"));
366
380
  if (this.pending >= 32) return Promise.reject(new WorkspaceError("busy", "Workspace request budget reached"));
367
381
  this.pending++;
368
- const queueKey = this.linkedWorkbench(b) ? b.repo : b.config.id;
369
382
  const task = (this.queues.get(queueKey) ?? Promise.resolve()).catch(() => {
370
383
  }).then(async () => {
371
384
  await this.owned(admitted);
@@ -417,6 +430,13 @@ class WorkspaceAuthority {
417
430
  async assertAvailable(b, allowBlocked = false) {
418
431
  if (b.state.blocked && !allowBlocked) throw new WorkspaceError(b.state.blocked.code, b.state.blocked.message);
419
432
  }
433
+ /** Whether any run on this physical workbench is still live, across every
434
+ * session sharing it. An in-progress Git operation marker belongs to such a
435
+ * run, so publication defers to it instead of electing an incident over it. */
436
+ async workbenchHasLiveRun(identity) {
437
+ const b = await this.bench(identity);
438
+ return Object.values(b.state.runs).some((run) => !["completed", "cancelled", "rejected_capacity"].includes(run.state));
439
+ }
420
440
  async status(identity) {
421
441
  const b = await this.bench(identity);
422
442
  return this.serial(b, async () => {
@@ -434,7 +454,14 @@ class WorkspaceAuthority {
434
454
  state.runs = Object.fromEntries(
435
455
  Object.entries(state.runs).filter(([, run]) => (run.sessionId ?? b.config.sessionId) === identity.sessionId)
436
456
  );
437
- return { workbench: { ...b.config, sessionId: identity.sessionId }, ...state, files };
457
+ let outer;
458
+ if (b.config.rootProfile === "account" && this.outerEnabled()) {
459
+ outer = structuredClone((await this.outer(b.config.userId)).state);
460
+ state.initialized = outer.initialized;
461
+ state.head = outer.head;
462
+ state.blocked = outer.blocked;
463
+ }
464
+ return { workbench: { ...b.config, sessionId: identity.sessionId }, ...state, files, ...outer ? { outer } : {} };
438
465
  });
439
466
  }
440
467
  async cleanRefreshBase(b, expectedBase) {
@@ -468,7 +495,18 @@ class WorkspaceAuthority {
468
495
  * clean workbench refresh; process/PTY liveness never gates synchronization. */
469
496
  async hydrate(identity, expectedBase) {
470
497
  const b = await this.bench(identity);
471
- if (b.config.rootProfile === "account") return { head: "", unchanged: true };
498
+ if (b.config.rootProfile === "account") {
499
+ if (!this.outerEnabled()) return { head: "", unchanged: true };
500
+ return this.synchronizeOuter(b.config.userId, expectedBase === void 0 ? { bootstrapOnly: true } : { requireHead: GitOid.parse(expectedBase) });
501
+ }
502
+ if (this.outerEnabled(b)) {
503
+ if (!b.state.initialized) {
504
+ await this.synchronizeOuter(b.config.userId, { bootstrapOnly: true });
505
+ await this.serial(b, () => this.hydrateLinkedIdle(b, identity));
506
+ }
507
+ if (expectedBase !== void 0) return this.synchronizeOuter(b.config.userId, { requireHead: GitOid.parse(expectedBase) });
508
+ return { head: b.state.head ?? "" };
509
+ }
472
510
  return this.serial(b, () => this.hydrateIdle(b, identity, expectedBase));
473
511
  }
474
512
  async hydrateIdle(b, identity, expectedBase) {
@@ -524,27 +562,7 @@ class WorkspaceAuthority {
524
562
  message: "Source synchronization interrupted; preserve workbench and inspect staged tree/retained originals before maintenance"
525
563
  };
526
564
  await this.save(b);
527
- const chunks = [];
528
- let offset = 0, snapshot = null, size = -1, hash = "";
529
- do {
530
- const chunk = await storage.read({
531
- method: "repository.bundle",
532
- repositoryId: b.config.repositoryId,
533
- snapshot,
534
- offset,
535
- limit: STORAGE_LIMITS.chunkBytes
536
- });
537
- const bytes = Buffer.from(chunk.data, "base64");
538
- if (chunk.data !== bytes.toString("base64") || bytes.length > STORAGE_LIMITS.chunkBytes || chunk.offset !== offset || chunk.nextOffset !== offset + bytes.length || !bytes.length || chunk.size > STORAGE_LIMITS.blobBytes || chunk.nextOffset > chunk.size || snapshot && (snapshot !== chunk.snapshot || size !== chunk.size || hash !== chunk.sha256))
539
- throw new WorkspaceError("invalid_bundle", "Chunk identity/size/offset changed; no checkout performed");
540
- snapshot = chunk.snapshot;
541
- size = chunk.size;
542
- hash = chunk.sha256;
543
- offset = chunk.nextOffset;
544
- chunks.push(bytes);
545
- } while (offset < size);
546
- const bundle = Buffer.concat(chunks);
547
- if (sha256(bundle) !== hash) throw new WorkspaceError("invalid_bundle", "Bundle SHA256 mismatch");
565
+ const bundle = await this.downloadBundle(storage, b.config.repositoryId);
548
566
  const file = path.join(b.directory, `${randomUUID()}.bundle`);
549
567
  await fs.writeFile(file, bundle, { mode: 384, flag: "wx" });
550
568
  await git(b.repo, ["bundle", "unbundle", file]);
@@ -768,9 +786,11 @@ class WorkspaceAuthority {
768
786
  b.state.initialized = true;
769
787
  b.state.blocked = null;
770
788
  await this.save(b);
771
- const result = await this.publishIdle(b, identity);
789
+ const result = await this.publishIdle(b, identity, this.linkedWorkbench(b) ? "Initialize project" : void 0, false, this.linkedWorkbench(b));
772
790
  if (this.linkedWorkbench(b)) {
773
791
  await fs.unlink(path.join(b.config.cwd, "README.md"));
792
+ b.state.mirroredHead = result.head;
793
+ await this.save(b);
774
794
  }
775
795
  await this.installGitPolicy(b, result.head);
776
796
  return result;
@@ -796,22 +816,7 @@ class WorkspaceAuthority {
796
816
  await git(b.config.cwd, ["reset", "--mixed", visibleHead]);
797
817
  }
798
818
  }
799
- const origin = this.githubOrigin(b);
800
- await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.url", origin]);
801
- await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"]);
802
- const localConfig = (await readRegular(path.join(b.repo, "config"), 128 * 1024)).toString("utf8");
803
- if (/^\[remote "canonical"\]\s*$/m.test(localConfig))
804
- await git(b.repo, ["config", "--local", "--remove-section", "remote.canonical"]);
805
- await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.remote`, "origin"]);
806
- await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.merge`, `refs/heads/${b.config.branch}`]);
807
- if (remoteTrackingHead)
808
- await git(b.repo, ["update-ref", `refs/remotes/origin/${b.config.branch}`, remoteTrackingHead]);
809
- await git(b.repo, ["config", "--local", "--replace-all", "push.default", "upstream"]);
810
- await git(b.repo, ["config", "--local", "--replace-all", "credential.helper", ""]);
811
- await git(b.repo, ["config", "--local", "--add", "credential.helper", GITHUB_CREDENTIAL_HELPER]);
812
- await git(b.repo, ["config", "--local", "--replace-all", "credential.useHttpPath", "false"]);
813
- await git(b.repo, ["config", "protocol.allow", "never"]);
814
- await git(b.repo, ["config", "protocol.https.allow", "always"]);
819
+ await this.configureLinkedRemote(b, remoteTrackingHead);
815
820
  return;
816
821
  }
817
822
  const destination = path.join(b.config.cwd, ".git");
@@ -840,6 +845,28 @@ class WorkspaceAuthority {
840
845
  await fs.writeFile(ref, `${head}
841
846
  `, { mode: 384 });
842
847
  }
848
+ /** This repository is also the common Git directory for the visible project
849
+ * worktrees. Keep their ordinary Git topology pointed at GitHub; mirroring is
850
+ * performed by WorkspaceAuthority directly and must never be exposed as the
851
+ * checkout's origin. */
852
+ async configureLinkedRemote(b, remoteTrackingHead = b.config.baseCommitHash) {
853
+ const origin = this.githubOrigin(b);
854
+ await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.url", origin]);
855
+ await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"]);
856
+ const localConfig = (await readRegular(path.join(b.repo, "config"), 128 * 1024)).toString("utf8");
857
+ if (/^\[remote "canonical"\]\s*$/m.test(localConfig))
858
+ await git(b.repo, ["config", "--local", "--remove-section", "remote.canonical"]);
859
+ await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.remote`, "origin"]);
860
+ await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.merge`, `refs/heads/${b.config.branch}`]);
861
+ if (remoteTrackingHead)
862
+ await git(b.repo, ["update-ref", `refs/remotes/origin/${b.config.branch}`, remoteTrackingHead]);
863
+ await git(b.repo, ["config", "--local", "--replace-all", "push.default", "upstream"]);
864
+ await git(b.repo, ["config", "--local", "--replace-all", "credential.helper", ""]);
865
+ await git(b.repo, ["config", "--local", "--add", "credential.helper", GITHUB_CREDENTIAL_HELPER]);
866
+ await git(b.repo, ["config", "--local", "--replace-all", "credential.useHttpPath", "false"]);
867
+ await git(b.repo, ["config", "protocol.allow", "never"]);
868
+ await git(b.repo, ["config", "protocol.https.allow", "always"]);
869
+ }
843
870
  /** Scoped receipt lookup never repeats a file effect; completion can clear its own crash marker. */
844
871
  async fileWriteResult(identity, input) {
845
872
  WorkspaceFileWriteLookup.parse({ method: "fileWriteResult", ...input });
@@ -870,7 +897,7 @@ class WorkspaceAuthority {
870
897
  let mode = 420;
871
898
  let retainedBlock = null;
872
899
  const check = async () => {
873
- if (b.state.blocked && !(allowBlockedConflict && (b.state.blocked.code === "conflict" || b.state.blocked.code === "workbench_conflict")))
900
+ if (b.state.blocked && !(allowBlockedConflict && WORKBENCH_CONFLICT_CODES.has(b.state.blocked.code)))
874
901
  throw new WorkspaceError(b.state.blocked.code, b.state.blocked.message);
875
902
  retainedBlock = b.state.blocked;
876
903
  if (!b.state.initialized) throw new WorkspaceError("uninitialized", "Hydrate this workspace before writing files");
@@ -1048,10 +1075,7 @@ class WorkspaceAuthority {
1048
1075
  const bytes = await readRegular(file, STORAGE_LIMITS.blobBytes), blobId = operationId;
1049
1076
  b.state.blocked = { code: "publication_unknown", operationId, commit: head, message: "Inspect the original import publication receipt" };
1050
1077
  await this.save(b);
1051
- for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1052
- const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1053
- await storage.mutate({ method: "blob.append", operationId: `${operationId}-chunk-${offset}`, blobId, kind: "blob", offset, data: bytes.subarray(offset, end).toString("base64"), seal: end === bytes.length });
1054
- }
1078
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1055
1079
  const result = await storage.mutate({ method: "repository.publish", operationId, repositoryId: b.config.repositoryId, branch: b.config.branch, expectedHead: null, commit: head, bundleId: blobId });
1056
1080
  if (result.head !== head) throw new WorkspaceError("invalid_receipt", "Import receipt does not match selected commit");
1057
1081
  if (this.linkedWorkbench(b)) await fs.rm(staged, { recursive: true });
@@ -1060,6 +1084,7 @@ class WorkspaceAuthority {
1060
1084
  b.state.initialized = true;
1061
1085
  b.state.head = head;
1062
1086
  b.state.blocked = null;
1087
+ b.state.mirroredHead = head;
1063
1088
  await this.save(b);
1064
1089
  return { head, workspaceHead: head };
1065
1090
  }
@@ -1067,6 +1092,10 @@ class WorkspaceAuthority {
1067
1092
  const b = await this.bench(identity);
1068
1093
  if (!input.message.trim() || input.message.length > 1e4) throw new WorkspaceError("invalid_input", "Commit message is required");
1069
1094
  return this.serial(b, () => this.productAction(b, input.id, { method: "commit", expectedHead: input.expectedHead, message: input.message }, async () => {
1095
+ if (this.outerEnabled(b)) {
1096
+ const result2 = await this.commitInnerIdle(b, identity, input.message);
1097
+ return { ...result2, treeHash: (await git(b.repo, ["rev-parse", `${result2.head}^{tree}`])).toString().trim() };
1098
+ }
1070
1099
  const result = await this.publishIdle(b, identity, input.message);
1071
1100
  if (this.linkedWorkbench(b)) {
1072
1101
  return { ...result, treeHash: (await git(b.repo, ["rev-parse", `${result.head}^{tree}`])).toString().trim() };
@@ -1080,22 +1109,24 @@ class WorkspaceAuthority {
1080
1109
  return { ...result, treeHash: (await git(b.repo, ["rev-parse", `${result.head}^{tree}`])).toString().trim() };
1081
1110
  }, async () => {
1082
1111
  await this.assertAvailable(b);
1083
- if (input.expectedHead !== void 0 && input.expectedHead !== b.state.head) throw new WorkspaceError("conflict", "Workbench head changed");
1112
+ if (input.expectedHead !== void 0 && !await this.headMatches(b, input.expectedHead)) throw new WorkspaceError("conflict", "Workbench head changed");
1084
1113
  }));
1085
1114
  }
1086
1115
  async push(identity, input) {
1087
1116
  const b = await this.bench(identity);
1088
1117
  this.validateGithubRemote(input.remote);
1089
1118
  return this.serial(b, () => this.productAction(b, input.id, { method: "push", expectedHead: input.expectedHead, url: input.remote.url, branch: input.remote.branch, expectedRemoteHead: input.remote.expectedHead }, async () => {
1119
+ const head = this.outerEnabled(b) ? await this.innerHead(b) : b.state.head;
1120
+ if (!head) throw new WorkspaceError("conflict", "The checkout has no commit to push");
1090
1121
  if (input.remote.expectedHead) {
1091
1122
  GitOid.parse(input.remote.expectedHead);
1092
- await git(b.repo, ["merge-base", "--is-ancestor", input.remote.expectedHead, b.state.head]);
1123
+ await git(b.repo, ["merge-base", "--is-ancestor", input.remote.expectedHead, head]);
1093
1124
  }
1094
- await git(b.repo, ["-c", "protocol.https.allow=always", "push", "--porcelain", ...input.remote.expectedHead !== void 0 ? [`--force-with-lease=refs/heads/${input.remote.branch}:${input.remote.expectedHead ?? ""}`] : [], "--", input.remote.url, `${b.state.head}:refs/heads/${input.remote.branch}`], void 0, void 0, { token: input.remote.token });
1095
- return { head: b.state.head, pushed: true };
1125
+ await git(b.repo, ["-c", "protocol.https.allow=always", "push", "--porcelain", ...input.remote.expectedHead !== void 0 ? [`--force-with-lease=refs/heads/${input.remote.branch}:${input.remote.expectedHead ?? ""}`] : [], "--", input.remote.url, `${head}:refs/heads/${input.remote.branch}`], void 0, void 0, { token: input.remote.token });
1126
+ return { head, pushed: true };
1096
1127
  }, async () => {
1097
1128
  await this.assertAvailable(b);
1098
- if (!b.state.head || input.expectedHead !== void 0 && input.expectedHead !== b.state.head) throw new WorkspaceError("conflict", "Workbench head changed");
1129
+ if (input.expectedHead !== void 0 && !await this.headMatches(b, input.expectedHead)) throw new WorkspaceError("conflict", "Workbench head changed");
1099
1130
  }));
1100
1131
  }
1101
1132
  async archiveBranch(identity, input) {
@@ -1128,8 +1159,11 @@ class WorkspaceAuthority {
1128
1159
  const receipt = await storage.read({ method: "operation.get", lookupId: b.state.blocked.operationId });
1129
1160
  if (receipt.state !== "completed" || b.state.blocked.commit && receipt.result?.head !== b.state.blocked.commit) throw new WorkspaceError("publication_unknown", "Reconcile the original publication before resetting");
1130
1161
  }
1131
- const canonical = await storage.read({ method: "repository.get", repositoryId: b.config.repositoryId, branch: b.config.branch });
1132
- if (!canonical.head) throw new WorkspaceError("empty_repository", "No canonical source exists to restore");
1162
+ const canonical = await storage.read({ method: "repository.get", repositoryId: b.config.repositoryId, branch: b.config.branch }).catch((error) => {
1163
+ if (this.outerEnabled(b) && error instanceof WorkspaceError && error.code === "not_found") return { head: null };
1164
+ throw error;
1165
+ });
1166
+ if (!canonical.head && !this.outerEnabled(b)) throw new WorkspaceError("empty_repository", "No canonical source exists to restore");
1133
1167
  const retained = path.join(b.directory, `reset-retained-${randomUUID()}`);
1134
1168
  await fs.mkdir(retained, { mode: 448 });
1135
1169
  await durableJson(path.join(retained, "recovery.json"), { workbench: b.config, previousState: b.state, resetId: input.id, targetHead: canonical.head });
@@ -1145,21 +1179,443 @@ class WorkspaceAuthority {
1145
1179
  b.state.initialized = false;
1146
1180
  b.state.head = null;
1147
1181
  b.state.blocked = null;
1182
+ b.state.mirroredHead = null;
1148
1183
  await this.save(b);
1149
- const result = await this.hydrateIdle(b, identity);
1184
+ const result = this.outerEnabled(b) ? await this.hydrateLinkedIdle(b, identity) : await this.hydrateIdle(b, identity);
1150
1185
  return { ...result, reset: true, retained: true };
1151
1186
  }));
1152
1187
  }
1188
+ // ---- Outer repository ---------------------------------------------------
1189
+ outerEnabled(b) {
1190
+ return !!this.options.accountStorage && (!b || b.config.rootProfile === "account" || this.linkedWorkbench(b));
1191
+ }
1192
+ outerStateFile() {
1193
+ return path.join(this.config.root, "state", "outer.json");
1194
+ }
1195
+ async outer(userId) {
1196
+ if (!this.options.accountStorage) throw new WorkspaceError("outer_unavailable", "This authority has no account storage");
1197
+ const workTree = this.config.workspaceRoot;
1198
+ if (!workTree) throw new WorkspaceError("invalid_config", "The outer repository requires a workspace root");
1199
+ if (!this.outerRepository)
1200
+ this.outerRepository = (async () => {
1201
+ const repo = await OuterRepository.open(path.join(this.config.root, "outer.git"), workTree);
1202
+ const stored = await readRegular(this.outerStateFile(), 1024 * 1024).catch((error) => {
1203
+ if (error.code === "ENOENT") return null;
1204
+ throw error;
1205
+ });
1206
+ const state = stored ? JSON.parse(stored.toString("utf8")) : { userId, initialized: false, publishedHead: null, head: null, blocked: null, conflict: null };
1207
+ if (typeof state.initialized !== "boolean" || !(state.head === null || GitOid.safeParse(state.head).success))
1208
+ throw new WorkspaceError("invalid_state", "Invalid durable outer repository state; maintenance required");
1209
+ if (!stored) await durableJson(this.outerStateFile(), state);
1210
+ return { repo, state };
1211
+ })();
1212
+ const outer = await this.outerRepository.catch((error) => {
1213
+ this.outerRepository = void 0;
1214
+ throw error;
1215
+ });
1216
+ if (outer.state.userId !== userId) throw new WorkspaceError("wrong_binding", "The outer repository belongs to another account");
1217
+ return outer;
1218
+ }
1219
+ saveOuter(state) {
1220
+ return durableJson(this.outerStateFile(), state);
1221
+ }
1222
+ async outerStatus(userId) {
1223
+ return structuredClone((await this.outer(userId)).state);
1224
+ }
1225
+ accountRepositoryId(userId) {
1226
+ return `user-workspace-${sha256(userId).slice(0, 40)}`;
1227
+ }
1228
+ provisionId(repositoryId) {
1229
+ return `provision-${sha256(repositoryId).slice(0, 48)}`;
1230
+ }
1231
+ async hasCommit(repo, commit) {
1232
+ return (await gitResult(repo, ["cat-file", "-e", `${GitOid.parse(commit)}^{commit}`])).code === 0;
1233
+ }
1234
+ async innerHead(b) {
1235
+ const { code, stdout } = await gitResult(b.config.cwd, ["rev-parse", "--verify", "--quiet", "HEAD"]);
1236
+ if (code === 1) return null;
1237
+ if (code !== 0) throw new WorkspaceError("unsafe_git", "Project checkout HEAD is unreadable");
1238
+ return GitOid.parse(stdout.toString("utf8").trim());
1239
+ }
1240
+ async headMatches(b, expected) {
1241
+ if (!this.outerEnabled(b)) return expected === b.state.head;
1242
+ return expected === b.state.mirroredHead || expected === await this.innerHead(b);
1243
+ }
1244
+ async innerTracked(b) {
1245
+ const head = await this.innerHead(b);
1246
+ if (!head) return /* @__PURE__ */ new Set();
1247
+ const listing = await git(b.repo, ["ls-tree", "-r", "--name-only", "-z", head]);
1248
+ return new Set(listing.toString("utf8").split("\0").filter(Boolean));
1249
+ }
1250
+ /** Platform snapshot commits from the per-project model sit on top of the
1251
+ * GitHub tip. Hydration peels them so a checkout's history is its own. */
1252
+ async platformSnapshot(repo, commit) {
1253
+ const header = (await git(repo, ["cat-file", "commit", commit])).toString("utf8").split("\n\n")[0] ?? "";
1254
+ return /^committer .*<workspace@invalid>/m.test(header.replace(PLATFORM_COMMIT_EMAIL, "workspace@invalid"));
1255
+ }
1256
+ async firstParent(repo, commit) {
1257
+ const parents = (await git(repo, ["rev-list", "--parents", "-n", "1", commit])).toString("utf8").trim().split(/\s+/).slice(1);
1258
+ return parents[0] ? GitOid.parse(parents[0]) : null;
1259
+ }
1260
+ /** Every initialized project checkout beneath the workspace root, for the
1261
+ * outer walk and the measure. */
1262
+ async innerCheckouts(userId) {
1263
+ const workTree = this.config.workspaceRoot;
1264
+ const result = [];
1265
+ for (const b of this.benches.values()) {
1266
+ if (b.config.userId !== userId || !this.linkedWorkbench(b) || !b.state.initialized || b.state.blocked?.code === "archived") continue;
1267
+ const relative = path.relative(workTree, b.config.cwd);
1268
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) continue;
1269
+ if (!await fs.lstat(b.config.cwd).then((stat) => stat.isDirectory(), () => false)) continue;
1270
+ result.push({ bench: b, root: relative.split(path.sep).join("/"), tracked: () => this.innerTracked(b) });
1271
+ }
1272
+ return result;
1273
+ }
1274
+ /** The mirror's head for a branch, or null when it has none. Only a caller
1275
+ * that owns the repository's existence provisions it: a project repository
1276
+ * is provisioned by its seed or import under that action's own identity. */
1277
+ async remoteHead(storage, repositoryId, branch, provision = false) {
1278
+ try {
1279
+ return (await storage.read({ method: "repository.get", repositoryId, branch })).head;
1280
+ } catch (error) {
1281
+ if (!(error instanceof WorkspaceError) || error.code !== "not_found") throw error;
1282
+ if (provision) await storage.mutate({ method: "repository.provision", operationId: this.provisionId(repositoryId), repositoryId });
1283
+ return null;
1284
+ }
1285
+ }
1286
+ async downloadBundle(storage, repositoryId) {
1287
+ const chunks = [];
1288
+ let offset = 0, snapshot = null, size = -1, hash = "";
1289
+ do {
1290
+ const chunk = await storage.read({
1291
+ method: "repository.bundle",
1292
+ repositoryId,
1293
+ snapshot,
1294
+ offset,
1295
+ limit: STORAGE_LIMITS.chunkBytes
1296
+ });
1297
+ const bytes = Buffer.from(chunk.data, "base64");
1298
+ if (chunk.data !== bytes.toString("base64") || bytes.length > STORAGE_LIMITS.chunkBytes || chunk.offset !== offset || chunk.nextOffset !== offset + bytes.length || !bytes.length || chunk.size > STORAGE_LIMITS.blobBytes || chunk.nextOffset > chunk.size || snapshot && (snapshot !== chunk.snapshot || size !== chunk.size || hash !== chunk.sha256))
1299
+ throw new WorkspaceError("invalid_bundle", "Chunk identity/size/offset changed; no checkout performed");
1300
+ snapshot = chunk.snapshot;
1301
+ size = chunk.size;
1302
+ hash = chunk.sha256;
1303
+ offset = chunk.nextOffset;
1304
+ chunks.push(bytes);
1305
+ } while (offset < size);
1306
+ const bundle = Buffer.concat(chunks);
1307
+ if (sha256(bundle) !== hash) throw new WorkspaceError("invalid_bundle", "Bundle SHA256 mismatch");
1308
+ return bundle;
1309
+ }
1310
+ async uploadBundle(storage, bytes, blobId, operationId) {
1311
+ for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1312
+ const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1313
+ await storage.mutate({
1314
+ method: "blob.append",
1315
+ operationId: `${operationId}-chunk-${offset}`,
1316
+ blobId,
1317
+ kind: "blob",
1318
+ offset,
1319
+ data: bytes.subarray(offset, end).toString("base64"),
1320
+ seal: end === bytes.length
1321
+ });
1322
+ }
1323
+ }
1324
+ async unbundleInto(b, bytes) {
1325
+ const file = path.join(b.directory, `${randomUUID()}.bundle`);
1326
+ await fs.writeFile(file, bytes, { mode: 384, flag: "wx" });
1327
+ try {
1328
+ await git(b.repo, ["bundle", "unbundle", file]);
1329
+ } finally {
1330
+ await fs.rm(file, { force: true });
1331
+ }
1332
+ }
1333
+ async forcePublishSupported(storage) {
1334
+ const hello = await storage.read({ method: "hello" });
1335
+ return hello.capabilities?.includes("storage-force-publish-v1") === true;
1336
+ }
1337
+ /** One synchronization cycle of the outer repository: snapshot the workspace,
1338
+ * integrate what the mirror gained, publish what changed. Serialized on its
1339
+ * own queue; project checkouts stay ordinary concurrent writers whose later
1340
+ * edits the next cycle observes. */
1341
+ async synchronizeOuter(userId, options = {}) {
1342
+ return this.serialKey("outer", () => this.synchronizeOuterIdle(userId, options));
1343
+ }
1344
+ async synchronizeOuterIdle(userId, options) {
1345
+ await this.owned();
1346
+ const { repo, state } = await this.outer(userId);
1347
+ const storage = await this.options.accountStorage(userId);
1348
+ const repositoryId = this.accountRepositoryId(userId);
1349
+ if (state.blocked?.code === "publication_unknown") {
1350
+ const receipt = await storage.read({ method: "operation.get", lookupId: state.blocked.operationId });
1351
+ if (receipt.state !== "completed" || receipt.result?.head !== state.blocked.commit)
1352
+ throw new WorkspaceError("publication_unknown", "Original workspace publication not proven completed; preserve state for operator review");
1353
+ state.publishedHead = state.blocked.commit;
1354
+ state.head = state.blocked.commit;
1355
+ state.blocked = null;
1356
+ await this.saveOuter(state);
1357
+ }
1358
+ if (!state.initialized) {
1359
+ const remote2 = await this.remoteHead(storage, repositoryId, OUTER_BRANCH, true);
1360
+ if (remote2) {
1361
+ if (!await repo.has(remote2)) await repo.unbundle(await this.downloadBundle(storage, repositoryId));
1362
+ if (!await repo.isLegacyBootstrap(remote2)) await repo.checkout(remote2);
1363
+ await repo.setHead(remote2);
1364
+ }
1365
+ state.initialized = true;
1366
+ state.publishedHead = remote2;
1367
+ state.head = remote2;
1368
+ await this.saveOuter(state);
1369
+ if (options.bootstrapOnly) return { head: remote2, unchanged: true };
1370
+ } else if (options.bootstrapOnly) return { head: state.head, unchanged: true };
1371
+ if (state.conflict && !options.resolveConflict)
1372
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, "Workspace synchronization conflict awaits resolution", state.conflict.paths);
1373
+ const inners = await this.innerCheckouts(userId);
1374
+ let snapshot;
1375
+ try {
1376
+ snapshot = await repo.snapshot(inners, { allowLargeDiff: options.allowLargeDiff });
1377
+ } catch (error) {
1378
+ if (error instanceof OuterSnapshotRefusal) {
1379
+ state.blocked = { code: error.code, message: error.message, paths: error.paths };
1380
+ await this.saveOuter(state);
1381
+ }
1382
+ throw error;
1383
+ }
1384
+ if (state.conflict) {
1385
+ const marker = /^(<{7}|={7}|>{7})( |$)/m;
1386
+ for (const file of state.conflict.paths) {
1387
+ const bytes2 = await readRegular(path.join(repo.workTree, file)).catch((error) => {
1388
+ if (error.code === "ENOENT" || error.code === "ENOTDIR") return null;
1389
+ throw error;
1390
+ });
1391
+ if (bytes2 && marker.test(bytes2.toString("utf8")))
1392
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, "Conflict markers remain; resolve them before confirming", [file]);
1393
+ }
1394
+ } else if (state.blocked && state.blocked.code !== "publication_unknown") {
1395
+ state.blocked = null;
1396
+ await this.saveOuter(state);
1397
+ }
1398
+ const base = state.publishedHead;
1399
+ const baseTree = base ? await repo.treeOf(base) : await repo.emptyTree();
1400
+ let local;
1401
+ if (state.conflict) {
1402
+ local = await repo.commit(snapshot.tree, [state.conflict.ours, state.conflict.theirs], "Resolve workspace synchronization conflict");
1403
+ state.conflict = null;
1404
+ state.blocked = null;
1405
+ } else if (base && snapshot.tree === baseTree) local = base;
1406
+ else local = await repo.commit(snapshot.tree, base ? [base] : [], "Workspace snapshot");
1407
+ if (state.head !== local) {
1408
+ state.head = local;
1409
+ await repo.setHead(local);
1410
+ await this.saveOuter(state);
1411
+ }
1412
+ const integrated = async (head) => {
1413
+ if (options.requireHead && !await repo.isAncestor(options.requireHead, head))
1414
+ throw new WorkspaceError("conflict", "The required workspace head is not integrated; retry the transfer");
1415
+ return options.requireHead ? { integrated: options.requireHead } : {};
1416
+ };
1417
+ const remote = await this.remoteHead(storage, repositoryId, OUTER_BRANCH, true);
1418
+ let currentTree = snapshot.tree;
1419
+ if (remote && remote !== base) {
1420
+ if (!await repo.has(remote)) await repo.unbundle(await this.downloadBundle(storage, repositoryId));
1421
+ if (local === base) {
1422
+ await repo.apply(currentTree, await repo.treeOf(remote));
1423
+ state.publishedHead = remote;
1424
+ state.head = remote;
1425
+ await repo.setHead(remote);
1426
+ await this.saveOuter(state);
1427
+ return { head: remote, unchanged: false, ...await integrated(remote) };
1428
+ }
1429
+ const merge = await repo.merge(local, remote);
1430
+ if (merge.conflicts.length) {
1431
+ await repo.apply(currentTree, merge.tree);
1432
+ state.conflict = { ours: local, theirs: remote, tree: merge.tree, paths: merge.conflicts };
1433
+ state.blocked = { code: OUTER_CONFLICT_CODE, message: "The workspace diverged from another worker; conflict markers were written to the paths named", paths: merge.conflicts };
1434
+ await this.saveOuter(state);
1435
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, state.blocked.message, merge.conflicts);
1436
+ }
1437
+ await repo.apply(currentTree, merge.tree);
1438
+ currentTree = merge.tree;
1439
+ local = await repo.commit(merge.tree, [local, remote], "Merge workspace");
1440
+ state.head = local;
1441
+ await repo.setHead(local);
1442
+ await this.saveOuter(state);
1443
+ }
1444
+ if (local === remote) {
1445
+ state.publishedHead = local;
1446
+ await this.saveOuter(state);
1447
+ return { head: local, unchanged: true, ...await integrated(local) };
1448
+ }
1449
+ const operationId = `ws-${randomUUID()}`, blobId = `ws-${randomUUID()}`;
1450
+ const bytes = await repo.bundle(remote && await repo.has(remote) ? remote : null);
1451
+ state.blocked = { code: "publication_unknown", operationId, commit: local, message: "Workspace publication is in progress/unknown. Inspect the original storage operation; never retry under a new ID." };
1452
+ await this.saveOuter(state);
1453
+ try {
1454
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1455
+ const result = await storage.mutate({
1456
+ method: "repository.publish",
1457
+ operationId,
1458
+ repositoryId,
1459
+ branch: OUTER_BRANCH,
1460
+ expectedHead: remote,
1461
+ commit: local,
1462
+ bundleId: blobId
1463
+ });
1464
+ if (result.head !== local) throw new WorkspaceError("invalid_response", "Workspace publication receipt head mismatch; inspect original operation");
1465
+ } catch (error) {
1466
+ if (error instanceof WorkspaceError && error.rejectedBeforeAdmission) {
1467
+ state.blocked = null;
1468
+ await this.saveOuter(state);
1469
+ throw new WorkspaceError("mirror_advanced", "The workspace mirror advanced during publication; retried next cycle", true);
1470
+ }
1471
+ throw error;
1472
+ }
1473
+ state.publishedHead = local;
1474
+ state.blocked = null;
1475
+ await this.saveOuter(state);
1476
+ return { head: local, unchanged: false, ...await integrated(local) };
1477
+ }
1478
+ /** Push a project checkout's own HEAD to its mirror. Last push wins: no merge
1479
+ * is attempted, and a rewind or rewrite replaces the mirror as readily as a
1480
+ * fast-forward. A lost acknowledgement needs no reconciliation because the
1481
+ * next cycle simply observes the mirror already holds the head. */
1482
+ async mirrorInnerIdle(b, identity) {
1483
+ if (!b.state.initialized || !this.linkedWorkbench(b) || b.state.blocked?.code === "archived") return { head: b.state.head, unchanged: true };
1484
+ const head = await this.innerHead(b);
1485
+ if (!head || head === b.state.mirroredHead) return { head, unchanged: true };
1486
+ const storage = await this.storage(b, identity);
1487
+ const remote = await this.remoteHead(storage, b.config.repositoryId, b.config.branch, true);
1488
+ if (remote !== head) {
1489
+ const ref = `refs/r5d/mirror/${b.config.branch}`;
1490
+ await git(b.repo, ["update-ref", ref, head]);
1491
+ const file = path.join(b.directory, `mirror-${randomUUID()}.bundle`);
1492
+ const known = remote !== null && await this.hasCommit(b.repo, remote);
1493
+ const rewound = known && (await gitResult(b.repo, ["merge-base", "--is-ancestor", head, remote])).code === 0;
1494
+ const exclude = known && !rewound ? [`^${remote}`] : (await gitResult(b.repo, ["rev-parse", "--verify", "--quiet", `${head}~1`])).code === 0 ? [`^${head}~1`] : [];
1495
+ await git(b.repo, ["bundle", "create", file, ref, ...exclude]);
1496
+ const bytes = await readRegular(file, STORAGE_LIMITS.blobBytes);
1497
+ await fs.rm(file, { force: true });
1498
+ const operationId = `mirror-${randomUUID()}`;
1499
+ const force = await this.forcePublishSupported(storage);
1500
+ try {
1501
+ await this.uploadBundle(storage, bytes, operationId, operationId);
1502
+ const result = await storage.mutate({
1503
+ method: "repository.publish",
1504
+ operationId,
1505
+ repositoryId: b.config.repositoryId,
1506
+ branch: b.config.branch,
1507
+ expectedHead: remote,
1508
+ commit: head,
1509
+ bundleId: operationId,
1510
+ ...force ? { force: true } : {}
1511
+ });
1512
+ if (result.head !== head) throw new WorkspaceError("invalid_response", "Mirror receipt head mismatch");
1513
+ } catch (error) {
1514
+ if (error instanceof WorkspaceError && error.rejectedBeforeAdmission) return { head, unchanged: true };
1515
+ throw error;
1516
+ }
1517
+ }
1518
+ b.state.mirroredHead = head;
1519
+ b.state.head = head;
1520
+ await this.save(b);
1521
+ return { head, unchanged: false };
1522
+ }
1523
+ /** Mirror one project checkout now, outside the periodic cycle. */
1524
+ async mirror(identity) {
1525
+ const b = await this.bench(identity);
1526
+ if (!this.outerEnabled(b) || b.config.rootProfile === "account") return { head: b.state.head, unchanged: true };
1527
+ return this.serial(b, () => this.mirrorInnerIdle(b, identity));
1528
+ }
1529
+ /** Commit the checkout's working tree to its own history on the user's behalf. */
1530
+ async commitInnerIdle(b, identity, message) {
1531
+ if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Hydrate first");
1532
+ await git(b.config.cwd, ["add", "-A"]);
1533
+ const dirty = (await git(b.config.cwd, ["status", "--porcelain", "-z"])).length > 0;
1534
+ const before = await this.innerHead(b);
1535
+ if (!dirty && before) return { head: before, unchanged: true };
1536
+ await git(b.config.cwd, ["commit", "--quiet", "--allow-empty", "-m", message], void 0, void 0, void 0, { env: PROJECT_COMMIT_IDENTITY });
1537
+ const head = await this.innerHead(b);
1538
+ await this.mirrorInnerIdle(b, identity);
1539
+ return { head };
1540
+ }
1541
+ /** Install a project checkout from its mirror. Files may already be present
1542
+ * because the outer repository delivered them first; the worktree is then
1543
+ * created around them and they show as ordinary dirty content. */
1544
+ async hydrateLinkedIdle(b, identity) {
1545
+ await this.assertAvailable(b);
1546
+ if (b.state.initialized) return { head: b.state.head ?? "" };
1547
+ const storage = await this.storage(b, identity);
1548
+ const mirror = await this.remoteHead(storage, b.config.repositoryId, b.config.branch);
1549
+ if (mirror && !await this.hasCommit(b.repo, mirror)) await this.unbundleInto(b, await this.downloadBundle(storage, b.config.repositoryId));
1550
+ let visible = mirror;
1551
+ while (visible && await this.platformSnapshot(b.repo, visible)) {
1552
+ const parent = await this.firstParent(b.repo, visible);
1553
+ if (!parent) break;
1554
+ visible = parent;
1555
+ }
1556
+ if (!visible && b.config.baseCommitHash && await this.hasCommit(b.repo, b.config.baseCommitHash)) visible = b.config.baseCommitHash;
1557
+ if (!visible) throw new WorkspaceError("empty_repository", "Seed README explicitly for an empty mirrored branch");
1558
+ b.state.blocked = { code: "hydration_incomplete", message: "Checkout installation interrupted; preserve the checkout and inspect before maintenance" };
1559
+ await this.save(b);
1560
+ await this.installLinkedWorktree(b, visible, mirror && visible !== mirror ? mirror : null);
1561
+ await this.configureLinkedRemote(b);
1562
+ b.state.initialized = true;
1563
+ b.state.head = mirror ?? visible;
1564
+ b.state.mirroredHead = mirror;
1565
+ b.state.blocked = null;
1566
+ delete b.state.publishedMetadata;
1567
+ await this.save(b);
1568
+ return { head: b.state.head ?? "" };
1569
+ }
1570
+ async installLinkedWorktree(b, visible, legacySnapshot) {
1571
+ const destination = path.join(b.config.cwd, ".git");
1572
+ if (await fs.lstat(destination).then(() => true, (error) => {
1573
+ if (error.code === "ENOENT") return false;
1574
+ throw error;
1575
+ })) return;
1576
+ await fs.mkdir(b.config.cwd, { recursive: true, mode: 448 });
1577
+ await noSymlinkAncestors(b.config.cwd);
1578
+ await git(b.repo, ["update-ref", `refs/heads/${b.config.branch}`, visible]);
1579
+ if (!(await fs.readdir(b.config.cwd)).length) {
1580
+ await fs.rmdir(b.config.cwd);
1581
+ await git(b.repo, ["worktree", "add", "--force", b.config.cwd, b.config.branch]);
1582
+ if (legacySnapshot) {
1583
+ await git(b.config.cwd, ["reset", "--hard", legacySnapshot]);
1584
+ await git(b.config.cwd, ["reset", "--mixed", visible]);
1585
+ }
1586
+ return;
1587
+ }
1588
+ const staging = path.join(b.directory, `worktree-${randomUUID()}`);
1589
+ await git(b.repo, ["worktree", "add", "--no-checkout", "--force", staging, b.config.branch]);
1590
+ const pointer = /^gitdir: (.+?)\s*$/.exec((await readRegular(path.join(staging, ".git"), 4096)).toString("utf8"));
1591
+ if (!pointer || !path.isAbsolute(pointer[1])) throw new WorkspaceError("unsafe_git", "Invalid linked worktree pointer");
1592
+ const gitDirectory = path.normalize(pointer[1]);
1593
+ if (!gitDirectory.startsWith(path.join(b.repo, "worktrees") + path.sep)) throw new WorkspaceError("unsafe_git", "Linked worktree belongs to another repository");
1594
+ await fs.writeFile(destination, `gitdir: ${gitDirectory}
1595
+ `, { mode: 384, flag: "wx" });
1596
+ await fs.writeFile(path.join(gitDirectory, "gitdir"), `${destination}
1597
+ `, { mode: 384 });
1598
+ await fs.rm(staging, { recursive: true });
1599
+ await git(b.config.cwd, ["reset", "--mixed", visible]);
1600
+ }
1153
1601
  async publish(identity, options = {}) {
1154
1602
  const b = await this.bench(identity);
1155
- if (b.config.rootProfile === "account") return { head: "", unchanged: true };
1603
+ if (b.config.rootProfile === "account") {
1604
+ if (!this.outerEnabled()) return { head: "", unchanged: true };
1605
+ return this.synchronizeOuter(b.config.userId, { allowLargeDiff: options.allowLargeDiff, resolveConflict: options.allowBlockedConflict });
1606
+ }
1607
+ if (this.outerEnabled(b)) {
1608
+ const outer = await this.synchronizeOuter(b.config.userId);
1609
+ await this.serial(b, () => this.mirrorInnerIdle(b, identity));
1610
+ return outer;
1611
+ }
1156
1612
  return this.serial(b, async () => {
1157
- const conflictBlocked = b.state.blocked?.code === "conflict" || b.state.blocked?.code === "workbench_conflict";
1613
+ const conflictBlocked = !!b.state.blocked && WORKBENCH_CONFLICT_CODES.has(b.state.blocked.code);
1158
1614
  await this.assertAvailable(b, options.allowBlockedConflict === true && conflictBlocked);
1159
1615
  return this.publishIdle(b, identity, "Destination workspace snapshot", options.allowLargeDiff === true);
1160
1616
  });
1161
1617
  }
1162
- async publishIdle(b, identity, message = "Destination workspace snapshot", allowLargeDiff = false) {
1618
+ async publishIdle(b, identity, message = "Destination workspace snapshot", allowLargeDiff = false, projectIdentity = false) {
1163
1619
  if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Hydrate or explicitly seed first");
1164
1620
  const storage = await this.storage(b, identity);
1165
1621
  const latest = await storage.read({
@@ -1192,7 +1648,7 @@ class WorkspaceAuthority {
1192
1648
  throw new WorkspaceError("too_large", "Source diff exceeds the 5242880-byte automatic publication limit");
1193
1649
  }
1194
1650
  const commit = (await git(b.repo, ["commit-tree", tree, ...b.state.head ? ["-p", b.state.head] : []], `${message}
1195
- `)).toString().trim();
1651
+ `, void 0, void 0, projectIdentity ? { env: PROJECT_COMMIT_IDENTITY } : {})).toString().trim();
1196
1652
  await git(b.repo, ["update-ref", this.canonicalRef(b), commit]);
1197
1653
  const bundleFile = path.join(b.directory, `${randomUUID()}.bundle`);
1198
1654
  await git(b.repo, ["bundle", "create", bundleFile, this.canonicalRef(b)]);
@@ -1226,18 +1682,7 @@ class WorkspaceAuthority {
1226
1682
  message: "Publication attempt is in progress/unknown. Inspect original storage operation; NEVER retry under a new ID. Workbench and prepared commit retained."
1227
1683
  };
1228
1684
  await this.save(b);
1229
- for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1230
- const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1231
- await storage.mutate({
1232
- method: "blob.append",
1233
- operationId: `${operationId}-chunk-${offset}`,
1234
- blobId,
1235
- kind: "blob",
1236
- offset,
1237
- data: bytes.subarray(offset, end).toString("base64"),
1238
- seal: end === bytes.length
1239
- });
1240
- }
1685
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1241
1686
  const result = await storage.mutate({
1242
1687
  method: "repository.publish",
1243
1688
  operationId,
@@ -1313,7 +1758,7 @@ class WorkspaceAuthority {
1313
1758
  const b = await this.bench(identity);
1314
1759
  const operation = OperationEnvelope.parse(JSON.parse(canonicalJson(input)));
1315
1760
  return this.serial(b, async () => {
1316
- const conflictBlocked = b.state.blocked?.code === "conflict" || b.state.blocked?.code === "workbench_conflict";
1761
+ const conflictBlocked = !!b.state.blocked && WORKBENCH_CONFLICT_CODES.has(b.state.blocked.code);
1317
1762
  if (!b.state.initialized || b.state.blocked && !(allowBlockedConflict && conflictBlocked))
1318
1763
  throw new WorkspaceError("workbench_blocked", b.state.blocked?.message ?? "Initialize workbench first");
1319
1764
  if (operation.installationId !== this.config.installationId || operation.userId !== identity.userId || operation.sessionId !== identity.sessionId || operation.kind !== "host.shell")