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.
@@ -2890,15 +2890,30 @@ var FrontmatterRefusedError = class extends InvalidInputError {
2890
2890
  }
2891
2891
  };
2892
2892
  var FilesystemIdentityAliasError = class extends InvalidInputError {
2893
+ reason = "filesystem_alias";
2893
2894
  rel;
2894
2895
  segment;
2895
- constructor(rel, segment) {
2896
+ existing;
2897
+ suggestedPath;
2898
+ /**
2899
+ * `noun` names the existing entry ("folder" or "file"); `index` is the position of `segment`
2900
+ * in `rel`. Both default from the position of the first segment spelled `segment`.
2901
+ */
2902
+ constructor(rel, segment, existing, noun, index) {
2903
+ const segments = rel.split("/").filter((part) => part !== "" && part !== ".");
2904
+ const at = index ?? segments.indexOf(segment);
2905
+ const kind = noun ?? (at === segments.length - 1 ? "file" : "folder");
2906
+ const clash = existing === void 0 ? `but a ${kind} with that name in a different case or Unicode form already exists` : existing.normalize("NFC") === segment.normalize("NFC") ? `but ${kind} '${existing}' already exists, written in a different Unicode form` : `but ${kind} '${existing}' already exists`;
2907
+ 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";
2896
2908
  super(
2897
- `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.`
2909
+ `Path '${rel}' uses ${kind} '${segment}', ${clash}, and this disk treats names that differ only by ${difference} as the same name. Use the existing spelling.`
2898
2910
  );
2899
2911
  this.name = "FilesystemIdentityAliasError";
2900
2912
  this.rel = rel;
2901
2913
  this.segment = segment;
2914
+ this.existing = existing;
2915
+ const unusable = existing === void 0 || at < 0 || segments[at] !== segment || kind === "file" && at < segments.length - 1 || existing.normalize("NFC") === segment.normalize("NFC");
2916
+ this.suggestedPath = unusable ? void 0 : segments.map((part, position) => position === at ? existing : part).join("/");
2902
2917
  }
2903
2918
  };
2904
2919
  var ConcurrentReplacementError = class extends Error {
@@ -3103,6 +3118,9 @@ function delimiterLineEnd(input, offset) {
3103
3118
  if (input[suffix] === "\r" && input[suffix + 1] === "\n") return suffix + 2;
3104
3119
  return null;
3105
3120
  }
3121
+ function startsWithFrontmatterSyntax(text) {
3122
+ return text.startsWith("\uFEFF") || delimiterLineEnd(text, 0) !== null;
3123
+ }
3106
3124
  function splitLeadingFrontmatter(raw, context) {
3107
3125
  const input = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
3108
3126
  const openingEnd = delimiterLineEnd(input, 0);
@@ -3208,7 +3226,10 @@ function stringifyWithSerializedFrontmatter(dumped, body) {
3208
3226
  const content = body ?? "";
3209
3227
  const newline = (value) => value.endsWith("\n") ? value : `${value}
3210
3228
  `;
3211
- if (dumped === "{}") return normalizeDocumentBodyForStorage(content);
3229
+ if (dumped === "{}") {
3230
+ const stored = normalizeDocumentBodyForStorage(content);
3231
+ return `${startsWithFrontmatterSyntax(stored) ? "---\n---\n" : ""}${stored}`;
3232
+ }
3212
3233
  return `---
3213
3234
  ${newline(dumped)}---
3214
3235
  ${normalizeDocumentBodyForStorage(content)}`;
@@ -3644,6 +3665,8 @@ function extractMarkdownLinkSpans(source, options = {}) {
3644
3665
  const body = options.skipCode ? maskMarkdownCode(source) : source;
3645
3666
  const out = [];
3646
3667
  let textOpen = -1;
3668
+ let codeOpen = -1;
3669
+ let masked;
3647
3670
  let afterClose;
3648
3671
  let hrefFirst;
3649
3672
  let hrefRest;
@@ -3662,6 +3685,7 @@ function extractMarkdownLinkSpans(source, options = {}) {
3662
3685
  image
3663
3686
  });
3664
3687
  textOpen = -1;
3688
+ codeOpen = -1;
3665
3689
  afterClose = void 0;
3666
3690
  hrefFirst = void 0;
3667
3691
  hrefRest = void 0;
@@ -3682,10 +3706,22 @@ function extractMarkdownLinkSpans(source, options = {}) {
3682
3706
  afterClose = void 0;
3683
3707
  }
3684
3708
  if (textOpen >= 0 && char === "]") {
3685
- afterClose = { open: textOpen, close: cursor };
3709
+ const open = codeOpen >= 0 && masked[cursor] !== "]" ? codeOpen : textOpen;
3710
+ afterClose = { open, close: cursor };
3686
3711
  textOpen = -1;
3712
+ codeOpen = -1;
3713
+ }
3714
+ if (char === "[") {
3715
+ if (textOpen >= 0 && !options.skipCode) {
3716
+ masked ??= maskMarkdownCode(source);
3717
+ if (masked[cursor] !== "[" && masked[textOpen] === "[") {
3718
+ codeOpen = cursor;
3719
+ continue;
3720
+ }
3721
+ }
3722
+ textOpen = cursor;
3723
+ codeOpen = -1;
3687
3724
  }
3688
- if (char === "[" && textOpen < 0) textOpen = cursor;
3689
3725
  }
3690
3726
  return out;
3691
3727
  }
@@ -4019,36 +4055,57 @@ function hasSourceIdentity(sources, identity) {
4019
4055
  return Array.isArray(sources) && sources.some((entry) => matchesSourceIdentity(entry, identity));
4020
4056
  }
4021
4057
 
4058
+ // ../core/src/skip-reasons.ts
4059
+ var PERMISSION_DENIED_PREFIX = "permission denied (";
4060
+ function permissionDeniedReason(code) {
4061
+ return `${PERMISSION_DENIED_PREFIX}${code})`;
4062
+ }
4063
+ function isPermissionDeniedSkip(skip) {
4064
+ return skip.reason.startsWith(PERMISSION_DENIED_PREFIX);
4065
+ }
4066
+
4022
4067
  // ../core/src/document-scan.ts
4023
4068
  function isEnoent(err) {
4024
4069
  return typeof err === "object" && err !== null && err.code === "ENOENT";
4025
4070
  }
4026
- async function readManyExisting(backend, ids, onMalformed, onAliased) {
4027
- try {
4028
- return await backend.readMany(ids);
4029
- } catch (err) {
4030
- const malformed = err instanceof MalformedDocumentError && onMalformed !== void 0;
4031
- const aliased = err instanceof FilesystemIdentityAliasError && onAliased !== void 0;
4032
- if (!isEnoent(err) && !malformed && !aliased) throw err;
4033
- const out = [];
4034
- for (const id of ids) {
4035
- try {
4036
- out.push(await backend.read(id));
4037
- } catch (candidate) {
4038
- if (isEnoent(candidate)) continue;
4039
- if (candidate instanceof MalformedDocumentError && onMalformed) {
4040
- onMalformed({ id, reason: candidate.detail });
4041
- continue;
4042
- }
4043
- if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
4044
- onAliased({ id, reason: candidate.message });
4045
- continue;
4046
- }
4047
- throw candidate;
4071
+ function deniedReason(err) {
4072
+ const code = typeof err === "object" && err !== null ? err.code : void 0;
4073
+ return code === "EACCES" || code === "EPERM" ? permissionDeniedReason(code) : void 0;
4074
+ }
4075
+ async function readManyExisting(backend, ids, onMalformed, onAliased, onDenied) {
4076
+ const tolerated = (err) => isEnoent(err) || err instanceof MalformedDocumentError && onMalformed !== void 0 || err instanceof FilesystemIdentityAliasError && onAliased !== void 0 || deniedReason(err) !== void 0 && onDenied !== void 0;
4077
+ const readOne = async (id) => {
4078
+ try {
4079
+ return [await backend.read(id)];
4080
+ } catch (candidate) {
4081
+ if (isEnoent(candidate)) return [];
4082
+ if (candidate instanceof MalformedDocumentError && onMalformed) {
4083
+ onMalformed({ id, reason: candidate.detail });
4084
+ return [];
4048
4085
  }
4086
+ if (candidate instanceof FilesystemIdentityAliasError && onAliased) {
4087
+ onAliased({ id, reason: candidate.message });
4088
+ return [];
4089
+ }
4090
+ const reason = deniedReason(candidate);
4091
+ if (reason !== void 0 && onDenied) {
4092
+ onDenied({ id, reason });
4093
+ return [];
4094
+ }
4095
+ throw candidate;
4049
4096
  }
4050
- return out;
4051
- }
4097
+ };
4098
+ const readBatch = async (batch) => {
4099
+ try {
4100
+ return await backend.readMany(batch);
4101
+ } catch (err) {
4102
+ if (!tolerated(err)) throw err;
4103
+ if (batch.length === 1) return readOne(batch[0]);
4104
+ const half = Math.ceil(batch.length / 2);
4105
+ return [...await readBatch(batch.slice(0, half)), ...await readBatch(batch.slice(half))];
4106
+ }
4107
+ };
4108
+ return readBatch(ids);
4052
4109
  }
4053
4110
 
4054
4111
  // ../core/src/engine.ts
@@ -4072,7 +4129,7 @@ async function readDocVersioned(backend, id) {
4072
4129
  async function scanMatching(backend, filter, onSkip) {
4073
4130
  const ids = await backend.list(filter.prefix);
4074
4131
  const results = [];
4075
- for (const result of await readManyExisting(backend, ids, onSkip)) {
4132
+ for (const result of await readManyExisting(backend, ids, onSkip, void 0, onSkip)) {
4076
4133
  if (matchesFilter(result.doc, filter)) results.push(result);
4077
4134
  }
4078
4135
  results.sort((a, b) => compareCodeUnits(a.doc.id, b.doc.id));
@@ -4197,7 +4254,7 @@ function assertStorableReservedWrite(dir, name, content) {
4197
4254
  // ../core/src/filesystem-identity.ts
4198
4255
  import { promises as fs2 } from "node:fs";
4199
4256
  import path2 from "node:path";
4200
- import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
4257
+ import { createHash as createHash2 } from "node:crypto";
4201
4258
 
4202
4259
  // ../core/src/filesystem-lock.ts
4203
4260
  import { promises as fs, realpathSync } from "node:fs";
@@ -4252,6 +4309,8 @@ import { createHash, randomUUID } from "node:crypto";
4252
4309
  var OWNER_FILE = "owner.json";
4253
4310
  var DEFAULT_WAIT_MS = 5e3;
4254
4311
  var DEFAULT_POLL_MS = 25;
4312
+ var UNREADABLE_OWNER_POLL_MS = 2e3;
4313
+ var ABANDONED_CLAIM_AGE_MS = 2e3;
4255
4314
  var FilesystemMutationLockError = class extends Error {
4256
4315
  lockPath;
4257
4316
  owner;
@@ -4339,9 +4398,13 @@ async function readOwnerRecord(lockPath) {
4339
4398
  return owner === null ? { state: "absent" } : { state: "record", owner };
4340
4399
  }
4341
4400
  async function resolveOwnerRecord(lockPath, started, waitMs, pollMs) {
4401
+ let firstUnreadable;
4342
4402
  while (true) {
4343
4403
  const record2 = await readOwnerRecord(lockPath);
4344
- if (record2.state !== "unreadable" || Date.now() - started >= waitMs) return record2;
4404
+ if (record2.state !== "unreadable") return record2;
4405
+ const now = Date.now();
4406
+ firstUnreadable ??= now;
4407
+ if (now - started >= waitMs || now - firstUnreadable >= UNREADABLE_OWNER_POLL_MS) return record2;
4345
4408
  await delay(pollMs);
4346
4409
  }
4347
4410
  }
@@ -4392,6 +4455,17 @@ async function quarantineStaleLock(lockPath, owner, policy) {
4392
4455
  throw err;
4393
4456
  }
4394
4457
  }
4458
+ async function removeAbandonedClaim(lockPath) {
4459
+ try {
4460
+ const info = await fs.lstat(lockPath);
4461
+ const age = Date.now() - info.mtimeMs;
4462
+ if (!info.isDirectory() || age < ABANDONED_CLAIM_AGE_MS) return false;
4463
+ await fs.rmdir(lockPath);
4464
+ return true;
4465
+ } catch {
4466
+ return false;
4467
+ }
4468
+ }
4395
4469
  function delay(ms) {
4396
4470
  return new Promise((resolve) => setTimeout(resolve, ms));
4397
4471
  }
@@ -4442,7 +4516,7 @@ async function timeoutError(lockPath, snapshot, guarded) {
4442
4516
  const sameHost = owner?.hostname === hostname();
4443
4517
  let message;
4444
4518
  if (malformed) {
4445
- 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.`;
4519
+ 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.`;
4446
4520
  } else if (stale) {
4447
4521
  message = `stale filesystem mutation lock '${lockPath}' belongs to absent PID ${owner.pid} on ${owner.hostname}. Inspect and remove the lock, then retry.`;
4448
4522
  } else if (!sameHost) {
@@ -4491,7 +4565,9 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
4491
4565
  } else {
4492
4566
  unwitnessedRetryUsed = false;
4493
4567
  }
4494
- let existingOwner = await readOwner(lockPath);
4568
+ const existing = await readOwnerRecord(lockPath);
4569
+ let existingOwner = existing.state === "record" ? existing.owner : null;
4570
+ if (existing.state === "absent" && await removeAbandonedClaim(lockPath)) continue;
4495
4571
  if (existingOwner !== null) {
4496
4572
  if (await quarantineStaleLock(lockPath, existingOwner, policy)) continue;
4497
4573
  existingOwner = await readOwner(lockPath);
@@ -4511,14 +4587,13 @@ async function claimLockPath(lockPath, owner, waitMs, pollMs, policy) {
4511
4587
  });
4512
4588
  } catch (err) {
4513
4589
  const code = err.code;
4514
- if (code === "EEXIST") {
4590
+ if (code === "EEXIST" || code === "ENOENT" || code === "ENOTDIR" || await claimDirectoryLost(lockPath, claimed)) {
4515
4591
  heldTokens.delete(owner.token);
4516
4592
  continue;
4517
4593
  }
4518
4594
  await rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy).catch(() => {
4519
4595
  });
4520
4596
  heldTokens.delete(owner.token);
4521
- if (code === "ENOENT" || code === "ENOTDIR") continue;
4522
4597
  throw err;
4523
4598
  }
4524
4599
  let inFlight;
@@ -4548,9 +4623,18 @@ async function rollBackOwnClaim(lockPath, owner, claimed, waitMs, pollMs, policy
4548
4623
  return;
4549
4624
  }
4550
4625
  if (record2.state === "unreadable" || !await isClaimedDirectory(lockPath, claimed)) return;
4551
- const remnant = releasedLockRemnantPath(lockPath, owner);
4552
- await fs.rename(lockPath, remnant);
4553
- await fs.rm(remnant, { recursive: true, force: true });
4626
+ await fs.rmdir(lockPath);
4627
+ }
4628
+ async function claimDirectoryLost(lockPath, claimed) {
4629
+ try {
4630
+ const current = await fs.lstat(lockPath, { bigint: true });
4631
+ if (claimed === null) return false;
4632
+ const reborn = claimed.birthtimeNs > 0n && current.birthtimeNs > 0n && current.birthtimeNs !== claimed.birthtimeNs;
4633
+ return current.dev !== claimed.dev || current.ino !== claimed.ino || reborn;
4634
+ } catch (err) {
4635
+ const code = err.code;
4636
+ return code === "ENOENT" || code === "ENOTDIR";
4637
+ }
4554
4638
  }
4555
4639
  async function isClaimedDirectory(lockPath, claimed) {
4556
4640
  if (claimed === null || claimed.birthtimeNs <= 0n) return false;
@@ -4647,9 +4731,20 @@ async function acquireFilesystemIdentityLock(key, identity, options = {}) {
4647
4731
  return claimLockPath(path.join(lockRoot, `${key}.lock`), owner, waitMs, pollMs, policy);
4648
4732
  }
4649
4733
 
4734
+ // ../core/src/path-fold.ts
4735
+ function foldPath(path4) {
4736
+ return path4.normalize("NFD").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
4737
+ }
4738
+
4650
4739
  // ../core/src/identity-fold.ts
4651
4740
  function foldSegment(segment) {
4652
- return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
4741
+ return foldPath(segment).normalize("NFD");
4742
+ }
4743
+
4744
+ // ../core/src/filesystem-temp-name.ts
4745
+ import { randomUUID as randomUUID2 } from "node:crypto";
4746
+ function identityTempName(leaf) {
4747
+ return `.${leaf}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
4653
4748
  }
4654
4749
 
4655
4750
  // ../core/src/filesystem-identity.ts
@@ -4715,7 +4810,10 @@ async function existingAnchor(resolved) {
4715
4810
  async function foldedPhysicalRoot(root) {
4716
4811
  const { anchor, tail } = await existingAnchor(path2.resolve(root));
4717
4812
  const anchorSegments = anchor.split(path2.sep).filter((segment, index) => index === 0 || segment !== "");
4718
- return [...anchorSegments, ...tail].map(foldSegment).join("/");
4813
+ return [...anchorSegments, ...tail].map(foldRootSegment).join("/");
4814
+ }
4815
+ function foldRootSegment(segment) {
4816
+ return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
4719
4817
  }
4720
4818
  async function identityKey(root, rel) {
4721
4819
  const foldedRel = relSegments(rel).map(foldSegment).join("/");
@@ -4796,10 +4894,32 @@ async function probeSegment(port, candidate, rel, segment) {
4796
4894
  function hasExact(listing, segment) {
4797
4895
  return listing.some((entry) => entry.name === segment);
4798
4896
  }
4897
+ function existingSpelling(names, segment) {
4898
+ const folded = foldSegment(segment);
4899
+ const matches = [...names].filter((name) => name !== segment && foldSegment(name) === folded);
4900
+ return matches.length === 1 ? matches[0] : void 0;
4901
+ }
4902
+ function entryNoun(kind, leaf) {
4903
+ if (kind === void 0) return leaf ? "file" : "folder";
4904
+ return kind === "directory" ? "folder" : "file";
4905
+ }
4906
+ function aliasRefusal(rel, segments, index, names, kind) {
4907
+ const segment = segments[index];
4908
+ return new FilesystemIdentityAliasError(rel, segment, existingSpelling(names, segment), entryNoun(kind, index === segments.length - 1), index);
4909
+ }
4910
+ function aliasRefusalFromListing(rel, index, listing, leaf) {
4911
+ const segment = relSegments(rel)[index];
4912
+ const existing = existingSpelling(listing.map((entry) => entry.name), segment);
4913
+ const kind = existing === void 0 ? void 0 : listing.find((entry) => entry.name === existing)?.kind;
4914
+ return new FilesystemIdentityAliasError(rel, segment, existing, entryNoun(kind, leaf), index);
4915
+ }
4916
+ function listingView(names) {
4917
+ return { has: (name) => names.has(name), names: () => names };
4918
+ }
4799
4919
  function freshListings(port) {
4800
4920
  return async (dir) => {
4801
4921
  const listing = await port.entries(dir);
4802
- return listing === null ? null : { has: (name) => hasExact(listing, name) };
4922
+ return listing === null ? null : { has: (name) => hasExact(listing, name), names: () => listing.map((entry) => entry.name) };
4803
4923
  };
4804
4924
  }
4805
4925
  async function walkExact(port, rootResolved, segments, rel) {
@@ -4811,7 +4931,7 @@ async function walkExact(port, rootResolved, segments, rel) {
4811
4931
  if (probed === null) return { state: "absent", depth: index };
4812
4932
  const listing = await port.entries(parent);
4813
4933
  if (listing === null) return { state: "absent", depth: index };
4814
- if (!hasExact(listing, segment)) throw new FilesystemIdentityAliasError(rel, segment);
4934
+ if (!hasExact(listing, segment)) throw aliasRefusal(rel, segments, index, listing.map((entry) => entry.name), probed.kind);
4815
4935
  if (index === segments.length - 1) return { state: "exact", leaf: probed };
4816
4936
  if (probed.kind !== "directory") return { state: "shape-mismatch", segment };
4817
4937
  parent = candidate;
@@ -4826,35 +4946,53 @@ async function recordWalk(port, rootResolved, segments, rel) {
4826
4946
  const segment = segments[index];
4827
4947
  const candidate = path2.join(parent, segment);
4828
4948
  const probed = await probeSegment(port, candidate, rel, segment);
4829
- if (probed === null) return null;
4830
- if (index < segments.length - 1 && probed.kind !== "directory") return null;
4949
+ if (probed === null) return { recorded, complete: false };
4831
4950
  recorded.push(probed);
4951
+ if (index < segments.length - 1 && probed.kind !== "directory") return { recorded, complete: false };
4832
4952
  parent = candidate;
4833
4953
  }
4834
- return recorded;
4954
+ return { recorded, complete: true };
4835
4955
  }
4836
- async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port)) {
4956
+ async function confirmedWalk(port, rootResolved, segments, rel, recorded, handle, listings = freshListings(port), stopAt = segments.length) {
4837
4957
  let parent = rootResolved;
4838
- for (let index = 0; index < segments.length; index++) {
4958
+ for (let index = 0; index < stopAt; index++) {
4839
4959
  const segment = segments[index];
4840
4960
  const candidate = path2.join(parent, segment);
4841
4961
  const listing = await listings(parent);
4842
4962
  if (listing === null) return "absent";
4843
4963
  const listed = listing.has(segment);
4844
4964
  if (handle !== null && index === segments.length - 1) {
4845
- const verdict = classifyLeaf({ listed, probe: await probeSegment(port, candidate, rel, segment), handle });
4846
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
4965
+ const probe = await probeSegment(port, candidate, rel, segment);
4966
+ const verdict = classifyLeaf({ listed, probe, handle });
4967
+ if (verdict === "aliased") throw aliasRefusal(rel, segments, index, listing.names(), probe?.kind);
4847
4968
  return verdict === "replaced" ? "restart" : verdict;
4848
4969
  }
4849
4970
  if (index < segments.length - 1 || !listed) {
4850
- const verdict = confirmAlias(listed, await probeSegment(port, candidate, rel, segment), recorded[index]);
4851
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
4971
+ const probe = await probeSegment(port, candidate, rel, segment);
4972
+ const verdict = confirmAlias(listed, probe, recorded[index]);
4973
+ if (verdict === "aliased") throw aliasRefusal(rel, segments, index, listing.names(), probe?.kind);
4852
4974
  if (verdict !== "continue") return verdict;
4853
4975
  }
4854
4976
  parent = candidate;
4855
4977
  }
4856
4978
  return "continue";
4857
4979
  }
4980
+ async function confirmPrefix(port, rootResolved, segments, rel, recorded) {
4981
+ if (recorded.length === 0) return "absent";
4982
+ let kept = prefixListings.get(port);
4983
+ if (kept === void 0) prefixListings.set(port, kept = /* @__PURE__ */ new Map());
4984
+ const cached = witnessedListings(port, kept, Date.now, PREFIX_LISTING_CAPACITY);
4985
+ let verdict;
4986
+ try {
4987
+ verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, cached.source, recorded.length);
4988
+ } catch (error) {
4989
+ if (!cached.reused()) throw error;
4990
+ kept.clear();
4991
+ verdict = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, freshListings(port), recorded.length);
4992
+ }
4993
+ if (verdict === "restart" && cached.reused()) kept.clear();
4994
+ return verdict === "restart" ? "restart" : "absent";
4995
+ }
4858
4996
  function countRestart(restarts, rel) {
4859
4997
  if (restarts >= MAX_RESTARTS) throw new ConcurrentReplacementError(rel, restarts + 1);
4860
4998
  return restarts + 1;
@@ -4866,8 +5004,14 @@ async function observeWith(port, rootResolved, rel, read, listings, onExact) {
4866
5004
  const segments = relSegments(rel);
4867
5005
  const target = path2.join(rootResolved, ...segments);
4868
5006
  for (let restarts = 0; ; ) {
4869
- const recorded = await recordWalk(port, rootResolved, segments, rel);
4870
- if (recorded === null) return { state: "absent" };
5007
+ const walk = await recordWalk(port, rootResolved, segments, rel);
5008
+ if (!walk.complete) {
5009
+ const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
5010
+ if (prefix === "absent") return { state: "absent" };
5011
+ restarts = countRestart(restarts, rel);
5012
+ continue;
5013
+ }
5014
+ const recorded = walk.recorded;
4871
5015
  const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null, listings);
4872
5016
  if (verified === "absent") return { state: "absent" };
4873
5017
  if (verified === "restart") {
@@ -4906,8 +5050,14 @@ async function probeExact(port, root, rel) {
4906
5050
  const segments = relSegments(rel);
4907
5051
  const rootResolved = path2.resolve(root);
4908
5052
  for (let restarts = 0; ; ) {
4909
- const recorded = await recordWalk(port, rootResolved, segments, rel);
4910
- if (recorded === null) return { state: "absent" };
5053
+ const walk = await recordWalk(port, rootResolved, segments, rel);
5054
+ if (!walk.complete) {
5055
+ const prefix = await confirmPrefix(port, rootResolved, segments, rel, walk.recorded);
5056
+ if (prefix === "absent") return { state: "absent" };
5057
+ restarts = countRestart(restarts, rel);
5058
+ continue;
5059
+ }
5060
+ const recorded = walk.recorded;
4911
5061
  const leaf = recorded[recorded.length - 1];
4912
5062
  const verified = await confirmedWalk(port, rootResolved, segments, rel, recorded, null);
4913
5063
  const verdict = verified === "continue" ? await confirmedWalk(port, rootResolved, segments, rel, recorded, leaf) : verified;
@@ -4917,45 +5067,56 @@ async function probeExact(port, root, rel) {
4917
5067
  }
4918
5068
  }
4919
5069
  var SETTLED_AFTER_NS = 3000000000n;
5070
+ function witnessCanDetectChange(witness) {
5071
+ return witness.mtimeNs > 0n && witness.ctimeNs > 0n;
5072
+ }
4920
5073
  function witnessKey(witness) {
4921
5074
  return `${witness.dev}:${witness.ino}:${witness.mtimeNs}:${witness.ctimeNs}`;
4922
5075
  }
4923
- function openObservationPass(port, root, now = Date.now) {
4924
- const rootResolved = path2.resolve(root);
4925
- const kept = /* @__PURE__ */ new Map();
4926
- const reusedVerdicts = [];
4927
- const fresh = freshListings(port);
4928
- const witnessOf = port.directoryWitness?.bind(port);
5076
+ function witnessedListings(port, kept, now, capacity = Infinity) {
5077
+ let reused = false;
5078
+ const portWitness = port.directoryWitness?.bind(port);
5079
+ if (portWitness === void 0) return { source: freshListings(port), reused: () => false };
5080
+ const witnessOf = async (dir) => {
5081
+ const witness = await portWitness(dir);
5082
+ return witness !== null && witnessCanDetectChange(witness) ? witness : null;
5083
+ };
4929
5084
  const settled = (witness) => {
4930
5085
  const nowNs = BigInt(Math.floor(now())) * 1000000n;
4931
5086
  const latest = witness.mtimeNs > witness.ctimeNs ? witness.mtimeNs : witness.ctimeNs;
4932
5087
  return nowNs - latest >= SETTLED_AFTER_NS;
4933
5088
  };
4934
- const listingsFor = () => {
4935
- let reused = false;
4936
- if (witnessOf === void 0) return { source: fresh, reused: () => false };
4937
- const source = async (dir) => {
4938
- const keep = kept.get(dir);
4939
- if (keep !== void 0) {
4940
- const current = await witnessOf(dir);
4941
- if (current !== null && witnessKey(current) === keep.witness) {
4942
- reused = true;
4943
- return keep.names;
4944
- }
4945
- kept.delete(dir);
4946
- }
4947
- const before = await witnessOf(dir);
4948
- const listing = await port.entries(dir);
4949
- if (listing === null) return null;
4950
- const names = new Set(listing.map((entry) => entry.name));
4951
- const after = await witnessOf(dir);
4952
- if (before !== null && after !== null && witnessKey(before) === witnessKey(after) && settled(after)) {
4953
- kept.set(dir, { witness: witnessKey(after), names });
4954
- }
4955
- return names;
4956
- };
4957
- return { source, reused: () => reused };
5089
+ const source = async (dir) => {
5090
+ const keep = kept.get(dir);
5091
+ if (keep !== void 0) {
5092
+ const current = await witnessOf(dir);
5093
+ if (current !== null && witnessKey(current) === keep.witness) {
5094
+ reused = true;
5095
+ return listingView(keep.names);
5096
+ }
5097
+ kept.delete(dir);
5098
+ }
5099
+ const before = await witnessOf(dir);
5100
+ const listing = await port.entries(dir);
5101
+ if (listing === null) return null;
5102
+ const names = new Set(listing.map((entry) => entry.name));
5103
+ const after = await witnessOf(dir);
5104
+ if (before !== null && after !== null && witnessKey(before) === witnessKey(after) && settled(after)) {
5105
+ kept.delete(dir);
5106
+ kept.set(dir, { witness: witnessKey(after), names });
5107
+ while (kept.size > capacity) kept.delete(kept.keys().next().value);
5108
+ }
5109
+ return listingView(names);
4958
5110
  };
5111
+ return { source, reused: () => reused };
5112
+ }
5113
+ var prefixListings = /* @__PURE__ */ new WeakMap();
5114
+ var PREFIX_LISTING_CAPACITY = 64;
5115
+ function openObservationPass(port, root, now = Date.now) {
5116
+ const rootResolved = path2.resolve(root);
5117
+ const kept = /* @__PURE__ */ new Map();
5118
+ const reusedVerdicts = [];
5119
+ const listingsFor = () => witnessedListings(port, kept, now);
4959
5120
  return {
4960
5121
  async observe(rel, read) {
4961
5122
  const listings = listingsFor();
@@ -5058,7 +5219,7 @@ async function readWhole(port, target) {
5058
5219
  await port.close(opened.handle);
5059
5220
  }
5060
5221
  }
5061
- async function mkdirExact(port, parent, segment, isTail, rel) {
5222
+ async function mkdirExact(port, parent, segment, isTail, rel, index = -1) {
5062
5223
  const outcome = await port.mkdir(path2.join(parent, segment));
5063
5224
  if (outcome === "created") return;
5064
5225
  const listing = await port.entries(parent);
@@ -5067,7 +5228,9 @@ async function mkdirExact(port, parent, segment, isTail, rel) {
5067
5228
  throw new FilesystemSymlinkEntryError(rel, segment);
5068
5229
  }
5069
5230
  const verdict = classifyMkdir(outcome, listing, segment, isTail);
5070
- if (verdict === "aliased") throw new FilesystemIdentityAliasError(rel, segment);
5231
+ if (verdict === "aliased") {
5232
+ throw aliasRefusalFromListing(rel, index, listing, false);
5233
+ }
5071
5234
  if (verdict === "shape-mismatch") throw new FilesystemShapeMismatchError(rel, segment);
5072
5235
  }
5073
5236
  async function ensureExactDirectories(port, rootResolved, segments, existingDepth, rel) {
@@ -5087,8 +5250,9 @@ async function ensureExactDirectories(port, rootResolved, segments, existingDept
5087
5250
  }
5088
5251
  }
5089
5252
  let parent = path2.join(rootResolved, ...segments.slice(0, existingDepth));
5090
- for (const segment of segments.slice(existingDepth, -1)) {
5091
- await mkdirExact(port, parent, segment, false, rel);
5253
+ for (let index = existingDepth; index < segments.length - 1; index++) {
5254
+ const segment = segments[index];
5255
+ await mkdirExact(port, parent, segment, false, rel, index);
5092
5256
  parent = path2.join(parent, segment);
5093
5257
  }
5094
5258
  }
@@ -5106,7 +5270,7 @@ async function createExactLeaf(port, tmp, target, rel, leaf, rootResolved) {
5106
5270
  }
5107
5271
  const listing = await port.entries(path2.dirname(target)) ?? [];
5108
5272
  if (hasExact(listing, leaf)) throw new ConcurrentReplacementError(rel, 1);
5109
- throw new FilesystemIdentityAliasError(rel, leaf);
5273
+ throw aliasRefusalFromListing(rel, relSegments(rel).length - 1, listing, true);
5110
5274
  }
5111
5275
  async function mutateExact(port, root, rel, body) {
5112
5276
  const segments = relSegments(rel);
@@ -5128,11 +5292,13 @@ async function mutateExact(port, root, rel, body) {
5128
5292
  async replace(bytes) {
5129
5293
  await ensureExactDirectories(port, rootResolved, segments, existingDepth, rel);
5130
5294
  const dir = path2.dirname(target);
5131
- const tmpName = `.${leaf}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
5295
+ const tmpName = identityTempName(leaf);
5132
5296
  const tmp = path2.join(dir, tmpName);
5133
5297
  await port.writeTemp(dir, tmpName, bytes);
5134
5298
  try {
5135
5299
  if (realized.state === "exact") {
5300
+ await port.copyMode?.(target, tmp).catch(() => {
5301
+ });
5136
5302
  await replaceExistingLeaf(port, tmp, target, rel);
5137
5303
  return;
5138
5304
  }
@@ -5292,6 +5458,9 @@ function createNodeFilesystemIdentityPort(hostPolicy) {
5292
5458
  async rename(from, to) {
5293
5459
  await fs2.rename(from, to);
5294
5460
  },
5461
+ async copyMode(from, to) {
5462
+ await fs2.chmod(to, (await fs2.lstat(from)).mode & 511);
5463
+ },
5295
5464
  async unlink(target) {
5296
5465
  await fs2.unlink(target);
5297
5466
  },
@@ -5314,6 +5483,7 @@ function blobVersion(bytes) {
5314
5483
 
5315
5484
  // ../core/src/backend.ts
5316
5485
  var publicationContexts = /* @__PURE__ */ new WeakMap();
5486
+ var fileMutations = /* @__PURE__ */ new WeakMap();
5317
5487
  function firstString(...vals) {
5318
5488
  for (const v of vals) {
5319
5489
  if (typeof v === "string" && v.trim() !== "") return v;
@@ -5430,6 +5600,7 @@ var FilesystemBackend = class _FilesystemBackend {
5430
5600
  this.#root = path3.resolve(root);
5431
5601
  this.#coordinator = createFilesystemMutationCoordinator(this.#port, this.#root, options.hostPolicy);
5432
5602
  publicationContexts.set(this, { root: this.#root, port: this.#port });
5603
+ fileMutations.set(this, (rel, body) => this.#mutateExact(rel, body));
5433
5604
  }
5434
5605
  async read(id) {
5435
5606
  return this.#readWithEdition(id, () => this.#readEdition());
@@ -5785,6 +5956,7 @@ var KIND_FIELD_TYPE_SET = new Set(KIND_FIELD_TYPES);
5785
5956
  function isKindFieldType(value) {
5786
5957
  return typeof value === "string" && KIND_FIELD_TYPE_SET.has(value);
5787
5958
  }
5959
+ var UNDECLARED_FIELDS_POLICIES = ["warn", "error"];
5788
5960
  function buildKindRegistry(docs, initialWarnings = [], options = {}) {
5789
5961
  const accepted = /* @__PURE__ */ new Map();
5790
5962
  const warnings = [...initialWarnings];
@@ -6379,6 +6551,19 @@ function parseConventionDoc(doc, options = {}) {
6379
6551
  });
6380
6552
  }
6381
6553
  }
6554
+ let undeclaredFields;
6555
+ if (fm.undeclared_fields !== void 0) {
6556
+ if (UNDECLARED_FIELDS_POLICIES.includes(fm.undeclared_fields)) {
6557
+ undeclaredFields = fm.undeclared_fields;
6558
+ } else {
6559
+ warnings.push({
6560
+ code: "KIND_CONVENTION_BAD_SHAPE",
6561
+ message: `kind convention '${doc.id}' has an invalid 'undeclared_fields' (${describeShape(fm.undeclared_fields)}; expected warn or error); using warn.`,
6562
+ field: "undeclared_fields",
6563
+ severity: "warning"
6564
+ });
6565
+ }
6566
+ }
6382
6567
  const kind = {
6383
6568
  id: doc.id,
6384
6569
  title,
@@ -6396,6 +6581,7 @@ function parseConventionDoc(doc, options = {}) {
6396
6581
  if (browseCollapsed !== void 0) kind.browseCollapsed = browseCollapsed;
6397
6582
  if (order !== void 0) kind.order = order;
6398
6583
  if (claim !== void 0) kind.claim = claim;
6584
+ if (undeclaredFields !== void 0) kind.undeclaredFields = undeclaredFields;
6399
6585
  if (Object.hasOwn(fm, "deprecated")) {
6400
6586
  kind.deprecated = parseKindDeprecation(fm.deprecated, kind, RESERVED_KIND_FIELD_NAMES, claimCoordinates(options.okfVersion, kind)?.fields ?? []);
6401
6587
  warnings.push(...kind.deprecated.problems ?? []);
@@ -6432,58 +6618,6 @@ function isTerminal(kind, frontmatter2) {
6432
6618
  return false;
6433
6619
  }
6434
6620
 
6435
- // ../core/src/query-selection.ts
6436
- function applyQuerySelectionFilters(rows, params, kinds = []) {
6437
- let out = rows;
6438
- const byGoverns = new Map(kinds.map((kind) => [kind.governs, kind]));
6439
- if (params.field) {
6440
- const eq = params.field.indexOf("=");
6441
- if (eq > 0) {
6442
- const key = params.field.slice(0, eq).trim();
6443
- const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
6444
- out = out.filter((row) => {
6445
- if (key !== PROGRESS_STATUS_FIELD) {
6446
- return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
6447
- }
6448
- const kind = byGoverns.get(String(row.frontmatter.type ?? ""));
6449
- if (!kind) return false;
6450
- const raw = readKindField(params.okfVersion, kind, row.frontmatter, key);
6451
- const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
6452
- return values.some((value) => actual.includes(value));
6453
- });
6454
- }
6455
- }
6456
- if (params.open) {
6457
- out = out.filter((row) => {
6458
- const kind = byGoverns.get(String(row.frontmatter.type ?? ""));
6459
- return !kind || !isTerminal(kind, row.frontmatter);
6460
- });
6461
- }
6462
- const count = out.length;
6463
- if (typeof params.limit === "number" && params.limit > 0) {
6464
- out = out.slice(0, params.limit);
6465
- }
6466
- return { rows: out, count };
6467
- }
6468
-
6469
- // ../core/src/kinds-load.ts
6470
- async function loadKinds(bundle) {
6471
- const warnings = [];
6472
- const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
6473
- onSkip: ({ id, reason }) => warnings.push({
6474
- code: "KIND_CONVENTION_MALFORMED",
6475
- message: `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
6476
- field: id,
6477
- severity: "warning"
6478
- })
6479
- });
6480
- const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
6481
- if (!(error instanceof MalformedDocumentError)) throw error;
6482
- return void 0;
6483
- });
6484
- return buildKindRegistry(docs, warnings, { okfVersion });
6485
- }
6486
-
6487
6621
  // ../core/src/page.ts
6488
6622
  var PAGE_REGISTRY_PREFIX = "pages-registry/";
6489
6623
  var PAGE_ENTRY_PREFIX = "pages/";
@@ -6556,6 +6690,58 @@ function parseRegistration(id, frontmatter2) {
6556
6690
  };
6557
6691
  }
6558
6692
 
6693
+ // ../core/src/query-selection.ts
6694
+ function applyQuerySelectionFilters(rows, params, kinds = []) {
6695
+ let out = rows;
6696
+ const byGoverns = new Map(kinds.map((kind) => [kind.governs, kind]));
6697
+ if (params.field) {
6698
+ const eq = params.field.indexOf("=");
6699
+ if (eq > 0) {
6700
+ const key = params.field.slice(0, eq).trim();
6701
+ const values = params.field.slice(eq + 1).split(",").map((value) => value.trim()).filter(Boolean);
6702
+ out = out.filter((row) => {
6703
+ if (key !== PROGRESS_STATUS_FIELD) {
6704
+ return values.some((value) => matchesFilter(row, { fields: { [key]: value } }));
6705
+ }
6706
+ const kind = byGoverns.get(String(row.frontmatter.type ?? ""));
6707
+ if (!kind) return false;
6708
+ const raw = readKindField(params.okfVersion, kind, row.frontmatter, key);
6709
+ const actual = raw === void 0 || raw === null ? [] : (Array.isArray(raw) ? raw : [raw]).map((value) => String(value));
6710
+ return values.some((value) => actual.includes(value));
6711
+ });
6712
+ }
6713
+ }
6714
+ if (params.open) {
6715
+ out = out.filter((row) => {
6716
+ const kind = byGoverns.get(String(row.frontmatter.type ?? ""));
6717
+ return !kind || !isTerminal(kind, row.frontmatter);
6718
+ });
6719
+ }
6720
+ const count = out.length;
6721
+ if (typeof params.limit === "number" && params.limit > 0) {
6722
+ out = out.slice(0, params.limit);
6723
+ }
6724
+ return { rows: out, count };
6725
+ }
6726
+
6727
+ // ../core/src/kinds-load.ts
6728
+ async function loadKinds(bundle) {
6729
+ const warnings = [];
6730
+ const docs = await query2(bundle, { prefix: CONVENTIONS_PREFIX, type: CONVENTION_TYPE }, {
6731
+ onSkip: ({ id, reason }) => warnings.push({
6732
+ code: "KIND_CONVENTION_MALFORMED",
6733
+ message: isPermissionDeniedSkip({ reason }) ? `skipped kind convention '${id}' that could not be read: ${reason}` : `skipped kind convention '${id}' with unparseable frontmatter: ${reason}`,
6734
+ field: id,
6735
+ severity: "warning"
6736
+ })
6737
+ });
6738
+ const okfVersion = await readBundleOkfVersion2(bundle).catch((error) => {
6739
+ if (!(error instanceof MalformedDocumentError)) throw error;
6740
+ return void 0;
6741
+ });
6742
+ return buildKindRegistry(docs, warnings, { okfVersion });
6743
+ }
6744
+
6559
6745
  // ../core/src/query-order.ts
6560
6746
  function meaningfulChangeOrderKey(id, frontmatter2, okfVersion) {
6561
6747
  const value = meaningfulChangeTimeValue(frontmatter2);