@fml-inc/fml 0.8.10-dev.1 → 0.8.10

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.
@@ -184,9 +184,9 @@ function setSyncEnabled(settingsFile, enabled) {
184
184
 
185
185
  // ../../packages/panopticon/src/artifacts.ts
186
186
  import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
187
- import fs8 from "fs";
187
+ import fs9 from "fs";
188
188
  import os3 from "os";
189
- import path18 from "path";
189
+ import path19 from "path";
190
190
 
191
191
  // ../../packages/agent-targets/src/artifacts/targets/claude.ts
192
192
  import path8 from "path";
@@ -755,8 +755,100 @@ var grokArtifactDiscovery = Object.freeze({
755
755
  )
756
756
  });
757
757
 
758
- // ../../packages/agent-targets/src/artifacts/targets/pi.ts
758
+ // ../../packages/agent-targets/src/artifacts/targets/mini-swe-agent.ts
759
+ import fs6 from "fs";
759
760
  import path15 from "path";
761
+ var SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
762
+ function dataDirectory({ homeDir, env }) {
763
+ if (env.FML_DATA_DIR?.trim()) {
764
+ if (!path15.isAbsolute(env.FML_DATA_DIR)) {
765
+ throw new Error("FML_DATA_DIR must be an absolute path");
766
+ }
767
+ return path15.normalize(env.FML_DATA_DIR);
768
+ }
769
+ if (process.platform === "darwin") {
770
+ return path15.join(homeDir, "Library", "Application Support", "fml");
771
+ }
772
+ if (process.platform === "win32") {
773
+ const roaming = env.APPDATA && path15.isAbsolute(env.APPDATA) ? env.APPDATA : path15.join(homeDir, "AppData", "Roaming");
774
+ return path15.join(roaming, "fml");
775
+ }
776
+ const xdgDataHome = env.XDG_DATA_HOME && path15.isAbsolute(env.XDG_DATA_HOME) ? env.XDG_DATA_HOME : path15.join(homeDir, ".local", "share");
777
+ return path15.join(xdgDataHome, "fml");
778
+ }
779
+ function snapshotCandidate(sourcePath, context) {
780
+ let file;
781
+ try {
782
+ file = fs6.openSync(sourcePath, "r");
783
+ } catch {
784
+ return null;
785
+ }
786
+ try {
787
+ const stat = fs6.fstatSync(file);
788
+ if (!stat.isFile()) return null;
789
+ if (context.maxFileBytes !== void 0 && stat.size > context.maxFileBytes) {
790
+ return transcriptCandidate({ targetId: "mini-swe-agent", sourcePath });
791
+ }
792
+ const bytes = Buffer.allocUnsafe(stat.size);
793
+ let offset = 0;
794
+ while (offset < bytes.length) {
795
+ const read = fs6.readSync(
796
+ file,
797
+ bytes,
798
+ offset,
799
+ bytes.length - offset,
800
+ offset
801
+ );
802
+ if (read <= 0) return null;
803
+ offset += read;
804
+ }
805
+ if (fs6.fstatSync(file).size !== stat.size) return null;
806
+ const value = JSON.parse(bytes.toString("utf8"));
807
+ if (typeof value !== "object" || value === null || !("fml" in value)) {
808
+ return null;
809
+ }
810
+ const metadata = value.fml;
811
+ if (typeof metadata !== "object" || metadata === null || !("version" in metadata) || metadata.version !== 1 || !("session_id" in metadata) || typeof metadata.session_id !== "string" || !SESSION_ID_PATTERN.test(metadata.session_id)) {
812
+ return null;
813
+ }
814
+ const cwd = "cwd" in metadata && typeof metadata.cwd === "string" ? metadata.cwd : void 0;
815
+ const origin = cwd ? context.resolveGitHubOrigin?.(cwd) : null;
816
+ return transcriptCandidate({
817
+ targetId: "mini-swe-agent",
818
+ sourcePath,
819
+ sessionId: metadata.session_id,
820
+ metadata: { store: "managed_snapshots" },
821
+ repositoryObservations: origin ? [
822
+ repositoryObservation({
823
+ repository: origin.repository,
824
+ source: "git_origin",
825
+ observedAtMs: (context.nowMs ?? Date.now)(),
826
+ cwd,
827
+ branch: origin.branch,
828
+ commitHash: origin.commitHash
829
+ })
830
+ ] : []
831
+ });
832
+ } catch {
833
+ return null;
834
+ } finally {
835
+ fs6.closeSync(file);
836
+ }
837
+ }
838
+ var miniSweAgentArtifactDiscovery = Object.freeze({
839
+ targetId: "mini-swe-agent",
840
+ discover: (context) => walkFiles({
841
+ root: path15.join(dataDirectory(context), "mini-swe-agent", "trajectories"),
842
+ maxDepth: 0,
843
+ includeFile: (filePath) => filePath.endsWith(".traj.json")
844
+ }).flatMap((sourcePath) => {
845
+ const candidate = snapshotCandidate(sourcePath, context);
846
+ return candidate ? [candidate] : [];
847
+ })
848
+ });
849
+
850
+ // ../../packages/agent-targets/src/artifacts/targets/pi.ts
851
+ import path16 from "path";
760
852
  var PI_SKIP_DIRS = /* @__PURE__ */ new Set(["subagent-artifacts"]);
