superbee 0.4.6-pre.1 → 0.4.6-pre.3

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.
@@ -30844,15 +30844,30 @@ var FrontmatterRefusedError = class extends InvalidInputError {
30844
30844
  }
30845
30845
  };
30846
30846
  var FilesystemIdentityAliasError = class extends InvalidInputError {
30847
+ reason = "filesystem_alias";
30847
30848
  rel;
30848
30849
  segment;
30849
- constructor(rel, segment) {
30850
+ existing;
30851
+ suggestedPath;
30852
+ /**
30853
+ * `noun` names the existing entry ("folder" or "file"); `index` is the position of `segment`
30854
+ * in `rel`. Both default from the position of the first segment spelled `segment`.
30855
+ */
30856
+ constructor(rel, segment, existing, noun, index2) {
30857
+ const segments = rel.split("/").filter((part) => part !== "" && part !== ".");
30858
+ const at = index2 ?? segments.indexOf(segment);
30859
+ const kind2 = noun ?? (at === segments.length - 1 ? "file" : "folder");
30860
+ const clash = existing === void 0 ? `but a ${kind2} with that name in a different case or Unicode form already exists` : existing.normalize("NFC") === segment.normalize("NFC") ? `but ${kind2} '${existing}' already exists, written in a different Unicode form` : `but ${kind2} '${existing}' already exists`;
30861
+ const difference = existing === void 0 ? "case or Unicode form" : existing.normalize("NFC") === segment.normalize("NFC") ? "Unicode form" : existing.toLowerCase() === segment.toLowerCase() ? "case" : "case and Unicode form";
30850
30862
  super(
30851
- `Path '${rel}' does not match the exact spelling of an existing filesystem entry at segment '${segment}'; ids that differ only by case or Unicode normalization cannot share one file.`
30863
+ `Path '${rel}' uses ${kind2} '${segment}', ${clash}, and this disk treats names that differ only by ${difference} as the same name. Use the existing spelling.`
30852
30864
  );
30853
30865
  this.name = "FilesystemIdentityAliasError";
30854
30866
  this.rel = rel;
30855
30867
  this.segment = segment;
30868
+ this.existing = existing;
30869
+ const unusable = existing === void 0 || at < 0 || segments[at] !== segment || kind2 === "file" && at < segments.length - 1 || existing.normalize("NFC") === segment.normalize("NFC");
30870
+ this.suggestedPath = unusable ? void 0 : segments.map((part, position2) => position2 === at ? existing : part).join("/");
30856
30871
  }
30857
30872
  };
30858
30873
  var ConcurrentReplacementError = class extends Error {
@@ -31057,6 +31072,9 @@ function delimiterLineEnd(input, offset) {
31057
31072
  if (input[suffix] === "\r" && input[suffix + 1] === "\n") return suffix + 2;
31058
31073
  return null;
31059
31074
  }
31075
+ function startsWithFrontmatterSyntax(text4) {
31076
+ return text4.startsWith("\uFEFF") || delimiterLineEnd(text4, 0) !== null;
31077
+ }
31060
31078
  function splitLeadingFrontmatter(raw, context) {
31061
31079
  const input = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
31062
31080
  const openingEnd = delimiterLineEnd(input, 0);
@@ -31162,7 +31180,10 @@ function stringifyWithSerializedFrontmatter(dumped, body) {
31162
31180
  const content3 = body ?? "";
31163
31181
  const newline = (value) => value.endsWith("\n") ? value : `${value}
31164
31182
  `;
31165
- if (dumped === "{}") return normalizeDocumentBodyForStorage(content3);
31183
+ if (dumped === "{}") {
31184
+ const stored = normalizeDocumentBodyForStorage(content3);
31185
+ return `${startsWithFrontmatterSyntax(stored) ? "---\n---\n" : ""}${stored}`;
31186
+ }
31166
31187
  return `---
31167
31188
  ${newline(dumped)}---
31168
31189
  ${normalizeDocumentBodyForStorage(content3)}`;
@@ -31605,6 +31626,8 @@ function extractMarkdownLinkSpans(source, options = {}) {
31605
31626
  const body = options.skipCode ? maskMarkdownCode(source) : source;
31606
31627
  const out = [];
31607
31628
  let textOpen = -1;
31629
+ let codeOpen = -1;
31630
+ let masked;
31608
31631
  let afterClose;
31609
31632
  let hrefFirst;
31610
31633
  let hrefRest;
@@ -31623,6 +31646,7 @@ function extractMarkdownLinkSpans(source, options = {}) {
31623
31646
  image
31624
31647
  });
31625
31648
  textOpen = -1;
31649
+ codeOpen = -1;
31626
31650
  afterClose = void 0;
31627
31651
  hrefFirst = void 0;
31628
31652
  hrefRest = void 0;
@@ -31643,10 +31667,22 @@ function extractMarkdownLinkSpans(source, options = {}) {
31643
31667
  afterClose = void 0;
31644
31668
  }
31645
31669
  if (textOpen >= 0 && char === "]") {
31646
- afterClose = { open: textOpen, close: cursor };
31670
+ const open = codeOpen >= 0 && masked[cursor] !== "]" ? codeOpen : textOpen;
31671
+ afterClose = { open, close: cursor };
31647
31672
  textOpen = -1;
31673
+ codeOpen = -1;
31674
+ }
31675
+ if (char === "[") {
31676
+ if (textOpen >= 0 && !options.skipCode) {
31677
+ masked ??= maskMarkdownCode(source);
31678
+ if (masked[cursor] !== "[" && masked[textOpen] === "[") {
31679
+ codeOpen = cursor;
31680
+ continue;
31681
+ }
31682
+ }
31683
+ textOpen = cursor;
31684
+ codeOpen = -1;
31648
31685
  }
31649
- if (char === "[" && textOpen < 0) textOpen = cursor;
31650
31686
  }
31651
31687
  return out;
31652
31688
  }
@@ -31980,36 +32016,57 @@ function hasSourceIdentity(sources, identity) {
31980
32016
  return Array.isArray(sources) && sources.some((entry) => matchesSourceIdentity(entry, identity));
31981
32017
  }
31982
32018
 
32019
+ // ../core/src/skip-reasons.ts
32020
+ var PERMISSION_DENIED_PREFIX = "permission denied (";
32021
+ function permissionDeniedReason(code2) {
32022
+ return `${PERMISSION_DENIED_PREFIX}${code2})`;
32023
+ }
32024
+ function isPermissionDeniedSkip(skip) {
32025
+ return skip.reason.startsWith(PERMISSION_DENIED_PREFIX);
32026
+ }
32027
+
31983
32028
  // ../core/src/document-scan.ts
31984
32029
  function isEnoent(err) {
31985
32030
  return typeof err === "object" && err !== null && err.code === "ENOENT";
31986
32031
  }
31987
- async function readManyExisting(backend, ids, onMalformed, onAliased) {
31988
- try {
31989
- return await backend.readMany(ids);
31990
- } catch (err) {
31991
- const malformed = err instanceof MalformedDocumentError && onMalformed !== void 0;
31992
- const aliased = err instanceof FilesystemIdentityAliasError && onAliased !== void 0;
31993
- if (!isEnoent(err) && !malformed && !aliased) throw err;
31994
- const out = [];
31995
- for (const id of ids) {
31996
- try {
31997
- out.push(await backend.read(id));
31998
- } catch (candidate) {
31999
- if (isEnoent(candidate)) continue;
32000
- if (candidate instanceof MalformedDocumentError && onMalformed) {
32001
- onMalformed({ id, reason: candidate.detail });
32002
- continue;
32003
- }
32004
- if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
32005
- onAliased({ id, reason: candidate.message });
32006
- continue;
32007
- }
32008
- throw candidate;
32032
+ function deniedReason(err) {
32033
+ const code2 = typeof err === "object" && err !== null ? err.code : void 0;
32034
+ return code2 === "EACCES" || code2 === "EPERM" ? permissionDeniedReason(code2) : void 0;
32035
+ }
32036
+ async function readManyExisting(backend, ids, onMalformed, onAliased, onDenied) {
32037
+ const tolerated = (err) => isEnoent(err) || err instanceof MalformedDocumentError && onMalformed !== void 0 || err instanceof FilesystemIdentityAliasError && onAliased !== void 0 || deniedReason(err) !== void 0 && onDenied !== void 0;
32038
+ const readOne = async (id) => {
32039
+ try {
32040
+ return [await backend.read(id)];
32041
+ } catch (candidate) {
32042
+ if (isEnoent(candidate)) return [];
32043
+ if (candidate instanceof MalformedDocumentError && onMalformed) {
32044
+ onMalformed({ id, reason: candidate.detail });
32045
+ return [];
32009
32046
  }
32047
+ if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
32048
+ onAliased({ id, reason: candidate.message });
32049
+ return [];
32050
+ }
32051
+ const reason = deniedReason(candidate);
32052
+ if (reason !== void 0 && onDenied) {
32053
+ onDenied({ id, reason });
32054
+ return [];
32055
+ }
32056
+ throw candidate;
32010
32057
  }
32011
- return out;
32012
- }
32058
+ };
32059
+ const readBatch = async (batch) => {
32060
+ try {
32061
+ return await backend.readMany(batch);
32062
+ } catch (err) {
32063
+ if (!tolerated(err)) throw err;
32064
+ if (batch.length === 1) return readOne(batch[0]);
32065
+ const half = Math.ceil(batch.length / 2);
32066
+ return [...await readBatch(batch.slice(0, half)), ...await readBatch(batch.slice(half))];
32067
+ }
32068
+ };
32069
+ return readBatch(ids);
32013
32070
  }
32014
32071
 
32015
32072
  // ../core/src/engine.ts
@@ -32033,7 +32090,7 @@ async function readDocVersioned(backend, id) {
32033
32090
  async function scanMatching(backend, filter, onSkip) {
32034
32091
  const ids = await backend.list(filter.prefix);
32035
32092
  const results = [];
32036
- for (const result of await readManyExisting(backend, ids, onSkip)) {
32093
+ for (const result of await readManyExisting(backend, ids, onSkip, void 0, onSkip)) {
32037
32094
  if (matchesFilter(result.doc, filter)) results.push(result);
32038
32095
  }
32039
32096
  results.sort((a, b) => compareCodeUnits(a.doc.id, b.doc.id));
@@ -32158,7 +32215,7 @@ function assertStorableReservedWrite(dir, name, content3) {
32158
32215
  // ../core/src/filesystem-identity.ts
32159
32216
  import { promises as fs2 } from "node:fs";
32160
32217
  import path2 from "node:path";
32161
- import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
32218
+ import { createHash as createHash2 } from "node:crypto";
32162
32219
 
32163
32220
  // ../core/src/filesystem-lock.ts
32164
32221
  import { promises as fs, realpathSync } from "node:fs";
@@ -32213,6 +32270,8 @@ import { createHash, randomUUID } from "node:crypto";
32213
32270
  var OWNER_FILE = "owner.json";
32214
32271
  var DEFAULT_WAIT_MS = 5e3;
32215
32272
  var DEFAULT_POLL_MS = 25;
32273
+ var UNREADABLE_OWNER_POLL_MS = 2e3;
32274
+ var ABANDONED_CLAIM_AGE_MS = 2e3;
32216
32275
  var FilesystemMutationLockError = class extends Error {
32217
32276
  lockPath;
32218
32277
  owner;
@@ -32300,9 +32359,13 @@ async function readOwnerRecord(lockPath) {
32300
32359
  return owner === null ? { state: "absent" } : { state: "record", owner };
32301
32360
  }
32302
32361
  async function resolveOwnerRecord(lockPath, started, waitMs, pollMs) {
32362
+ let firstUnreadable;
32303
32363
  while (true) {
32304
32364
  const record3 = await readOwnerRecord(lockPath);
32305
- if (record3.state !== "unreadable" || Date.now() - started >= waitMs) return record3;
32365
+ if (record3.state !== "unreadable") return record3;
32366
+ const now = Date.now();
32367
+ firstUnreadable ??= now;
32368
+ if (now - started >= waitMs || now - firstUnreadable >= UNREADABLE_OWNER_POLL_MS) return record3;
32306
32369
  await delay(pollMs);
32307
32370
  }
32308
32371
  }
@@ -32353,6 +32416,17 @@ async function quarantineStaleLock(lockPath, owner, policy) {
32353
32416
  throw err;
32354
32417
  }
32355
32418
  }
32419
+ async function removeAbandonedClaim(lockPath) {
32420
+ try {
32421
+ const info = await fs.lstat(lockPath);
32422
+ const age = Date.now() - info.mtimeMs;
32423
+ if (!info.isDirectory() || age < ABANDONED_CLAIM_AGE_MS) return false;
32424
+ await fs.rmdir(lockPath);
32425
+ return true;
32426
+ } catch {
32427
+ return false;
32428
+ }
32429
+ }
32356
32430
  function delay(ms) {
32357
32431
  return new Promise((resolve) => setTimeout(resolve, ms));
32358
32432
  }
@@ -32403,7 +32477,7 @@ async function timeoutError(lockPath, snapshot, guarded) {
32403
32477
  const sameHost = owner?.hostname === hostname();
32404
32478
  let message;
32405
32479
  if (malformed) {
32406
- message = `timed out waiting for filesystem mutation lock '${lockPath}'; its owner metadata is missing or malformed. Inspect and remove the lock only after confirming no process is mutating the target, then retry.`;
32480
+ message = `timed out waiting for filesystem mutation lock '${lockPath}'; its owner metadata is missing or malformed. Remove the lock directory once no Superbee process is running, then retry.`;
32407
32481
  } else if (stale) {
32408
32482
  message = `stale filesystem mutation lock '${lockPath}' belongs to absent PID ${owner.pid} on ${owner.hostname}. Inspect and remove the lock, then retry.`;
32409
32483
  } else if (!sameHost) {
@@ -32452,7 +32526,9 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
32452
32526
  } else {
32453
32527
  unwitnessedRetryUsed = false;
32454
32528
  }
32455
- let existingOwner = await readOwner(lockPath);
32529
+ const existing = await readOwnerRecord(lockPath);
32530
+ let existingOwner = existing.state === "record" ? existing.owner : null;
32531
+ if (existing.state === "absent" && await removeAbandonedClaim(lockPath)) continue;
32456
32532
  if (existingOwner !== null) {
32457
32533
  if (await quarantineStaleLock(lockPath, existingOwner, policy)) continue;
32458
32534
  existingOwner = await readOwner(lockPath);
@@ -32472,14 +32548,13 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
32472
32548
  });
32473
32549
  } catch (err) {
32474
32550
  const code2 = err.code;
32475
- if (code2 === "EEXIST") {
32551
+ if (code2 === "EEXIST" || code2 === "ENOENT" || code2 === "ENOTDIR" || await claimDirectoryLost(lockPath, claimed)) {
32476
32552
  heldTokens.delete(owner.token);
32477
32553
  continue;
32478
32554
  }
32479
32555
  await rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy).catch(() => {
32480
32556
  });
32481
32557
  heldTokens.delete(owner.token);
32482
- if (code2 === "ENOENT" || code2 === "ENOTDIR") continue;
32483
32558
  throw err;
32484
32559
  }
32485
32560
  let inFlight;
@@ -32509,9 +32584,18 @@ async function rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy
32509
32584
  return;
32510
32585
  }
32511
32586
  if (record3.state === "unreadable" || !await isClaimedDirectory(lockPath, claimed)) return;
32512
- const remnant = releasedLockRemnantPath(lockPath, owner);
32513
- await fs.rename(lockPath, remnant);
32514
- await fs.rm(remnant, { recursive: true, force: true });
32587
+ await fs.rmdir(lockPath);
32588
+ }
32589
+ async function claimDirectoryLost(lockPath, claimed) {
32590
+ try {
32591
+ const current = await fs.lstat(lockPath, { bigint: true });
32592
+ if (claimed === null) return false;
32593
+ const reborn = claimed.birthtimeNs > 0n && current.birthtimeNs > 0n && current.birthtimeNs !== claimed.birthtimeNs;
32594
+ return current.dev !== claimed.dev || current.ino !== claimed.ino || reborn;
32595
+ } catch (err) {
32596
+ const code2 = err.code;
32597
+ return code2 === "ENOENT" || code2 === "ENOTDIR";
32598
+ }
32515
32599
  }
32516
32600
  async function isClaimedDirectory(lockPath, claimed) {
32517
32601
  if (claimed === null || claimed.birthtimeNs <= 0n) return false;
@@ -32608,9 +32692,20 @@ async function acquireFilesystemIdentityLock(key, identity, options = {}) {
32608
32692
  return claimLockPath(path.join(lockRoot, `${key}.lock`), owner, waitMs, pollMs, policy);
32609
32693
  }
32610
32694
 
32695
+ // ../core/src/path-fold.ts
32696
+ function foldPath(path6) {
32697
+ return path6.normalize("NFD").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
32698
+ }
32699
+
32611
32700
  // ../core/src/identity-fold.ts
32612
32701
  function foldSegment(segment) {
32613
- return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
32702
+ return foldPath(segment).normalize("NFD");
32703
+ }
32704
+
32705
+ // ../core/src/filesystem-temp-name.ts
32706
+ import { randomUUID as randomUUID2 } from "node:crypto";
32707
+ function identityTempName(leaf) {
32708
+ return `.${leaf}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
32614
32709
  }
32615
32710
 
32616
32711
  // ../core/src/filesystem-identity.ts
@@ -32676,7 +32771,10 @@ async function existingAnchor(resolved) {
32676
32771
  async function foldedPhysicalRoot(root) {
32677
32772
  const { anchor, tail } = await existingAnchor(path2.resolve(root));
32678
32773
  const anchorSegments = anchor.split(path2.sep).filter((segment, index2) => index2 === 0 || segment !== "");
32679
- return [...anchorSegments, ...tail].map(foldSegment).join("/");
32774
+ return [...anchorSegments, ...tail].map(foldRootSegment).join("/");
32775
+ }
32776
+ function foldRootSegment(segment) {
32777
+ return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
32680
32778
  }
32681
32779
  async function identityKey(root, rel) {
32682
32780
  const foldedRel = relSegments(rel).map(foldSegment).join("/");
@@ -32757,10 +32855,32 @@ async function probeSegment(port, candidate, rel, segment) {
32757
32855
  function hasExact(listing, segment) {
32758
32856
  return listing.some((entry) => entry.name === segment);
32759
32857
  }
32858
+ function existingSpelling(names, segment) {
32859
+ const folded = foldSegment(segment);
32860
+ const matches = [...names].filter((name) => name !== segment && foldSegment(name) === folded);
32861
+ return matches.length === 1 ? matches[0] : void 0;
32862
+ }
32863
+ function entryNoun(kind2, leaf) {
32864
+ if (kind2 === void 0) return leaf ? "file" : "folder";
32865
+ return kind2 === "directory" ? "folder" : "file";
32866
+ }
32867
+ function aliasRefusal(rel, segments, index2, names, kind2) {
32868
+ const segment = segments[index2];
32869
+ return new FilesystemIdentityAliasError(rel, segment, existingSpelling(names, segment), entryNoun(kind2, index2 === segments.length - 1), index2);
32870
+ }
32871
+ function aliasRefusalFromListing(rel, index2, listing, leaf) {
32872
+ const segment = relSegments(rel)[index2];
32873
+ const existing = existingSpelling(listing.map((entry) => entry.name), segment);
32874
+ const kind2 = existing === void 0 ? void 0 : listing.find((entry) => entry.name === existing)?.kind;
32875
+ return new FilesystemIdentityAliasError(rel, segment, existing, entryNoun(kind2, leaf), index2);
32876
+ }
32877
+ function listingView(names) {
32878
+ return { has: (name) => names.has(name), names: () => names };
32879
+ }
32760
32880
  function freshListings(port) {
32761
32881
  return async (dir) => {
32762
32882
  const listing = await port.entries(dir);
32763
- return listing === null ? null : { has: (name) => hasExact(listing, name) };
32883
+ return listing === null ? null : { has: (name) => hasExact(listing, name), names: () => listing.map((entry) => entry.name) };
32764
32884
  };
32765
32885
  }
32766
32886
  async function walkExact(port, rootResolved, segments, rel) {
@@ -32772,7 +32892,7 @@ async function walkExact(port, rootResolved, segments, rel) {
32772
32892
  if (probed === null) return { state: "absent", depth: index2 };
32773
32893
  const listing = await port.entries(parent);
32774
32894
  if (listing === null) return { state: "absent", depth: index2 };
32775
- if (!hasExact(listing, segment)) throw new FilesystemIdentityAliasError(rel, segment);
32895
+ if (!hasExact(listing, segment)) throw aliasRefusal(rel, segments, index2, listing.map((entry) => entry.name), probed.kind);
32776
32896
  if (index2 === segments.length - 1) return { state: "exact", leaf: probed };
32777
32897
  if (probed.kind !== "directory") return { state: "shape-mismatch", segment };
32778
32898
  parent = candidate;
@@ -32787,35 +32907,53 @@ async function recordWalk(port, rootResolved, segments, rel) {
32787
32907
  const segment = segments[index2];
32788
32908
  const candidate = path2.join(parent, segment);
32789
32909
  const probed = await probeSegment(port, candidate, rel, segment);
32790
- if (probed === null) return null;
32791
- if (index2 < segments.length - 1 && probed.kind !== "directory") return null;
32910
+ if (probed === null) return { recorded, complete: false };
32792
32911
  recorded.push(probed);
32912
+ if (index2 < segments.length - 1 && probed.kind !== "directory") return { recorded, complete: false };
32793
32913
  parent = candidate;
32794
32914
  }
32795
- return recorded;
32915
+ return { recorded, complete: true };
32796
32916
  }
32797
- async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port)) {
32917
+ async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port), stopAt = segments.length) {
32798
32918
  let parent = rootResolved;
32799
- for (let index2 = 0; index2 < segments.length; index2++) {
32919
+ for (let index2 = 0; index2 < stopAt; index2++) {
32800
32920
  const segment = segments[index2];
32801
32921
  const candidate = path2.join(parent, segment);
32802
32922
  const listing = await listings(parent);
32803
32923
  if (listing === null) return "absent";
32804
32924
  const listed = listing.has(segment);
32805
32925
  if (handle !== null && index2 === segments.length - 1) {
32806
- const verdict = classifyLeaf({ listed, probe: await probeSegment(port, candidate, rel, segment), handle });
32807
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
32926
+ const probe = await probeSegment(port, candidate, rel, segment);
32927
+ const verdict = classifyLeaf({ listed, probe, handle });
32928
+ if (verdict === "aliased") throw aliasRefusal(rel, segments, index2, listing.names(), probe?.kind);
32808
32929
  return verdict === "replaced" ? "restart" : verdict;
32809
32930
  }
32810
32931
  if (index2 < segments.length - 1 || !listed) {
32811
- const verdict = confirmAlias(listed, await probeSegment(port, candidate, rel, segment), recorded[index2]);
32812
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
32932
+ const probe = await probeSegment(port, candidate, rel, segment);
32933
+ const verdict = confirmAlias(listed, probe, recorded[index2]);
32934
+ if (verdict === "aliased") throw aliasRefusal(rel, segments, index2, listing.names(), probe?.kind);
32813
32935
  if (verdict !== "continue") return verdict;
32814
32936
  }
32815
32937
  parent = candidate;
32816
32938
  }
32817
32939
  return "continue";
32818
32940
  }
32941
+ async function confirmPrefix(port, rootResolved, segments, rel, recorded) {
32942
+ if (recorded.length === 0) return "absent";
32943
+ let kept = prefixListings.get(port);
32944
+ if (kept === void 0) prefixListings.set(port, kept = /* @__PURE__ */ new Map());
32945
+ const cached = witnessedListings(port, kept, Date.now, PREFIX_LISTING_CAPACITY);
32946
+ let verdict;
32947
+ try {
32948
+ verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, cached.source, recorded.length);
32949
+ } catch (error) {
32950
+ if (!cached.reused()) throw error;
32951
+ kept.clear();
32952
+ verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, freshListings(port), recorded.length);
32953
+ }
32954
+ if (verdict === "restart" && cached.reused()) kept.clear();
32955
+ return verdict === "restart" ? "restart" : "absent";
32956
+ }
32819
32957
  function countRestart(restarts, rel) {
32820
32958
  if (restarts >= MAX_RESTARTS) throw new ConcurrentReplacementError(rel, restarts + 1);
32821
32959
  return restarts + 1;
@@ -32827,8 +32965,14 @@ async function observeWith(port, rootResolved, rel, read, listings, onExact) {
32827
32965
  const segments = relSegments(rel);
32828
32966
  const target = path2.join(rootResolved, ...segments);
32829
32967
  for (let restarts = 0; ; ) {
32830
- const recorded = await recordWalk(port, rootResolved, segments, rel);
32831
- if (recorded === null) return { state: "absent" };
32968
+ const walk = await recordWalk(port, rootResolved, segments, rel);
32969
+ if (!walk.complete) {
32970
+ const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
32971
+ if (prefix === "absent") return { state: "absent" };
32972
+ restarts = countRestart(restarts, rel);
32973
+ continue;
32974
+ }
32975
+ const recorded = walk.recorded;
32832
32976
  const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, listings);
32833
32977
  if (verified === "absent") return { state: "absent" };
32834
32978
  if (verified === "restart") {
@@ -32867,8 +33011,14 @@ async function probeExact(port, root, rel) {
32867
33011
  const segments = relSegments(rel);
32868
33012
  const rootResolved = path2.resolve(root);
32869
33013
  for (let restarts = 0; ; ) {
32870
- const recorded = await recordWalk(port, rootResolved, segments, rel);
32871
- if (recorded === null) return { state: "absent" };
33014
+ const walk = await recordWalk(port, rootResolved, segments, rel);
33015
+ if (!walk.complete) {
33016
+ const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
33017
+ if (prefix === "absent") return { state: "absent" };
33018
+ restarts = countRestart(restarts, rel);
33019
+ continue;
33020
+ }
33021
+ const recorded = walk.recorded;
32872
33022
  const leaf = recorded[recorded.length - 1];
32873
33023
  const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null);
32874
33024
  const verdict = verified === "continue" ? await confirmedWalk(port, rootResolved, segments, rel, recorded, leaf) : verified;
@@ -32878,45 +33028,56 @@ async function probeExact(port, root, rel) {
32878
33028
  }
32879
33029
  }
32880
33030
  var SETTLED_AFTER_NS = 3000000000n;
33031
+ function witnessCanDetectChange(witness) {
33032
+ return witness.mtimeNs > 0n && witness.ctimeNs > 0n;
33033
+ }
32881
33034
  function witnessKey(witness) {
32882
33035
  return `${witness.dev}:${witness.ino}:${witness.mtimeNs}:${witness.ctimeNs}`;
32883
33036
  }
32884
- function openObservationPass(port, root, now = Date.now) {
32885
- const rootResolved = path2.resolve(root);
32886
- const kept = /* @__PURE__ */ new Map();
32887
- const reusedVerdicts = [];
32888
- const fresh = freshListings(port);
32889
- const witnessOf = port.directoryWitness?.bind(port);
33037
+ function witnessedListings(port, kept, now, capacity = Infinity) {
33038
+ let reused = false;
33039
+ const portWitness = port.directoryWitness?.bind(port);
33040
+ if (portWitness === void 0) return { source: freshListings(port), reused: () => false };
33041
+ const witnessOf = async (dir) => {
33042
+ const witness = await portWitness(dir);
33043
+ return witness !== null && witnessCanDetectChange(witness) ? witness : null;
33044
+ };
32890
33045
  const settled = (witness) => {
32891
33046
  const nowNs = BigInt(Math.floor(now())) * 1000000n;
32892
33047
  const latest = witness.mtimeNs > witness.ctimeNs ? witness.mtimeNs : witness.ctimeNs;
32893
33048
  return nowNs - latest >= SETTLED_AFTER_NS;
32894
33049
  };
32895
- const listingsFor = () => {
32896
- let reused = false;
32897
- if (witnessOf === void 0) return { source: fresh, reused: () => false };
32898
- const source = async (dir) => {
32899
- const keep = kept.get(dir);
32900
- if (keep !== void 0) {
32901
- const current = await witnessOf(dir);
32902
- if (current !== null && witnessKey(current) === keep.witness) {
32903
- reused = true;
32904
- return keep.names;
32905
- }
32906
- kept.delete(dir);
32907
- }
32908
- const before = await witnessOf(dir);
32909
- const listing = await port.entries(dir);
32910
- if (listing === null) return null;
32911
- const names = new Set(listing.map((entry) => entry.name));
32912
- const after = await witnessOf(dir);
32913
- if (before !== null && after !== null && witnessKey(before) === witnessKey(after) && settled(after)) {
32914
- kept.set(dir, { witness: witnessKey(after), names });
32915
- }
32916
- return names;
32917
- };
32918
- return { source, reused: () => reused };
33050
+ const source = async (dir) => {
33051
+ const keep = kept.get(dir);
33052
+ if (keep !== void 0) {
33053
+ const current = await witnessOf(dir);
33054
+ if (current !== null && witnessKey(current) === keep.witness) {
33055
+ reused = true;
33056
+ return listingView(keep.names);
33057
+ }
33058
+ kept.delete(dir);
33059
+ }
33060
+ const before = await witnessOf(dir);
33061
+ const listing = await port.entries(dir);
33062
+ if (listing === null) return null;
33063
+ const names = new Set(listing.map((entry) => entry.name));
33064
+ const after = await witnessOf(dir);
33065
+ if (before !== null && after !== null && witnessKey(before) === witnessKey(after) && settled(after)) {
33066
+ kept.delete(dir);
33067
+ kept.set(dir, { witness: witnessKey(after), names });
33068
+ while (kept.size > capacity) kept.delete(kept.keys().next().value);
33069
+ }
33070
+ return listingView(names);
32919
33071
  };
33072
+ return { source, reused: () => reused };
33073
+ }
33074
+ var prefixListings = /* @__PURE__ */ new WeakMap();
33075
+ var PREFIX_LISTING_CAPACITY = 64;
33076
+ function openObservationPass(port, root, now = Date.now) {
33077
+ const rootResolved = path2.resolve(root);
33078
+ const kept = /* @__PURE__ */ new Map();
33079
+ const reusedVerdicts = [];
33080
+ const listingsFor = () => witnessedListings(port, kept, now);
32920
33081
  return {
32921
33082
  async observe(rel, read) {
32922
33083
  const listings = listingsFor();
@@ -33019,7 +33180,7 @@ async function readWhole(port, target) {
33019
33180
  await port.close(opened.handle);
33020
33181
  }
33021
33182
  }
33022
- async function mkdirExact(port, parent, segment, isTail, rel) {
33183
+ async function mkdirExact(port, parent, segment, isTail, rel, index2 = -1) {
33023
33184
  const outcome = await port.mkdir(path2.join(parent, segment));
33024
33185
  if (outcome === "created") return;
33025
33186
  const listing = await port.entries(parent);
@@ -33028,7 +33189,9 @@ async function mkdirExact(port, parent, segment, isTail, rel) {
33028
33189
  throw new FilesystemSymlinkEntryError(rel, segment);
33029
33190
  }
33030
33191
  const verdict = classifyMkdir(outcome, listing, segment, isTail);
33031
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
33192
+ if (verdict === "aliased") {
33193
+ throw aliasRefusalFromListing(rel, index2, listing, false);
33194
+ }
33032
33195
  if (verdict === "shape-mismatch") throw new FilesystemShapeMismatchError(rel, segment);
33033
33196
  }
33034
33197
  async function ensureExactDirectories(port, rootResolved, segments, existingDepth, rel) {
@@ -33048,8 +33211,9 @@ async function ensureExactDirectories(port, rootResolved, segments, existingDept
33048
33211
  }
33049
33212
  }
33050
33213
  let parent = path2.join(rootResolved, ...segments.slice(0, existingDepth));
33051
- for (const segment of segments.slice(existingDepth, -1)) {
33052
- await mkdirExact(port, parent, segment, false, rel);
33214
+ for (let index2 = existingDepth; index2 < segments.length - 1; index2++) {
33215
+ const segment = segments[index2];
33216
+ await mkdirExact(port, parent, segment, false, rel, index2);
33053
33217
  parent = path2.join(parent, segment);
33054
33218
  }
33055
33219
  }
@@ -33067,7 +33231,7 @@ async function createExactLeaf(port, tmp, target, rel, leaf, rootResolved) {
33067
33231
  }
33068
33232
  const listing = await port.entries(path2.dirname(target)) ?? [];
33069
33233
  if (hasExact(listing, leaf)) throw new ConcurrentReplacementError(rel, 1);
33070
- throw new FilesystemIdentityAliasError(rel, leaf);
33234
+ throw aliasRefusalFromListing(rel, relSegments(rel).length - 1, listing, true);
33071
33235
  }
33072
33236
  async function mutateExact(port, root, rel, body) {
33073
33237
  const segments = relSegments(rel);
@@ -33089,11 +33253,13 @@ async function mutateExact(port, root, rel, body) {
33089
33253
  async replace(bytes) {
33090
33254
  await ensureExactDirectories(port, rootResolved, segments, existingDepth, rel);
33091
33255
  const dir = path2.dirname(target);
33092
- const tmpName = `.${leaf}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
33256
+ const tmpName = identityTempName(leaf);
33093
33257
  const tmp = path2.join(dir, tmpName);
33094
33258
  await port.writeTemp(dir, tmpName, bytes);
33095
33259
  try {
33096
33260
  if (realized.state === "exact") {
33261
+ await port.copyMode?.(target, tmp).catch(() => {
33262
+ });
33097
33263
  await replaceExistingLeaf(port, tmp, target, rel);
33098
33264
  return;
33099
33265
  }
@@ -33253,6 +33419,9 @@ function createNodeFilesystemIdentityPort(hostPolicy) {
33253
33419
  async rename(from, to) {
33254
33420
  await fs2.rename(from, to);
33255
33421
  },
33422
+ async copyMode(from, to) {
33423
+ await fs2.chmod(to, (await fs2.lstat(from)).mode & 511);
33424
+ },
33256
33425
  async unlink(target) {
33257
33426
  await fs2.unlink(target);
33258
33427
  },
@@ -33275,6 +33444,7 @@ function blobVersion(bytes) {
33275
33444
 
33276
33445
  // ../core/src/backend.ts
33277
33446
  var publicationContexts = /* @__PURE__ */ new WeakMap();
33447
+ var fileMutations = /* @__PURE__ */ new WeakMap();
33278
33448
  function firstString(...vals) {
33279
33449
  for (const v of vals) {
33280
33450
  if (typeof v === "string" && v.trim() !== "") return v;
@@ -33391,6 +33561,7 @@ var FilesystemBackend = class _FilesystemBackend {
33391
33561
  this.#root = path3.resolve(root);
33392
33562
  this.#coordinator = createFilesystemMutationCoordinator(this.#port, this.#root, options.hostPolicy);
33393
33563
  publicationContexts.set(this, { root: this.#root, port: this.#port });
33564
+ fileMutations.set(this, (rel, body) => this.#mutateExact(rel, body));
33394
33565
  }
33395
33566
  async read(id) {
33396
33567
  return this.#readWithEdition(id, () => this.#readEdition());
@@ -33776,6 +33947,7 @@ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
33776
33947
  function isKindFieldType(value) {
33777
33948
  return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
33778
33949
  }
33950
+ var UNDECLARED_FIELDS_POLICIES = ["warn", "error"];
33779
33951
  function buildKindRegistry(docs, initialWarnings = [], options = {}) {
33780
33952
  const accepted = /* @__PURE__ */ new Map();
33781
33953
  const warnings = [...initialWarnings];
@@ -34370,6 +34542,19 @@ function parseConventionDoc(doc, options = {}) {
34370
34542
  });
34371
34543
  }
34372
34544
  }
34545
+ let undeclaredFields;
34546
+ if (fm.undeclared_fields !== void 0) {
34547
+ if (UNDECLARED_FIELDS_POLICIES.includes(fm.undeclared_fields)) {
34548
+ undeclaredFields = fm.undeclared_fields;
34549
+ } else {
34550
+ warnings.push({
34551
+ code: "KIND_CONVENTION_BAD_SHAPE",
34552
+ message: `kind convention '${doc.id}' has an invalid 'undeclared_fields' (${describeShape(fm.undeclared_fields)}; expected warn or error); using warn.`,
34553
+ field: "undeclared_fields",
34554
+ severity: "warning"
34555
+ });
34556
+ }
34557
+ }
34373
34558
  const kind2 = {
34374
34559
  id: doc.id,
34375
34560
  title,
@@ -34387,6 +34572,7 @@ function parseConventionDoc(doc, options = {}) {
34387
34572
  if (browseCollapsed !== void 0) kind2.browseCollapsed = browseCollapsed;
34388
34573
  if (order !== void 0) kind2.order = order;
34389
34574
  if (claim !== void 0) kind2.claim = claim;
34575
+ if (undeclaredFields !== void 0) kind2.undeclaredFields = undeclaredFields;
34390
34576
  if (Object.hasOwn(fm, "deprecated")) {
34391
34577
  kind2.deprecated = parseKindDeprecation(fm.deprecated, kind2, RESERVED_KIND_FIELD_NAMES, claimCoordinates(options.okfVersion, kind2)?.fields ?? []);
34392
34578
  warnings.push(...kind2.deprecated.problems ?? []);
@@ -34423,58 +34609,6 @@ function isTerminal(kind2, frontmatter2) {
34423
34609
  return false;
34424
34610
  }
34425
34611
 
34426
- // ../core/src/query-selection.ts
34427
- function applyQuerySelectionFilters(rows, params, kinds = []) {
34428
- let out = rows;
34429
- const byGoverns = new Map(kinds.map((kind2) => [kind2.governs, kind2]));
34430
- if (params.field) {
34431
- const eq = params.field.indexOf("=");
34432
- if (eq > 0) {
34433
- const key = params.field.slice(0, eq).trim();
34434
- const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
34435
- out = out.filter((row) => {
34436
- if (key !== PROGRESS_STATUS_FIELD) {
34437
- return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
34438
- }
34439
- const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
34440
- if (!kind2) return false;
34441
- const raw = readKindField(params.okfVersion, kind2, row.frontmatter, key);
34442
- const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
34443
- return values.some((value) => actual.includes(value));
34444
- });
34445
- }
34446
- }
34447
- if (params.open) {
34448
- out = out.filter((row) => {
34449
- const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
34450
- return !kind2 || !isTerminal(kind2, row.frontmatter);
34451
- });
34452
- }
34453
- const count = out.length;
34454
- if (typeof params.limit === "number" && params.limit > 0) {
34455
- out = out.slice(0, params.limit);
34456
- }
34457
- return { rows: out, count };
34458
- }
34459
-
34460
- // ../core/src/kinds-load.ts
34461
- async function loadKinds(bundle) {
34462
- const warnings = [];
34463
- const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
34464
- onSkip: ({ id, reason }) => warnings.push({
34465
- code: "KIND_CONVENTION_MALFORMED",
34466
- message: `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
34467
- field: id,
34468
- severity: "warning"
34469
- })
34470
- });
34471
- const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
34472
- if (!(error instanceof MalformedDocumentError)) throw error;
34473
- return void 0;
34474
- });
34475
- return buildKindRegistry(docs, warnings, { okfVersion });
34476
- }
34477
-
34478
34612
  // ../core/src/page.ts
34479
34613
  var PAGE_REGISTRY_PREFIX = "pages-registry/";
34480
34614
  var PAGE_ENTRY_PREFIX = "pages/";
@@ -34556,6 +34690,58 @@ function parseRegistration(id, frontmatter2) {
34556
34690
  };
34557
34691
  }
34558
34692
 
34693
+ // ../core/src/query-selection.ts
34694
+ function applyQuerySelectionFilters(rows, params, kinds = []) {
34695
+ let out = rows;
34696
+ const byGoverns = new Map(kinds.map((kind2) => [kind2.governs, kind2]));
34697
+ if (params.field) {
34698
+ const eq = params.field.indexOf("=");
34699
+ if (eq > 0) {
34700
+ const key = params.field.slice(0, eq).trim();
34701
+ const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
34702
+ out = out.filter((row) => {
34703
+ if (key !== PROGRESS_STATUS_FIELD) {
34704
+ return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
34705
+ }
34706
+ const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
34707
+ if (!kind2) return false;
34708
+ const raw = readKindField(params.okfVersion, kind2, row.frontmatter, key);
34709
+ const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
34710
+ return values.some((value) => actual.includes(value));
34711
+ });
34712
+ }
34713
+ }
34714
+ if (params.open) {
34715
+ out = out.filter((row) => {
34716
+ const kind2 = byGoverns.get(String(row.frontmatter.type ?? ""));
34717
+ return !kind2 || !isTerminal(kind2, row.frontmatter);
34718
+ });
34719
+ }
34720
+ const count = out.length;
34721
+ if (typeof params.limit === "number" && params.limit > 0) {
34722
+ out = out.slice(0, params.limit);
34723
+ }
34724
+ return { rows: out, count };
34725
+ }
34726
+
34727
+ // ../core/src/kinds-load.ts
34728
+ async function loadKinds(bundle) {
34729
+ const warnings = [];
34730
+ const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
34731
+ onSkip: ({ id, reason }) => warnings.push({
34732
+ code: "KIND_CONVENTION_MALFORMED",
34733
+ message: isPermissionDeniedSkip({ reason }) ? `skipped kind convention '${id}' that could not be read: ${reason}` : `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
34734
+ field: id,
34735
+ severity: "warning"
34736
+ })
34737
+ });
34738
+ const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
34739
+ if (!(error instanceof MalformedDocumentError)) throw error;
34740
+ return void 0;
34741
+ });
34742
+ return buildKindRegistry(docs, warnings, { okfVersion });
34743
+ }
34744
+
34559
34745
  // ../markdown-renderer/src/static.tsx
34560
34746
  var import_server = __toESM(require_server_node(), 1);
34561
34747
 
@@ -44601,12 +44787,27 @@ var CAPABILITIES = [
44601
44787
  ];
44602
44788
  async function authorizePublicationRoot(requested) {
44603
44789
  const entry = await lstat(requested);
44604
- if (entry.isSymbolicLink() || !entry.isDirectory()) {
44790
+ if (entry.isSymbolicLink()) {
44791
+ const target = await realpath(requested).catch(() => void 0);
44792
+ if (target === void 0) {
44793
+ throw new PublicationError("INVALID_OBJECT_IDENTITY", `the filesystem publication root ${JSON.stringify(requested)} is a symlink that does not resolve to a directory`, { actual: requested });
44794
+ }
44795
+ throw new PublicationError(
44796
+ "INVALID_OBJECT_IDENTITY",
44797
+ `the filesystem publication root ${JSON.stringify(requested)} is a symlink to ${JSON.stringify(target)}; capture does not follow symlinks, so pass the resolved path (await fs.realpath(root))`,
44798
+ { expected: target, actual: requested }
44799
+ );
44800
+ }
44801
+ if (!entry.isDirectory()) {
44605
44802
  throw new PublicationError("INVALID_OBJECT_IDENTITY", "the filesystem publication root must be a real directory");
44606
44803
  }
44607
44804
  const canonical2 = await realpath(requested);
44608
44805
  if (canonical2 !== requested) {
44609
- throw new PublicationError("INVALID_OBJECT_IDENTITY", "the filesystem publication root must not be a symlink or aliased path");
44806
+ throw new PublicationError(
44807
+ "INVALID_OBJECT_IDENTITY",
44808
+ `the filesystem publication root ${JSON.stringify(requested)} is not in canonical form (it resolves to ${JSON.stringify(canonical2)}); capture does not follow symlinks or normalize paths, so pass the resolved path (await fs.realpath(root))`,
44809
+ { expected: canonical2, actual: requested }
44810
+ );
44610
44811
  }
44611
44812
  const identity = await stat(requested);
44612
44813
  return { requested, canonical: canonical2, dev: identity.dev, ino: identity.ino };