761
853
  function piTranscriptCandidate(sourcePath, context) {
762
854
  const fallbackObservedAtMs = (context.nowMs ?? Date.now)();
@@ -794,7 +886,7 @@ var piArtifactDiscovery = Object.freeze({
794
886
  discover: (context) => {
795
887
  const { homeDir } = context;
796
888
  return walkFiles({
797
- root: path15.join(homeDir, ".pi", "agent", "sessions"),
889
+ root: path16.join(homeDir, ".pi", "agent", "sessions"),
798
890
  maxDepth: 8,
799
891
  includeFile: (filePath) => filePath.endsWith(".jsonl"),
800
892
  skipDirs: PI_SKIP_DIRS
@@ -809,6 +901,7 @@ var ARTIFACT_DISCOVERY_CAPABILITIES = Object.freeze([
809
901
  geminiArtifactDiscovery,
810
902
  grokArtifactDiscovery,
811
903
  piArtifactDiscovery,
904
+ miniSweAgentArtifactDiscovery,
812
905
  cursorArtifactDiscovery,
813
906
  copilotCliArtifactDiscovery,
814
907
  factoryDroidArtifactDiscovery
@@ -826,13 +919,13 @@ function discoverTargetArtifactCandidates(context) {
826
919
 
827
920
  // ../../packages/agent-targets/src/artifacts/materialize.ts
828
921
  import { createHash as createHash3 } from "crypto";
829
- import fs6 from "fs";
830
- import path16 from "path";
922
+ import fs7 from "fs";
923
+ import path17 from "path";
831
924
  import zlib from "zlib";
832
925
  var MAX_MATERIALIZED_ARTIFACT_BYTES = 100 * 1024 * 1024;
833
926
  var DEFAULT_MATERIALIZED_CACHE_BYTES = 2 * 1024 * 1024 * 1024;
834
927
  function cacheEntryName(sourcePath, stat) {
835
- const identity = `${path16.resolve(sourcePath)}\0${stat.size}\0${Math.floor(
928
+ const identity = `${path17.resolve(sourcePath)}\0${stat.size}\0${Math.floor(
836
929
  stat.mtimeMs
837
930
  )}`;
838
931
  const digest = createHash3("sha256").update(identity).digest("hex");
@@ -845,7 +938,7 @@ function decodeZstd(sourcePath, maxOutputBytes) {
845
938
  const decompress = zlib.zstdDecompressSync;
846
939
  if (typeof decompress !== "function") return null;
847
940
  try {
848
- return decompress(fs6.readFileSync(sourcePath), {
941
+ return decompress(fs7.readFileSync(sourcePath), {
849
942
  maxOutputLength: maxOutputBytes
850
943
  });
851
944
  } catch {
@@ -854,9 +947,9 @@ function decodeZstd(sourcePath, maxOutputBytes) {
854
947
  }
855
948
  function materializedArtifactPath(input) {
856
949
  try {
857
- const stat = fs6.statSync(input.sourcePath);
950
+ const stat = fs7.statSync(input.sourcePath);
858
951
  if (!stat.isFile() || stat.size === 0) return null;
859
- return path16.join(input.cacheDir, cacheEntryName(input.sourcePath, stat));
952
+ return path17.join(input.cacheDir, cacheEntryName(input.sourcePath, stat));
860
953
  } catch {
861
954
  return null;
862
955
  }
@@ -864,20 +957,20 @@ function materializedArtifactPath(input) {
864
957
  function materializeCompressedArtifact(input) {
865
958
  let stat;
866
959
  try {
867
- stat = fs6.statSync(input.sourcePath);
960
+ stat = fs7.statSync(input.sourcePath);
868
961
  } catch {
869
962
  return null;
870
963
  }
871
964
  if (!stat.isFile() || stat.size === 0) return null;
872
- const cachePath = path16.join(
965
+ const cachePath = path17.join(
873
966
  input.cacheDir,
874
967
  cacheEntryName(input.sourcePath, stat)
875
968
  );
876
969
  try {
877
- if (fs6.statSync(cachePath).isFile()) {
970
+ if (fs7.statSync(cachePath).isFile()) {
878
971
  const now = /* @__PURE__ */ new Date();
879
972
  try {
880
- fs6.utimesSync(cachePath, now, now);
973
+ fs7.utimesSync(cachePath, now, now);
881
974
  } catch {
882
975
  }
883
976
  return cachePath;
@@ -890,10 +983,10 @@ function materializeCompressedArtifact(input) {
890
983
  );
891
984
  if (!decoded) return null;
892
985
  try {
893
- fs6.mkdirSync(input.cacheDir, { recursive: true, mode: 448 });
986
+ fs7.mkdirSync(input.cacheDir, { recursive: true, mode: 448 });
894
987
  const tempPath = `${cachePath}.${process.pid}.tmp`;
895
- fs6.writeFileSync(tempPath, decoded, { mode: 384 });
896
- fs6.renameSync(tempPath, cachePath);
988
+ fs7.writeFileSync(tempPath, decoded, { mode: 384 });
989
+ fs7.renameSync(tempPath, cachePath);
897
990
  return cachePath;
898
991
  } catch {
899
992
  return null;
@@ -903,16 +996,16 @@ function pruneMaterializedCache(input) {
903
996
  const maxTotalBytes = input.maxTotalBytes ?? DEFAULT_MATERIALIZED_CACHE_BYTES;
904
997
  let entries;
905
998
  try {
906
- entries = fs6.readdirSync(input.cacheDir, { withFileTypes: true });
999
+ entries = fs7.readdirSync(input.cacheDir, { withFileTypes: true });
907
1000
  } catch {
908
1001
  return { removed: 0, retainedBytes: 0 };
909
1002
  }
910
1003
  const files = [];
911
1004
  for (const entry of entries) {
912
1005
  if (!entry.isFile()) continue;
913
- const filePath = path16.join(input.cacheDir, entry.name);
1006
+ const filePath = path17.join(input.cacheDir, entry.name);
914
1007
  try {
915
- const stat = fs6.statSync(filePath);
1008
+ const stat = fs7.statSync(filePath);
916
1009
  files.push({ path: filePath, size: stat.size, atimeMs: stat.atimeMs });
917
1010
  } catch {
918
1011
  }
@@ -927,7 +1020,7 @@ function pruneMaterializedCache(input) {
927
1020
  continue;
928
1021
  }
929
1022
  try {
930
- fs6.rmSync(file.path);
1023
+ fs7.rmSync(file.path);
931
1024
  removed += 1;
932
1025
  } catch {
933
1026
  retainedBytes += file.size;
@@ -939,8 +1032,8 @@ function pruneMaterializedCache(input) {
939
1032
  // ../../packages/panopticon/src/repository-context.ts
940
1033
  import { execFileSync } from "child_process";
941
1034
  import { createHash as createHash4 } from "crypto";
942
- import fs7 from "fs";
943
- import path17 from "path";
1035
+ import fs8 from "fs";
1036
+ import path18 from "path";
944
1037
  var MAX_CWD_BYTES2 = 4096;
945
1038
  var GIT_OUTPUT_BYTES = 16 * 1024;
946
1039
  var GIT_CONFIG_OUTPUT_BYTES = 4 * 1024 * 1024;
@@ -1080,7 +1173,7 @@ var PERSISTENT_ORIGIN_CACHE_SCHEMA_VERSION = 2;
1080
1173
  var DEFAULT_PERSISTENT_ORIGIN_CACHE_MAX_ENTRIES = 512;
1081
1174
  function fileContentIdentity(filePath) {
1082
1175
  try {
1083
- const contents = fs7.readFileSync(filePath);
1176
+ const contents = fs8.readFileSync(filePath);
1084
1177
  return `sha256:${createHash4("sha256").update(contents).digest("hex")}`;
1085
1178
  } catch (error) {
1086
1179
  const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
@@ -1089,7 +1182,7 @@ function fileContentIdentity(filePath) {
1089
1182
  }
1090
1183
  function packedRefsIdentity(filePath) {
1091
1184
  try {
1092
- const stat = fs7.statSync(filePath, { bigint: true });
1185
+ const stat = fs8.statSync(filePath, { bigint: true });
1093
1186
  if (!stat.isFile() || stat.ino === 0n) return null;
1094
1187
  return [stat.dev, stat.ino, stat.size, stat.mtimeNs, stat.ctimeNs].join(
1095
1188
  ":"
@@ -1118,18 +1211,18 @@ function effectiveConfigIdentity(cwd) {
1118
1211
  }
1119
1212
  function readSmallText(filePath) {
1120
1213
  try {
1121
- return fs7.readFileSync(filePath, "utf8").trim();
1214
+ return fs8.readFileSync(filePath, "utf8").trim();
1122
1215
  } catch {
1123
1216
  return null;
1124
1217
  }
1125
1218
  }
1126
1219
  function findGitDirectory(cwd) {
1127
- let current = path17.resolve(cwd);
1220
+ let current = path18.resolve(cwd);
1128
1221
  for (; ; ) {
1129
- const candidate = path17.join(current, ".git");
1222
+ const candidate = path18.join(current, ".git");
1130
1223
  let stat;
1131
1224
  try {
1132
- stat = fs7.statSync(candidate);
1225
+ stat = fs8.statSync(candidate);
1133
1226
  } catch {
1134
1227
  stat = void 0;
1135
1228
  }
@@ -1140,20 +1233,20 @@ function findGitDirectory(cwd) {
1140
1233
  const pointer = readSmallText(candidate);
1141
1234
  const match = pointer ? /^gitdir:\s*(.+)$/u.exec(pointer) : null;
1142
1235
  if (!match?.[1]) return null;
1143
- const gitDir = path17.resolve(current, match[1]);
1144
- const common = readSmallText(path17.join(gitDir, "commondir"));
1236
+ const gitDir = path18.resolve(current, match[1]);
1237
+ const common = readSmallText(path18.join(gitDir, "commondir"));
1145
1238
  return {
1146
1239
  gitDir,
1147
- commonDir: common ? path17.resolve(gitDir, common) : gitDir
1240
+ commonDir: common ? path18.resolve(gitDir, common) : gitDir
1148
1241
  };
1149
1242
  }
1150
- const parent = path17.dirname(current);
1243
+ const parent = path18.dirname(current);
1151
1244
  if (parent === current) return null;
1152
1245
  current = parent;
1153
1246
  }
1154
1247
  }
1155
1248
  function checkoutSignature(layout, cwd) {
1156
- const headPath = path17.join(layout.gitDir, "HEAD");
1249
+ const headPath = path18.join(layout.gitDir, "HEAD");
1157
1250
  const head = readSmallText(headPath);
1158
1251
  const configIdentity = effectiveConfigIdentity(cwd);
1159
1252
  if (head === null || configIdentity === null) {
@@ -1162,14 +1255,14 @@ function checkoutSignature(layout, cwd) {
1162
1255
  const parts = [layout.gitDir, head, configIdentity];
1163
1256
  const ref = /^ref:\s*(.+)$/u.exec(head)?.[1];
1164
1257
  if (ref) {
1165
- const looseRefPath = path17.join(layout.commonDir, ref);
1258
+ const looseRefPath = path18.join(layout.commonDir, ref);
1166
1259
  if (/^ref:/u.test(readSmallText(looseRefPath) ?? "")) return null;
1167
1260
  const looseRefIdentity = fileContentIdentity(looseRefPath);
1168
1261
  const packedIdentity = packedRefsIdentity(
1169
- path17.join(layout.commonDir, "packed-refs")
1262
+ path18.join(layout.commonDir, "packed-refs")
1170
1263
  );
1171
1264
  const reftableIdentity = fileContentIdentity(
1172
- path17.join(layout.commonDir, "reftable", "tables.list")
1265
+ path18.join(layout.commonDir, "reftable", "tables.list")
1173
1266
  );
1174
1267
  if (!looseRefIdentity || !packedIdentity || !reftableIdentity || looseRefIdentity === "missing" && packedIdentity === "missing" && reftableIdentity === "missing") {
1175
1268
  return null;
@@ -1180,7 +1273,7 @@ function checkoutSignature(layout, cwd) {
1180
1273
  }
1181
1274
  function readPersistentOriginCache(cacheFile) {
1182
1275
  try {
1183
- const parsed = JSON.parse(fs7.readFileSync(cacheFile, "utf8"));
1276
+ const parsed = JSON.parse(fs8.readFileSync(cacheFile, "utf8"));
1184
1277
  if (parsed && typeof parsed === "object" && parsed.schemaVersion === PERSISTENT_ORIGIN_CACHE_SCHEMA_VERSION && parsed.entries && typeof parsed.entries === "object") {
1185
1278
  return parsed;
1186
1279
  }
@@ -1191,13 +1284,13 @@ function readPersistentOriginCache(cacheFile) {
1191
1284
  function writePersistentOriginCache(cacheFile, cache) {
1192
1285
  const temporary = `${cacheFile}.${process.pid}.tmp`;
1193
1286
  try {
1194
- fs7.mkdirSync(path17.dirname(cacheFile), { recursive: true, mode: 448 });
1195
- fs7.writeFileSync(temporary, `${JSON.stringify(cache)}
1287
+ fs8.mkdirSync(path18.dirname(cacheFile), { recursive: true, mode: 448 });
1288
+ fs8.writeFileSync(temporary, `${JSON.stringify(cache)}
1196
1289
  `, { mode: 384 });
1197
- fs7.renameSync(temporary, cacheFile);
1290
+ fs8.renameSync(temporary, cacheFile);
1198
1291
  } catch {
1199
1292
  try {
1200
- fs7.rmSync(temporary, { force: true });
1293
+ fs8.rmSync(temporary, { force: true });
1201
1294
  } catch {
1202
1295
  }
1203
1296
  }
@@ -1285,20 +1378,20 @@ function isAbortError(error) {
1285
1378
  }
1286
1379
  function safeStat(filePath) {
1287
1380
  try {
1288
- return fs8.statSync(filePath);
1381
+ return fs9.statSync(filePath);
1289
1382
  } catch {
1290
1383
  return null;
1291
1384
  }
1292
1385
  }
1293
1386
  function normalizeFilePath2(filePath) {
1294
- return path18.resolve(filePath);
1387
+ return path19.resolve(filePath);
1295
1388
  }
1296
1389
  function artifactReadPath(artifact) {
1297
1390
  return normalizeFilePath2(artifact.readPath ?? artifact.sourcePath);
1298
1391
  }
1299
1392
  function statCandidateSource(sourcePath, transientStatErrors) {
1300
1393
  try {
1301
- return fs8.statSync(sourcePath);
1394
+ return fs9.statSync(sourcePath);
1302
1395
  } catch (error) {
1303
1396
  if (error.code === "ENOENT") return null;
1304
1397
  if (transientStatErrors === "throw") throw error;
@@ -1306,7 +1399,7 @@ function statCandidateSource(sourcePath, transientStatErrors) {
1306
1399
  }
1307
1400
  }
1308
1401
  function contentTypeForPath(filePath) {
1309
- const ext = path18.extname(filePath).toLowerCase();
1402
+ const ext = path19.extname(filePath).toLowerCase();
1310
1403
  if (ext === ".json" || ext === ".jsonl") return "application/json";
1311
1404
  if (ext === ".md") return "text/markdown";
1312
1405
  if (ext === ".toml") return "application/toml";
@@ -1349,13 +1442,14 @@ function discoverArtifacts(options = {}) {
1349
1442
  };
1350
1443
  }
1351
1444
  const homeDir = normalizeFilePath2(homeDirInput);
1445
+ const maxBytes = options.maxFileBytes ?? DEFAULT_MAX_ARTIFACT_BYTES;
1352
1446
  const candidates = discoverTargetArtifactCandidates({
1353
1447
  homeDir,
1354
1448
  env,
1449
+ maxFileBytes: maxBytes,
1355
1450
  resolveGitHubOrigin: repositoryResolution.resolve,
1356
1451
  ...options.materializeArtifact ? { materializeArtifact: options.materializeArtifact } : {}
1357
1452
  });
1358
- const maxBytes = options.maxFileBytes ?? DEFAULT_MAX_ARTIFACT_BYTES;
1359
1453
  const byKey = /* @__PURE__ */ new Map();
1360
1454
  const oversizedByKey = /* @__PURE__ */ new Map();
1361
1455
  for (const candidate of candidates) {
@@ -1418,7 +1512,7 @@ function readUploadThrottles(value) {
1418
1512
  }
1419
1513
  function readArtifactQueue(queueFile) {
1420
1514
  try {
1421
- const parsed = JSON.parse(fs8.readFileSync(queueFile, "utf8"));
1515
+ const parsed = JSON.parse(fs9.readFileSync(queueFile, "utf8"));
1422
1516
  if (!parsed || typeof parsed !== "object") return emptyQueue();
1423
1517
  const record = parsed;
1424
1518
  if (record.schemaVersion !== RAW_ARTIFACT_SCHEMA_VERSION) {
@@ -1435,15 +1529,15 @@ function readArtifactQueue(queueFile) {
1435
1529
  }
1436
1530
  }
1437
1531
  function writeArtifactQueue(queueFile, queue) {
1438
- fs8.mkdirSync(path18.dirname(queueFile), { recursive: true, mode: 448 });
1532
+ fs9.mkdirSync(path19.dirname(queueFile), { recursive: true, mode: 448 });
1439
1533
  const tempFile = `${queueFile}.${process.pid}.${Date.now()}.tmp`;
1440
- fs8.writeFileSync(tempFile, `${JSON.stringify(queue, null, 2)}
1534
+ fs9.writeFileSync(tempFile, `${JSON.stringify(queue, null, 2)}
1441
1535
  `, {
1442
1536
  mode: 384
1443
1537
  });
1444
- fs8.renameSync(tempFile, queueFile);
1538
+ fs9.renameSync(tempFile, queueFile);
1445
1539
  try {
1446
- fs8.chmodSync(queueFile, 384);
1540
+ fs9.chmodSync(queueFile, 384);
1447
1541
  } catch {
1448
1542
  }
1449
1543
  }
@@ -1460,11 +1554,20 @@ function nextGenerationStartedAtMs(nowMs, existing) {
1460
1554
  return existing ? Math.max(nowMs, existing.generationStartedAtMs + 1) : nowMs;
1461
1555
  }
1462
1556
  function shouldStartNewGeneration(input) {
1557
+ if (input.existing.source === "mini-swe-agent") {
1558
+ if (input.existing.contentSha256) {
1559
+ try {
1560
+ return createHash5("sha256").update(fs9.readFileSync(input.nextReadPath)).digest("hex") !== input.existing.contentSha256;
1561
+ } catch {
1562
+ }
1563
+ }
1564
+ return input.nextSizeBytes !== input.existing.sizeBytes || input.nextMtimeMs !== input.existing.mtimeMs;
1565
+ }
1463
1566
  if (input.nextSizeBytes < input.existing.uploadedSizeBytes) return true;
1464
1567
  if (input.nextSizeBytes < input.existing.sizeBytes) return true;
1465
1568
  if ((input.nextReadPath !== artifactReadPath(input.existing) || input.existing.readPath !== void 0) && input.nextSizeBytes === input.existing.sizeBytes && input.existing.uploadedSizeBytes >= input.nextSizeBytes && input.existing.contentSha256) {
1466
1569
  try {
1467
- const contentSha256 = createHash5("sha256").update(fs8.readFileSync(input.nextReadPath)).digest("hex");
1570
+ const contentSha256 = createHash5("sha256").update(fs9.readFileSync(input.nextReadPath)).digest("hex");
1468
1571
  if (contentSha256 === input.existing.contentSha256) return false;
1469
1572
  } catch {
1470
1573
  }
@@ -1583,7 +1686,7 @@ function metadataForGeneration(input) {
1583
1686
  ...repositoryContext ? { repositoryContext } : {}
1584
1687
  };
1585
1688
  }
1586
- function snapshotCandidate(candidate, existing, nowMs, maxFileBytes, transientStatErrors = "ignore", observerIdentity) {
1689
+ function snapshotCandidate2(candidate, existing, nowMs, maxFileBytes, transientStatErrors = "ignore", observerIdentity) {
1587
1690
  const sourcePath = normalizeFilePath2(candidate.sourcePath);
1588
1691
  const readPath = artifactReadPath(candidate);
1589
1692
  const stat = statCandidateSource(readPath, transientStatErrors);
@@ -1727,7 +1830,7 @@ function snapshotArtifactsLocked(options, lock) {
1727
1830
  throw new Error("artifact queue lock ownership was lost");
1728
1831
  }
1729
1832
  const existing = (candidate.identityKey ? entriesByIdentityKey.get(candidate.identityKey) : void 0) ?? entriesByKey.get(buildArtifactKey(candidate));
1730
- const snapshot = snapshotCandidate(
1833
+ const snapshot = snapshotCandidate2(
1731
1834
  candidate,
1732
1835
  existing,
1733
1836
  nowMs,
@@ -1798,7 +1901,7 @@ function sameSourceRevision(left, right) {
1798
1901
  }
1799
1902
  function safeSourceRevision(filePath) {
1800
1903
  try {
1801
- const stat = fs8.statSync(filePath, { bigint: true });
1904
+ const stat = fs9.statSync(filePath, { bigint: true });
1802
1905
  return stat.isFile() ? sourceRevisionFromStat(stat) : null;
1803
1906
  } catch {
1804
1907
  return null;
@@ -1810,7 +1913,7 @@ function readExactRange(fd, startByte, endByte) {
1810
1913
  const buffer = Buffer.alloc(sizeBytes);
1811
1914
  let offset = 0;
1812
1915
  while (offset < sizeBytes) {
1813
- const bytesRead = fs8.readSync(
1916
+ const bytesRead = fs9.readSync(
1814
1917
  fd,
1815
1918
  buffer,
1816
1919
  offset,
@@ -1829,19 +1932,19 @@ function readFileRangeAtRevision(filePath, startByte, endByte, expectedRevision)
1829
1932
  }
1830
1933
  let fd;
1831
1934
  try {
1832
- fd = fs8.openSync(filePath, "r");
1935
+ fd = fs9.openSync(filePath, "r");
1833
1936
  } catch {
1834
1937
  return null;
1835
1938
  }
1836
1939
  try {
1837
1940
  const openedRevision = sourceRevisionFromStat(
1838
- fs8.fstatSync(fd, { bigint: true })
1941
+ fs9.fstatSync(fd, { bigint: true })
1839
1942
  );
1840
1943
  if (!sameSourceRevision(pathRevisionBefore, openedRevision)) return null;
1841
1944
  const bytes = readExactRange(fd, startByte, endByte);
1842
1945
  if (!bytes) return null;
1843
1946
  const revisionAfterRead = sourceRevisionFromStat(
1844
- fs8.fstatSync(fd, { bigint: true })
1947
+ fs9.fstatSync(fd, { bigint: true })
1845
1948
  );
1846
1949
  const pathRevisionAfter = safeSourceRevision(filePath);
1847
1950
  if (!sameSourceRevision(openedRevision, revisionAfterRead) || !pathRevisionAfter || !sameSourceRevision(openedRevision, pathRevisionAfter)) {
@@ -1851,7 +1954,7 @@ function readFileRangeAtRevision(filePath, startByte, endByte, expectedRevision)
1851
1954
  } catch {
1852
1955
  return null;
1853
1956
  } finally {
1854
- fs8.closeSync(fd);
1957
+ fs9.closeSync(fd);
1855
1958
  }
1856
1959
  }
1857
1960
  function uploadMetadata(input) {
@@ -1983,13 +2086,13 @@ function validateCheckpointPrefix(input) {
1983
2086
  }
1984
2087
  let fd;
1985
2088
  try {
1986
- fd = fs8.openSync(input.sourcePath, "r");
2089
+ fd = fs9.openSync(input.sourcePath, "r");
1987
2090
  } catch {
1988
2091
  return { status: "changed" };
1989
2092
  }
1990
2093
  try {
1991
2094
  const openedRevision = sourceRevisionFromStat(
1992
- fs8.fstatSync(fd, { bigint: true })
2095
+ fs9.fstatSync(fd, { bigint: true })
1993
2096
  );
1994
2097
  if (!sameSourceRevision(pathRevisionBefore, openedRevision)) {
1995
2098
  return { status: "changed" };
@@ -2009,7 +2112,7 @@ function validateCheckpointPrefix(input) {
2009
2112
  contentHash.update(chunk);
2010
2113
  }
2011
2114
  const revisionAfterRead = sourceRevisionFromStat(
2012
- fs8.fstatSync(fd, { bigint: true })
2115
+ fs9.fstatSync(fd, { bigint: true })
2013
2116
  );
2014
2117
  const pathRevisionAfter = safeSourceRevision(input.sourcePath);
2015
2118
  if (!sameSourceRevision(openedRevision, revisionAfterRead) || !pathRevisionAfter || !sameSourceRevision(openedRevision, pathRevisionAfter)) {
@@ -2024,7 +2127,7 @@ function validateCheckpointPrefix(input) {
2024
2127
  } catch {
2025
2128
  return { status: "changed" };
2026
2129
  } finally {
2027
- fs8.closeSync(fd);
2130
+ fs9.closeSync(fd);
2028
2131
  }
2029
2132
  }
2030
2133
  function validatedPrefixStillApplies(prefix, entry, uploadDestinationId, revision) {
@@ -2158,14 +2261,14 @@ function defaultIsPidAlive(pid) {
2158
2261
  }
2159
2262
  function readQueueLockHolder(lockFile) {
2160
2263
  try {
2161
- const parsed = JSON.parse(fs8.readFileSync(lockFile, "utf8"));
2264
+ const parsed = JSON.parse(fs9.readFileSync(lockFile, "utf8"));
2162
2265
  if (!parsed || typeof parsed !== "object") return null;
2163
2266
  const record = parsed;
2164
2267
  if (typeof record.pid !== "number" || typeof record.timestampMs !== "number") {
2165
2268
  return null;
2166
2269
  }
2167
2270
  const ownerToken = typeof record.ownerToken === "string" ? record.ownerToken : void 0;
2168
- const timestampMs = ownerToken ? Math.max(record.timestampMs, fs8.statSync(lockFile).mtimeMs) : record.timestampMs;
2271
+ const timestampMs = ownerToken ? Math.max(record.timestampMs, fs9.statSync(lockFile).mtimeMs) : record.timestampMs;
2169
2272
  return { pid: record.pid, timestampMs, ownerToken };
2170
2273
  } catch {
2171
2274
  return null;
@@ -2173,8 +2276,8 @@ function readQueueLockHolder(lockFile) {
2173
2276
  }
2174
2277
  function queueLockFileMatchesOwner(lockFile, fd, ownerToken) {
2175
2278
  try {
2176
- const openStat = fs8.fstatSync(fd);
2177
- const pathStat = fs8.statSync(lockFile);
2279
+ const openStat = fs9.fstatSync(fd);
2280
+ const pathStat = fs9.statSync(lockFile);
2178
2281
  if (openStat.dev !== pathStat.dev || openStat.ino !== pathStat.ino) {
2179
2282
  return false;
2180
2283
  }
@@ -2185,14 +2288,14 @@ function queueLockFileMatchesOwner(lockFile, fd, ownerToken) {
2185
2288
  }
2186
2289
  function acquireQueueLock(queueFile, deps) {
2187
2290
  const lockFile = queueLockFile(queueFile);
2188
- fs8.mkdirSync(path18.dirname(lockFile), { recursive: true, mode: 448 });
2291
+ fs9.mkdirSync(path19.dirname(lockFile), { recursive: true, mode: 448 });
2189
2292
  for (let attempt = 0; attempt < 2; attempt += 1) {
2190
2293
  try {
2191
- const fd = fs8.openSync(lockFile, "wx+", 384);
2294
+ const fd = fs9.openSync(lockFile, "wx+", 384);
2192
2295
  const ownerToken = randomUUID3();
2193
2296
  let released = false;
2194
2297
  try {
2195
- fs8.writeSync(
2298
+ fs9.writeSync(
2196
2299
  fd,
2197
2300
  `${JSON.stringify({
2198
2301
  pid: process.pid,
@@ -2202,11 +2305,11 @@ function acquireQueueLock(queueFile, deps) {
2202
2305
  `
2203
2306
  );
2204
2307
  const heartbeatAt = new Date(deps.nowMs());
2205
- fs8.futimesSync(fd, heartbeatAt, heartbeatAt);
2308
+ fs9.futimesSync(fd, heartbeatAt, heartbeatAt);
2206
2309
  } catch (error) {
2207
- fs8.closeSync(fd);
2310
+ fs9.closeSync(fd);
2208
2311
  try {
2209
- fs8.unlinkSync(lockFile);
2312
+ fs9.unlinkSync(lockFile);
2210
2313
  } catch {
2211
2314
  }
2212
2315
  throw error;
@@ -2214,7 +2317,7 @@ function acquireQueueLock(queueFile, deps) {
2214
2317
  const close = () => {
2215
2318
  if (released) return;
2216
2319
  released = true;
2217
- fs8.closeSync(fd);
2320
+ fs9.closeSync(fd);
2218
2321
  };
2219
2322
  return {
2220
2323
  heartbeat() {
@@ -2223,7 +2326,7 @@ function acquireQueueLock(queueFile, deps) {
2223
2326
  return false;
2224
2327
  try {
2225
2328
  const heartbeatAt = new Date(deps.nowMs());
2226
- fs8.futimesSync(fd, heartbeatAt, heartbeatAt);
2329
+ fs9.futimesSync(fd, heartbeatAt, heartbeatAt);
2227
2330
  return true;
2228
2331
  } catch {
2229
2332
  return false;
@@ -2233,7 +2336,7 @@ function acquireQueueLock(queueFile, deps) {
2233
2336
  if (released) return;
2234
2337
  if (queueLockFileMatchesOwner(lockFile, fd, ownerToken)) {
2235
2338
  try {
2236
- fs8.unlinkSync(lockFile);
2339
+ fs9.unlinkSync(lockFile);
2237
2340
  } catch {
2238
2341
  }
2239
2342
  }
@@ -2246,7 +2349,7 @@ function acquireQueueLock(queueFile, deps) {
2246
2349
  const stale = !holder || !deps.isPidAlive(holder.pid) || deps.nowMs() - holder.timestampMs > QUEUE_LOCK_STALE_MS;
2247
2350
  if (!stale) return null;
2248
2351
  try {
2249
- fs8.unlinkSync(lockFile);
2352
+ fs9.unlinkSync(lockFile);
2250
2353
  } catch {
2251
2354
  }
2252
2355
  }
@@ -2304,7 +2407,7 @@ async function postRawArtifact(url, metadata, content, headers, fetchImpl = fetc
2304
2407
  form.append(
2305
2408
  "file",
2306
2409
  new Blob([new Uint8Array(content)], { type: metadata.contentType }),
2307
- path18.basename(metadata.sourcePath) || "raw-artifact"
2410
+ path19.basename(metadata.sourcePath) || "raw-artifact"
2308
2411
  );
2309
2412
  const abort = new AbortController();
2310
2413
  const timeout = setTimeout(() => abort.abort(), timeoutMs);
@@ -2663,7 +2766,7 @@ async function uploadPendingArtifactsLocked(options, run) {
2663
2766
  let sourceRefreshesThisAttempt = 0;
2664
2767
  let validatedPrefix;
2665
2768
  const refreshSourceSnapshot = () => {
2666
- const snapshot = snapshotCandidate(
2769
+ const snapshot = snapshotCandidate2(
2667
2770
  {
2668
2771
  artifactType: current.artifactType,
2669
2772
  source: current.source,
@@ -3193,11 +3296,11 @@ async function uploadPendingArtifactsLocked(options, run) {
3193
3296
  }
3194
3297
 
3195
3298
  // ../../packages/panopticon/src/raw-sync.ts
3196
- import fs10 from "fs";
3197
- import path19 from "path";
3299
+ import fs11 from "fs";
3300
+ import path20 from "path";
3198
3301
 
3199
3302
  // ../../packages/panopticon/src/artifact-materializer.ts
3200
- import fs9 from "fs";
3303
+ import fs10 from "fs";
3201
3304
  function entryNeedsBytes(entry, amendmentPending) {
3202
3305
  if (entry.uploadedSizeBytes < entry.sizeBytes) return true;
3203
3306
  return amendmentPending(entry);
@@ -3212,7 +3315,7 @@ function createArtifactMaterializer(input) {
3212
3315
  const unsupportedReason = (input.supportsCompression ?? supportsCompressedArtifacts)() ? void 0 : `compressed artifacts need Node 22.15 or newer (running ${process.version})`;
3213
3316
  const chargeExisting = (cachePath) => {
3214
3317
  try {
3215
- const stat = fs9.statSync(cachePath);
3318
+ const stat = fs10.statSync(cachePath);
3216
3319
  if (!stat.isFile()) return false;
3217
3320
  if (!retained.has(cachePath)) {
3218
3321
  retained.add(cachePath);
@@ -3260,20 +3363,20 @@ function getRawArtifactSyncPaths(stateDir) {
3260
3363
  if (stateDir.length === 0) {
3261
3364
  throw new Error("raw artifact sync state directory must not be empty");
3262
3365
  }
3263
- const root = path19.resolve(stateDir);
3366
+ const root = path20.resolve(stateDir);
3264
3367
  const managed = getManagedClientPaths({ PANOPTICON_HOME: root });
3265
3368
  return {
3266
3369
  root,
3267
3370
  settingsFile: managed.syncSettingsFile,
3268
3371
  queueFile: managed.artifactQueue,
3269
3372
  artifactCacheDir: managed.artifactCache,
3270
- discoveryCacheFile: path19.join(root, "discovery.cache.json"),
3271
- githubOriginCacheFile: path19.join(root, "github-origins.cache.json")
3373
+ discoveryCacheFile: path20.join(root, "discovery.cache.json"),
3374
+ githubOriginCacheFile: path20.join(root, "github-origins.cache.json")
3272
3375
  };
3273
3376
  }
3274
3377
  function invalidateRawArtifactDiscoveryCache(stateDir) {
3275
3378
  try {
3276
- fs10.rmSync(getRawArtifactSyncPaths(stateDir).discoveryCacheFile, {
3379
+ fs11.rmSync(getRawArtifactSyncPaths(stateDir).discoveryCacheFile, {
3277
3380
  force: true
3278
3381
  });
3279
3382
  } catch {
@@ -3382,7 +3485,7 @@ function createRawArtifactSync(options) {
3382
3485
  if (reuseMs <= 0) return null;
3383
3486
  try {
3384
3487
  const parsed = JSON.parse(
3385
- fs10.readFileSync(paths.discoveryCacheFile, "utf8")
3488
+ fs11.readFileSync(paths.discoveryCacheFile, "utf8")
3386
3489
  );
3387
3490
  if (parsed.schemaVersion !== DISCOVERY_CACHE_SCHEMA_VERSION || typeof parsed.createdAtMs !== "number" || parsed.inputs !== discoveryInputs() || !parsed.discovery || typeof parsed.discovery !== "object") {
3388
3491
  return null;
@@ -3398,11 +3501,11 @@ function createRawArtifactSync(options) {
3398
3501
  if ((options.discoveryReuseMs ?? 0) <= 0) return;
3399
3502
  const temporary = `${paths.discoveryCacheFile}.${process.pid}.tmp`;
3400
3503
  try {
3401
- fs10.mkdirSync(path19.dirname(paths.discoveryCacheFile), {
3504
+ fs11.mkdirSync(path20.dirname(paths.discoveryCacheFile), {
3402
3505
  recursive: true,
3403
3506
  mode: 448
3404
3507
  });
3405
- fs10.writeFileSync(
3508
+ fs11.writeFileSync(
3406
3509
  temporary,
3407
3510
  `${JSON.stringify({
3408
3511
  schemaVersion: DISCOVERY_CACHE_SCHEMA_VERSION,
@@ -3413,10 +3516,10 @@ function createRawArtifactSync(options) {
3413
3516
  `,
3414
3517
  { mode: 384 }
3415
3518
  );
3416
- fs10.renameSync(temporary, paths.discoveryCacheFile);
3519
+ fs11.renameSync(temporary, paths.discoveryCacheFile);
3417
3520
  } catch {
3418
3521
  try {
3419
- fs10.rmSync(temporary, { force: true });
3522
+ fs11.rmSync(temporary, { force: true });
3420
3523
  } catch {
3421
3524
  }
3422
3525
  }