@orkestrel/scaffold 0.0.101 → 0.0.103

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.
Files changed (59) hide show
  1. package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +6 -14
  2. package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +41 -28
  3. package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +5 -12
  4. package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +25 -13
  5. package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +18 -25
  6. package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +11 -9
  7. package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +233 -232
  8. package/dist/agents/skills/orkestrel-publish/scripts/compare.js +95 -89
  9. package/dist/agents/skills/orkestrel-publish/scripts/pins.js +5 -7
  10. package/dist/agents/skills/orkestrel-publish/scripts/swap.js +1273 -0
  11. package/dist/agents/skills/orkestrel-publish/scripts/wave.js +99 -89
  12. package/dist/agents/skills/orkestrel-publish/scripts/window.js +54 -52
  13. package/dist/agents/skills/orkestrel-scout/scripts/map.js +160 -161
  14. package/dist/bin/main.js +483 -444
  15. package/dist/bin/main.js.map +1 -1
  16. package/dist/host/AGENTS.md +1 -0
  17. package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
  18. package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +8 -11
  19. package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +58 -28
  20. package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +5 -10
  21. package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +31 -12
  22. package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +28 -23
  23. package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +12 -10
  24. package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +318 -237
  25. package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +2 -5
  26. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +7 -6
  27. package/dist/host/agents/skills/orkestrel-publish/references/release.md +12 -10
  28. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +12 -5
  29. package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +124 -82
  30. package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +5 -7
  31. package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1655 -0
  32. package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +128 -97
  33. package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +70 -55
  34. package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +215 -155
  35. package/dist/host/claude/rules/architecture.md +2 -2
  36. package/dist/host/claude/rules/tests.md +8 -2
  37. package/dist/host/claude/rules/typescript.md +130 -0
  38. package/dist/host/claude/rules/workspace.md +33 -18
  39. package/dist/host/configs/helpers.ts +209 -148
  40. package/dist/host/configs/policy.ts +110 -105
  41. package/dist/host/dotfiles/oxlintrc.json +1 -11
  42. package/dist/host/guides/scaffold.md +244 -170
  43. package/dist/host/manifest.json +36 -30
  44. package/dist/host/tests/config.test.ts +1263 -687
  45. package/dist/host/tests/policy.test.ts +19 -0
  46. package/dist/host/tests/setupPolicy.ts +1699 -1026
  47. package/dist/src/core/index.cjs +1595 -1686
  48. package/dist/src/core/index.cjs.map +1 -1
  49. package/dist/src/core/index.d.cts +202 -18
  50. package/dist/src/core/index.d.ts +202 -18
  51. package/dist/src/core/index.js +1590 -1687
  52. package/dist/src/core/index.js.map +1 -1
  53. package/dist/src/server/index.cjs +448 -392
  54. package/dist/src/server/index.cjs.map +1 -1
  55. package/dist/src/server/index.d.cts +1182 -1052
  56. package/dist/src/server/index.d.ts +1182 -1052
  57. package/dist/src/server/index.js +447 -395
  58. package/dist/src/server/index.js.map +1 -1
  59. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
- import { andOf, arrayOf, attempt, boundsOf, compareValues, compileGuard, holds, isArray, isBoolean, isError, isFunction, isInteger, isNumber, isRecord, isString, parseJSON, parseJSONAs, parseStringField, recordOf, recordShape, stringOf, stringShape, unionOf, whereOf } from "@orkestrel/contract";
3
- import { CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONTROL_CHARACTER_PATTERN, DEPENDENCY_NAME_PATTERN, EXECUTABLE_PATHS, HOST_INVENTORY_PATH, HOST_PATHS, MAX_ARTIFACT_BYTES, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, REFERENCE_PATHS, ScaffoldError, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, contentToHex, extractRangeMajor, extractVersion, inferGroup, insertManifestDependencies, isAudit, isCatalogEntry, isCollection, isDependency, isDependencyName, isFloorPath, isHex, isManifestScript, isMirror, isPath, isPlan, isRetainedPath, isSnapshot, matchesDriftReachability, matchesRange, nameToGuide, planToFindings, renderSkillPointer, replaceManifestOverrides, replaceManifestRanges, replaceManifestScripts } from "../core/index.js";
2
+ import { andOf, arrayOf, attempt, boundsOf, compareValues, compileGuard, holds, isArray, isBoolean, isDefined, isError, isFunction, isInteger, isNonNegativeInteger, isNumber, isRecord, isString, parseJSON, parseJSONAs, parseStringField, recordOf, recordShape, stringOf, stringShape, unionOf, whereOf } from "@orkestrel/contract";
3
+ import { CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONTROL_CHARACTER_PATTERN, DEPENDENCY_NAME_PATTERN, EXECUTABLE_PATHS, HOST_INVENTORY_PATH, HOST_PATHS, MAX_ARTIFACT_BYTES, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, REFERENCE_PATHS, ScaffoldError, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeTotal, contentToHex, extractRangeMajor, extractVersion, inferGroup, insertManifestDependencies, isAudit, isCatalogEntry, isCollection, isDependency, isDependencyName, isFloorPath, isHex, isManifestScript, isMirror, isPath, isPlan, isRetainedPath, isSnapshot, iterateAnswers, matchesDriftReachability, matchesRange, nameToGuide, planToFindings, renderSkillPointer, replaceManifestOverrides, replaceManifestRanges, replaceManifestScripts } from "../core/index.js";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
5
  import { chmodSync, closeSync, constants, copyFileSync, fstatSync, linkSync, lstatSync, mkdirSync, mkdtempSync, openSync, opendirSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
6
6
  import { tmpdir } from "node:os";
@@ -481,18 +481,61 @@ function isExactCaseFile(path) {
481
481
  if (!isPhysicalFile(full)) return false;
482
482
  const root = parse(full).root;
483
483
  const segments = relative(root, full).split(sep);
484
- let parent = root;
485
- for (const segment of segments) {
484
+ return segments.every((segment, index) => {
485
+ const parent = join(root, ...segments.slice(0, index));
486
486
  const entries = attempt(() => readdirSync(parent));
487
- if (entries.success) {
488
- if (!entries.value.includes(segment)) return false;
489
- } else {
490
- const actual = attempt(() => realpathSync.native(join(parent, segment)));
491
- if (!actual.success || basename(actual.value) !== segment) return false;
492
- }
493
- parent = join(parent, segment);
494
- }
495
- return true;
487
+ if (entries.success) return entries.value.includes(segment);
488
+ const actual = attempt(() => realpathSync.native(join(parent, segment)));
489
+ return actual.success && basename(actual.value) === segment;
490
+ });
491
+ }
492
+ /**
493
+ * Places each result at the index its entry names, in a fresh array.
494
+ *
495
+ * @param entries - The index and result pairs, in any order; each index a non-negative integer.
496
+ * @returns An array holding each result at its index, whose length is the highest index plus one,
497
+ * and where an index no entry names stays a hole.
498
+ *
499
+ * @remarks
500
+ * A worker pool finishes its items out of order and can skip one, so its answer is merged by
501
+ * position rather than by arrival: each index is written once into a fresh array, which needs no
502
+ * sort and keeps a skipped index absent instead of closing the gap. A repeated index keeps its last
503
+ * result.
504
+ *
505
+ * @example
506
+ * ```ts
507
+ * import { collectIndexed } from '@orkestrel/scaffold/server'
508
+ *
509
+ * collectIndexed([[0, 'first'], [2, 'third']]).length // 3
510
+ * ```
511
+ */
512
+ function collectIndexed(entries) {
513
+ return Object.assign([], Object.fromEntries(entries));
514
+ }
515
+ /**
516
+ * Lists a path followed by each directory above it, nearest first.
517
+ *
518
+ * @param path - The host path to climb from.
519
+ * @param limit - The most paths to list; every ancestor by default.
520
+ * @returns The path, then `dirname` of each result in turn, ending at the first path that is its
521
+ * own parent (`.` for a relative path, the filesystem root for an absolute one) or at `limit`.
522
+ *
523
+ * @remarks
524
+ * The climb is derived from the path text alone and reads no filesystem, so a caller bounds a walk
525
+ * by the length it asks for rather than by a counter it reassigns. The final path of an unbounded
526
+ * list is the one `dirname` leaves unchanged.
527
+ *
528
+ * @example
529
+ * ```ts
530
+ * import { listAncestors } from '@orkestrel/scaffold/server'
531
+ *
532
+ * listAncestors('notes/entry/file.md') // ['notes/entry/file.md', 'notes/entry', 'notes', '.']
533
+ * listAncestors('notes/entry/file.md', 2) // ['notes/entry/file.md', 'notes/entry']
534
+ * ```
535
+ */
536
+ function listAncestors(path, limit = Number.POSITIVE_INFINITY) {
537
+ const parent = dirname(path);
538
+ return parent === path || limit <= 1 ? [path] : [path, ...listAncestors(parent, limit - 1)];
496
539
  }
497
540
  /**
498
541
  * Tests whether a path is a physical directory this package will read or write into.
@@ -548,14 +591,15 @@ function computeFileDigest(path) {
548
591
  if (!before.isFile() || before.nlink !== 1 || before.size > MAX_ARTIFACT_BYTES) return void 0;
549
592
  const hash = createHash("sha256");
550
593
  const buffer = Buffer.alloc(65536);
551
- let size = 0;
594
+ const lengths = [];
552
595
  for (;;) {
553
596
  const length = readSync(handle, buffer, 0, buffer.byteLength, null);
554
597
  if (length === 0) break;
555
- size += length;
556
- if (size > MAX_ARTIFACT_BYTES) return void 0;
598
+ lengths.push(length);
599
+ if (computeTotal(lengths) > MAX_ARTIFACT_BYTES) return void 0;
557
600
  hash.update(buffer.subarray(0, length));
558
601
  }
602
+ const size = computeTotal(lengths);
559
603
  const after = fstatSync(handle);
560
604
  if (size !== before.size || after.size !== before.size || after.mtimeMs !== before.mtimeMs) return;
561
605
  return hash.digest("hex");
@@ -577,8 +621,8 @@ function computeFileDigest(path) {
577
621
  * yet, and a lexical answer is not enough: a link anywhere in the existing
578
622
  * prefix moves the destination somewhere the text never named. So the deepest
579
623
  * existing ancestor is resolved and the remaining segments are re-joined onto
580
- * it. The climb is bounded by the path-depth ceiling, so an adversarial path
581
- * cannot make it walk indefinitely.
624
+ * it. {@link climbRealPath} performs the climb and bounds it by the path-depth
625
+ * ceiling, so an adversarial path cannot make it walk indefinitely.
582
626
  *
583
627
  * The caller's own text is collapsed first, which is what `resolve` does with a
584
628
  * `..` the caller wrote: it cancels the segment before it as text, before any
@@ -612,32 +656,50 @@ function computeFileDigest(path) {
612
656
  * ```
613
657
  */
614
658
  function resolveRealPath(path) {
615
- if (!isFilesystemPath(path)) return void 0;
616
- let current = resolve(path);
617
- const pending = [];
618
- for (let depth = 0; depth <= 64; depth += 1) {
619
- const real = attempt(() => realpathSync(current));
620
- if (real.success) {
621
- let physical = real.value;
622
- for (const segment of pending) physical = join(physical, segment);
623
- return physical;
624
- }
625
- if (!matchesMissingPath(real.error)) return void 0;
626
- const status = attempt(() => lstatSync(current));
627
- if (status.success) {
628
- if (!status.value.isSymbolicLink()) return void 0;
629
- const target = attempt(() => readlinkSync(current));
630
- if (!target.success) return void 0;
631
- if (target.value.split(/[\\/]/u).includes("..")) return void 0;
632
- current = resolve(dirname(current), target.value);
633
- continue;
634
- }
635
- if (!matchesMissingPath(status.error)) return void 0;
636
- const parent = dirname(current);
637
- if (parent === current) return void 0;
638
- pending.unshift(relative(parent, current));
639
- current = parent;
659
+ return isFilesystemPath(path) ? climbRealPath(resolve(path), [], 0) : void 0;
660
+ }
661
+ /**
662
+ * Climbs from an absolute path to its deepest existing ancestor and resolves it through every link.
663
+ *
664
+ * @param current - The absolute host path the climb reads at this depth.
665
+ * @param pending - The absent segments already climbed past, outermost first.
666
+ * @param depth - The steps already taken, from 0 through `MAX_PATH_DEPTH`.
667
+ * @returns The real path of the first existing ancestor joined with `pending` and every segment the
668
+ * climb passes, or `undefined` when `depth` is not a safe integer from 0 through `MAX_PATH_DEPTH`,
669
+ * the climb reaches the root, a link target cannot be read or carries a `..` segment, an existing
670
+ * entry is not a link, or an entry cannot be read.
671
+ *
672
+ * @remarks
673
+ * Each step reads one path and moves the climb to one other: a dangling link redirects it to the
674
+ * link's target with the same suffix, and an absent name moves it to the parent with that name added
675
+ * to the suffix. One successor per step makes the climb a bounded recursion rather than a worklist,
676
+ * and the depth argument is its bound, so an adversarial path or a link cycle answers `undefined`
677
+ * after `MAX_PATH_DEPTH` steps instead of walking indefinitely. {@link resolveRealPath} starts the
678
+ * climb at depth 0 with nothing pending.
679
+ *
680
+ * @example
681
+ * ```ts
682
+ * import { resolve } from 'node:path'
683
+ * import { climbRealPath } from '@orkestrel/scaffold/server'
684
+ *
685
+ * climbRealPath(resolve('./packages/new/src'), [], 0) // the real path of packages, plus new/src
686
+ * ```
687
+ */
688
+ function climbRealPath(current, pending, depth) {
689
+ if (!Number.isSafeInteger(depth) || depth < 0 || depth > 64) return void 0;
690
+ const real = attempt(() => realpathSync(current));
691
+ if (real.success) return pending.length === 0 ? real.value : join(real.value, ...pending);
692
+ if (!matchesMissingPath(real.error)) return void 0;
693
+ const status = attempt(() => lstatSync(current));
694
+ if (status.success) {
695
+ if (!status.value.isSymbolicLink()) return void 0;
696
+ const target = attempt(() => readlinkSync(current));
697
+ if (!target.success || target.value.split(/[\\/]/u).includes("..")) return void 0;
698
+ return climbRealPath(resolve(dirname(current), target.value), pending, depth + 1);
640
699
  }
700
+ if (!matchesMissingPath(status.error)) return void 0;
701
+ const parent = dirname(current);
702
+ return parent === current ? void 0 : climbRealPath(parent, [relative(parent, current), ...pending], depth + 1);
641
703
  }
642
704
  /**
643
705
  * Resolves a root-relative path and refuses one that leaves its root.
@@ -764,13 +826,12 @@ function listFiles(root) {
764
826
  });
765
827
  }
766
828
  if (!status.value.isDirectory() || status.value.isSymbolicLink()) throw new ScaffoldError("TARGET", `Listing root is not a physical directory at ${root}`, { root });
767
- const files = [];
768
829
  const pending = [{
769
830
  full: root,
770
831
  path: "",
771
832
  depth: 0
772
833
  }];
773
- let visited = 0;
834
+ const entries = [];
774
835
  while (pending.length > 0) {
775
836
  const current = pending.pop();
776
837
  if (current === void 0) break;
@@ -785,20 +846,21 @@ function listFiles(root) {
785
846
  for (;;) {
786
847
  const entry = handle.readSync();
787
848
  if (entry === null) break;
788
- visited += 1;
789
- if (visited > 1e5) throw new ScaffoldError("TARGET", "Listing exceeds the paths one inventory may report", {
849
+ const path = current.path === "" ? entry.name : `${current.path}/${entry.name}`;
850
+ const file = !entry.isDirectory() || entry.isSymbolicLink();
851
+ entries.push({
852
+ path,
853
+ file
854
+ });
855
+ if (entries.length > 1e5) throw new ScaffoldError("TARGET", "Listing exceeds the paths one inventory may report", {
790
856
  root,
791
857
  limit: MAX_INVENTORY_PATHS
792
858
  });
793
- const path = current.path === "" ? entry.name : `${current.path}/${entry.name}`;
794
859
  if (!isPath(path)) throw new ScaffoldError("TARGET", `Listing found a path this package cannot plan at ${path}`, {
795
860
  root,
796
861
  path
797
862
  });
798
- if (!entry.isDirectory() || entry.isSymbolicLink()) {
799
- files.push(path);
800
- continue;
801
- }
863
+ if (file) continue;
802
864
  const depth = current.depth + 1;
803
865
  if (depth >= 64) throw new ScaffoldError("TARGET", `Listing exceeds the depth one path may carry at ${path}`, {
804
866
  root,
@@ -815,7 +877,7 @@ function listFiles(root) {
815
877
  attempt(() => handle.closeSync());
816
878
  if (!walked.success) throw walked.error;
817
879
  }
818
- return files.sort();
880
+ return entries.filter(({ file }) => file).map(({ path }) => path).sort();
819
881
  }
820
882
  /**
821
883
  * Lists a directory's descendant directories as sorted root-relative paths.
@@ -857,13 +919,12 @@ function listDirectories(root) {
857
919
  });
858
920
  }
859
921
  if (!status.value.isDirectory() || status.value.isSymbolicLink()) throw new ScaffoldError("TARGET", `Listing root is not a physical directory at ${root}`, { root });
860
- const directories = [];
861
922
  const pending = [{
862
923
  full: root,
863
924
  path: "",
864
925
  depth: 0
865
926
  }];
866
- let visited = 0;
927
+ const entries = [];
867
928
  while (pending.length > 0) {
868
929
  const current = pending.pop();
869
930
  if (current === void 0) break;
@@ -878,24 +939,27 @@ function listDirectories(root) {
878
939
  for (;;) {
879
940
  const entry = handle.readSync();
880
941
  if (entry === null) break;
881
- visited += 1;
882
- if (visited > 1e5) throw new ScaffoldError("TARGET", "Listing exceeds the paths one inventory may report", {
942
+ const path = current.path === "" ? entry.name : `${current.path}/${entry.name}`;
943
+ const directory = entry.isDirectory() && !entry.isSymbolicLink();
944
+ entries.push({
945
+ path,
946
+ directory
947
+ });
948
+ if (entries.length > 1e5) throw new ScaffoldError("TARGET", "Listing exceeds the paths one inventory may report", {
883
949
  root,
884
950
  limit: MAX_INVENTORY_PATHS
885
951
  });
886
- const path = current.path === "" ? entry.name : `${current.path}/${entry.name}`;
887
952
  if (!isPath(path)) throw new ScaffoldError("TARGET", `Listing found a path this package cannot plan at ${path}`, {
888
953
  root,
889
954
  path
890
955
  });
891
- if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
956
+ if (!directory) continue;
892
957
  const depth = current.depth + 1;
893
958
  if (depth >= 64) throw new ScaffoldError("TARGET", `Listing exceeds the depth one path may carry at ${path}`, {
894
959
  root,
895
960
  path,
896
961
  limit: 64
897
962
  });
898
- directories.push(path);
899
963
  pending.push({
900
964
  full: join(current.full, entry.name),
901
965
  path,
@@ -906,7 +970,7 @@ function listDirectories(root) {
906
970
  attempt(() => handle.closeSync());
907
971
  if (!walked.success) throw walked.error;
908
972
  }
909
- return directories.sort();
973
+ return entries.filter(({ directory }) => directory).map(({ path }) => path).sort();
910
974
  }
911
975
  /**
912
976
  * Lists the canon paths a target holds, filtered to a plan's groups.
@@ -940,14 +1004,12 @@ function listDirectories(root) {
940
1004
  * ```
941
1005
  */
942
1006
  function listCanonPaths(target, groups) {
943
- const held = [];
944
- for (const member of CANON_PATHS) {
1007
+ return CANON_PATHS.flatMap((member) => {
945
1008
  const full = resolveContainedPath(target, member);
946
- if (full === void 0) continue;
947
- if (isPhysicalFile(full)) held.push(member);
948
- else if (isPhysicalDirectory(full)) for (const name of listFiles(full)) held.push(`${member}/${name}`);
949
- }
950
- return held.filter((path) => groups.includes(inferGroup(path)));
1009
+ if (full === void 0) return [];
1010
+ if (isPhysicalFile(full)) return [member];
1011
+ return isPhysicalDirectory(full) ? listFiles(full).map((name) => `${member}/${name}`) : [];
1012
+ }).filter((path) => groups.includes(inferGroup(path)));
951
1013
  }
952
1014
  /**
953
1015
  * Removes every directory one set of deletions emptied.
@@ -980,24 +1042,13 @@ function listCanonPaths(target, groups) {
980
1042
  * ```
981
1043
  */
982
1044
  function pruneEmptiedDirectories(target, removed) {
983
- const candidates = /* @__PURE__ */ new Set();
984
- for (const path of removed) {
985
- let parent = dirname(path);
986
- while (parent !== "." && parent !== dirname(parent) && !candidates.has(parent)) {
987
- candidates.add(parent);
988
- parent = dirname(parent);
989
- }
990
- }
991
- const ordered = [...candidates].sort((left, right) => compareValues(right.split("/").length, left.split("/").length) || compareValues(left, right));
992
- const pruned = [];
993
- for (const candidate of ordered) {
1045
+ return [...new Set(Iterator.from(removed).flatMap((path) => listAncestors(path).slice(1, -1)).toArray())].sort((left, right) => compareValues(right.split("/").length, left.split("/").length) || compareValues(left, right)).flatMap((candidate) => {
994
1046
  const directory = resolveContainedPath(target, candidate);
995
- if (directory === void 0 || !isPhysicalDirectory(directory)) continue;
1047
+ if (directory === void 0 || !isPhysicalDirectory(directory)) return [];
996
1048
  const entries = attempt(() => readdirSync(directory));
997
- if (!entries.success || entries.value.length > 0) continue;
998
- if (attempt(() => rmdirSync(directory)).success) pruned.push(candidate);
999
- }
1000
- return pruned;
1049
+ if (!entries.success || entries.value.length > 0) return [];
1050
+ return attempt(() => rmdirSync(directory)).success ? [candidate] : [];
1051
+ });
1001
1052
  }
1002
1053
  /**
1003
1054
  * Reads one contained file as its exact bytes in lowercase hexadecimal.
@@ -1045,12 +1096,15 @@ function readFileHex(root, path, limit = MAX_ARTIFACT_BYTES) {
1045
1096
  const before = fstatSync(handle);
1046
1097
  if (!before.isFile() || before.nlink !== 1 || before.size > limit) return void 0;
1047
1098
  const bytes = Buffer.alloc(before.size);
1048
- let offset = 0;
1049
- while (offset < bytes.byteLength) {
1050
- const length = readSync(handle, bytes, offset, bytes.byteLength - offset, offset);
1099
+ const reads = [];
1100
+ for (;;) {
1101
+ const position = computeTotal(reads);
1102
+ if (position >= bytes.byteLength) break;
1103
+ const length = readSync(handle, bytes, position, bytes.byteLength - position, position);
1051
1104
  if (length === 0) break;
1052
- offset += length;
1105
+ reads.push(length);
1053
1106
  }
1107
+ const offset = computeTotal(reads);
1054
1108
  const overflow = readSync(handle, Buffer.alloc(1), 0, 1, offset);
1055
1109
  const after = fstatSync(handle);
1056
1110
  if (offset !== bytes.byteLength || overflow !== 0 || after.size !== before.size || after.mtimeMs !== before.mtimeMs) return;
@@ -1122,9 +1176,7 @@ function readSnapshot(target, paths) {
1122
1176
  target,
1123
1177
  limit: MAX_COLLECTION_ITEMS
1124
1178
  });
1125
- let remaining = MAX_TOTAL_ARTIFACT_BYTES;
1126
- const snapshot = {};
1127
- for (const path of paths) {
1179
+ const read = Iterator.from(paths).reduce((state, path) => {
1128
1180
  const full = resolveContainedPath(target, path);
1129
1181
  if (full === void 0) throw new ScaffoldError("INVALID", `Snapshot path leaves its target at ${path}`, {
1130
1182
  target,
@@ -1132,27 +1184,32 @@ function readSnapshot(target, paths) {
1132
1184
  });
1133
1185
  const status = attempt(() => lstatSync(full));
1134
1186
  if (!status.success) {
1135
- if (matchesMissingPath(status.error)) continue;
1187
+ if (matchesMissingPath(status.error)) return state;
1136
1188
  throw new ScaffoldError("TARGET", `Snapshot path cannot be inspected at ${path}`, {
1137
1189
  target,
1138
1190
  path,
1139
1191
  error: status.error
1140
1192
  });
1141
1193
  }
1142
- if (isPhysicalDirectory(full)) {
1143
- snapshot[path] = "";
1144
- continue;
1145
- }
1146
- const hex = readFileHex(target, path, Math.min(MAX_ARTIFACT_BYTES, remaining));
1194
+ if (isPhysicalDirectory(full)) return {
1195
+ ...state,
1196
+ entries: [...state.entries, [path, ""]]
1197
+ };
1198
+ const hex = readFileHex(target, path, Math.min(MAX_ARTIFACT_BYTES, MAX_TOTAL_ARTIFACT_BYTES - computeTotal(state.spent)));
1147
1199
  if (hex === void 0) throw new ScaffoldError("TARGET", `Snapshot path is not a readable file at ${path}`, {
1148
1200
  target,
1149
1201
  path,
1150
1202
  limit: MAX_TOTAL_ARTIFACT_BYTES
1151
1203
  });
1152
- remaining -= hex.length / 2;
1153
- snapshot[path] = hex;
1154
- }
1155
- return snapshot;
1204
+ return {
1205
+ entries: [...state.entries, [path, hex]],
1206
+ spent: [...state.spent, hex.length / 2]
1207
+ };
1208
+ }, {
1209
+ entries: [],
1210
+ spent: []
1211
+ });
1212
+ return Object.fromEntries(read.entries);
1156
1213
  }
1157
1214
  /**
1158
1215
  * Reads a vendored host's manifest, when it carries one.
@@ -1236,20 +1293,18 @@ function readHostFloor(root) {
1236
1293
  if (!isPhysicalDirectory(host)) throw new ScaffoldError("TARGET", `The vendored host root is not readable at ${host}`, { host });
1237
1294
  const manifest = readHostManifest(host, source ? HOST_INVENTORY_PATH : MANIFEST_NAME);
1238
1295
  if (manifest === void 0) throw new ScaffoldError("TARGET", `The vendored host carries no manifest at ${host}`, { host });
1239
- const bytes = {};
1240
- for (const entry of manifest.entries) {
1241
- const path = source ? entry.destination : entry.storage;
1242
- const hex = readFileHex(host, path);
1243
- if (hex === void 0 || hexToDigest(hex) !== entry.digest) throw new ScaffoldError("TARGET", `The vendored host cannot read the declared file at ${path}`, {
1244
- host,
1245
- path,
1246
- destination: entry.destination
1247
- });
1248
- bytes[entry.destination] = hex;
1249
- }
1250
1296
  return {
1251
1297
  manifest,
1252
- bytes
1298
+ bytes: Object.fromEntries(manifest.entries.map((entry) => {
1299
+ const path = source ? entry.destination : entry.storage;
1300
+ const hex = readFileHex(host, path);
1301
+ if (hex === void 0 || hexToDigest(hex) !== entry.digest) throw new ScaffoldError("TARGET", `The vendored host cannot read the declared file at ${path}`, {
1302
+ host,
1303
+ path,
1304
+ destination: entry.destination
1305
+ });
1306
+ return [entry.destination, hex];
1307
+ }))
1253
1308
  };
1254
1309
  }
1255
1310
  /**
@@ -1329,24 +1384,21 @@ function readManifestEntry(destination, source) {
1329
1384
  */
1330
1385
  function filesToHost(files, floor) {
1331
1386
  const declared = new Set(floor.manifest.entries.map((entry) => entry.destination));
1332
- const held = /* @__PURE__ */ new Map();
1333
- for (const file of files) {
1334
- if (file.lookup !== "found" || !declared.has(file.path)) return void 0;
1335
- if (!isFloorPath(file.path)) held.set(file.path, file.hex);
1336
- }
1337
- const entries = [];
1338
- const bytes = {};
1339
- for (const entry of floor.manifest.entries) {
1387
+ const rows = [...iterateAnswers(files, (file) => file.lookup !== "found" || !declared.has(file.path) ? void 0 : isFloorPath(file.path) ? [] : [[file.path, file.hex]])];
1388
+ if (!rows.every(isDefined)) return void 0;
1389
+ const held = new Map(rows.flat());
1390
+ const filled = [...iterateAnswers(floor.manifest.entries, (entry) => {
1340
1391
  const hex = isFloorPath(entry.destination) ? floor.bytes[entry.destination] : held.get(entry.destination);
1341
- if (hex === void 0) return void 0;
1342
- entries.push({
1392
+ return hex === void 0 ? void 0 : [{
1343
1393
  storage: entry.storage,
1344
1394
  destination: entry.destination,
1345
1395
  executable: entry.executable,
1346
1396
  digest: hexToDigest(hex)
1347
- });
1348
- bytes[entry.destination] = hex;
1349
- }
1397
+ }, hex];
1398
+ })];
1399
+ if (!filled.every(isDefined)) return void 0;
1400
+ const entries = filled.map(([entry]) => entry);
1401
+ const bytes = Object.fromEntries(filled.map(([entry, hex]) => [entry.destination, hex]));
1350
1402
  return {
1351
1403
  manifest: {
1352
1404
  entries,
@@ -1394,8 +1446,7 @@ function filesToHost(files, floor) {
1394
1446
  function stageBytes(host, root, destinations) {
1395
1447
  if (!isFilesystemPath(root)) throw new ScaffoldError("INVALID", "Staging host root is not a host path", { host: root });
1396
1448
  const declared = new Map(host.manifest.entries.map((entry) => [entry.destination, entry]));
1397
- const staged = [];
1398
- for (const destination of destinations) {
1449
+ return Iterator.from(destinations).map((destination) => {
1399
1450
  const entry = declared.get(destination);
1400
1451
  const hex = host.bytes[destination];
1401
1452
  if (entry === void 0 || hex === void 0) throw new ScaffoldError("TARGET", `The host carries no bytes for ${destination}`, {
@@ -1425,9 +1476,8 @@ function stageBytes(host, root, destinations) {
1425
1476
  host: root,
1426
1477
  storage: entry.storage
1427
1478
  });
1428
- staged.push(entry);
1429
- }
1430
- return staged;
1479
+ return entry;
1480
+ }).toArray();
1431
1481
  }
1432
1482
  /**
1433
1483
  * Stages a vendored host root from a real checkout.
@@ -1504,37 +1554,36 @@ function stageHost(checkout, host, options) {
1504
1554
  const source = resolve(checkout);
1505
1555
  if (!isPhysicalDirectory(source)) throw new ScaffoldError("TARGET", `Staging checkout is not a physical directory at ${source}`, { checkout: source });
1506
1556
  if (!isVacant(host)) throw new ScaffoldError("TARGET", `Staging host root is not vacant at ${host}`, { host });
1507
- const vendored = [];
1508
- const roots = [];
1509
- const missing = [];
1510
- for (const path of [
1557
+ const reads = [
1511
1558
  ...HOST_PATHS,
1512
1559
  ...CANON_PATHS,
1513
1560
  ...REFERENCE_PATHS
1514
- ]) {
1561
+ ].map((path) => {
1515
1562
  const full = resolveContainedPath(source, path);
1516
1563
  if (full === void 0) throw new ScaffoldError("INVALID", `Vendored path leaves its checkout at ${path}`, {
1517
1564
  checkout: source,
1518
1565
  path
1519
1566
  });
1520
- if (isPhysicalFile(full)) {
1521
- vendored.push(path);
1522
- continue;
1523
- }
1524
- if (!isPhysicalDirectory(full)) {
1525
- if (!CANON_PATHS.includes(path)) missing.push(path);
1526
- continue;
1527
- }
1528
- roots.push(path);
1529
- for (const nested of listDirectories(full)) {
1530
- const rooted = `${path}/${nested}`;
1531
- if (!matchesSensitivePath(rooted)) roots.push(rooted);
1532
- }
1533
- for (const name of listFiles(full)) {
1534
- const destination = `${path}/${name}`;
1535
- if (!matchesSensitivePath(destination)) vendored.push(destination);
1536
- }
1537
- }
1567
+ if (isPhysicalFile(full)) return {
1568
+ vendored: [path],
1569
+ roots: [],
1570
+ missing: []
1571
+ };
1572
+ if (!isPhysicalDirectory(full)) return {
1573
+ vendored: [],
1574
+ roots: [],
1575
+ missing: CANON_PATHS.includes(path) ? [] : [path]
1576
+ };
1577
+ const nested = listDirectories(full);
1578
+ return {
1579
+ vendored: listFiles(full).map((name) => `${path}/${name}`).filter((destination) => !matchesSensitivePath(destination)),
1580
+ roots: [path, ...nested.map((name) => `${path}/${name}`).filter((rooted) => !matchesSensitivePath(rooted))],
1581
+ missing: []
1582
+ };
1583
+ });
1584
+ const vendored = reads.flatMap((read) => read.vendored);
1585
+ const roots = reads.flatMap((read) => read.roots).sort();
1586
+ const missing = reads.flatMap((read) => read.missing);
1538
1587
  if (missing.length > 0) throw new ScaffoldError("TARGET", "The checkout does not carry every vendored path", {
1539
1588
  checkout: source,
1540
1589
  missing
@@ -1554,9 +1603,8 @@ function stageHost(checkout, host, options) {
1554
1603
  path
1555
1604
  });
1556
1605
  }
1557
- const stored = /* @__PURE__ */ new Set([MANIFEST_NAME]);
1558
- const candidates = [];
1559
- for (const destination of vendored) {
1606
+ const storages = vendored.map((destination) => pathToStorage(destination));
1607
+ const candidates = vendored.map((destination, index) => {
1560
1608
  const full = resolveContainedPath(source, destination);
1561
1609
  if (full === void 0) throw new ScaffoldError("INVALID", `Vendored path leaves its checkout at ${destination}`, {
1562
1610
  checkout: source,
@@ -1568,16 +1616,13 @@ function stageHost(checkout, host, options) {
1568
1616
  path: destination,
1569
1617
  limit: MAX_ARTIFACT_BYTES
1570
1618
  });
1571
- if (stored.has(entry.storage)) throw new ScaffoldError("TARGET", `Two vendored paths claim the storage name ${entry.storage}`, {
1619
+ if (entry.storage === "manifest.json" || storages.indexOf(entry.storage) < index) throw new ScaffoldError("TARGET", `Two vendored paths claim the storage name ${entry.storage}`, {
1572
1620
  checkout: source,
1573
1621
  path: destination,
1574
1622
  storage: entry.storage
1575
1623
  });
1576
- stored.add(entry.storage);
1577
- candidates.push(entry);
1578
- }
1579
- candidates.sort((first, second) => first.storage < second.storage ? -1 : 1);
1580
- roots.sort();
1624
+ return entry;
1625
+ }).sort((first, second) => first.storage < second.storage ? -1 : 1);
1581
1626
  const baseline = resolveContainedPath(source, options?.inventory ?? HOST_INVENTORY_PATH);
1582
1627
  if (baseline === void 0) throw new ScaffoldError("INVALID", "Surface inventory leaves its checkout", {
1583
1628
  checkout: source,
@@ -1597,8 +1642,7 @@ function stageHost(checkout, host, options) {
1597
1642
  host: root,
1598
1643
  ...established.success ? {} : { error: established.error }
1599
1644
  });
1600
- const entries = [];
1601
- for (const entry of candidates) {
1645
+ const entries = candidates.map((entry) => {
1602
1646
  const origin = resolveContainedPath(source, entry.destination);
1603
1647
  const destination = resolveContainedPath(root, entry.storage);
1604
1648
  if (origin === void 0 || destination === void 0) throw new ScaffoldError("INVALID", `Vendored path leaves its root at ${entry.destination}`, {
@@ -1622,17 +1666,16 @@ function stageHost(checkout, host, options) {
1622
1666
  host: root,
1623
1667
  storage: entry.storage
1624
1668
  });
1625
- entries.push({
1669
+ return {
1626
1670
  ...entry,
1627
1671
  digest
1628
- });
1629
- }
1672
+ };
1673
+ });
1630
1674
  const collisions = readSurfaceCollisions(join(root, "guides"));
1631
- const growth = [];
1632
- if (published !== void 0) for (const [name, owners] of collisions) {
1675
+ const growth = published === void 0 ? [] : [...collisions].flatMap(([name, owners]) => {
1633
1676
  const record = published.get(name);
1634
- if (!(record !== void 0 && owners.every((owner) => record.includes(owner)))) growth.push(`${name} staged (${owners.join(", ")}), recorded (${record?.join(", ") ?? "absent"})`);
1635
- }
1677
+ return record !== void 0 && owners.every((owner) => record.includes(owner)) ? [] : [`${name} staged (${owners.join(", ")}), recorded (${record?.join(", ") ?? "absent"})`];
1678
+ });
1636
1679
  if (growth.length > 0) throw new ScaffoldError("TARGET", `Staged Surface collisions differ from the inventory: ${growth.join("; ")}`, {
1637
1680
  checkout: source,
1638
1681
  host: root,
@@ -1692,26 +1735,19 @@ function readSurfaceCollisions(root) {
1692
1735
  error: loaded.error
1693
1736
  });
1694
1737
  const guide = loaded.value;
1695
- const owners = /* @__PURE__ */ new Map();
1696
- for (const path of listFiles(root)) {
1697
- if (path.includes("/") || extname(path) !== ".md" || path === "README.md") continue;
1738
+ const claims = listFiles(root).filter((path) => !path.includes("/") && extname(path) === ".md" && path !== "README.md").flatMap((path) => {
1698
1739
  const text = readFileText(root, path);
1699
1740
  if (text === void 0) throw new ScaffoldError("TARGET", `Surface guide cannot be read at ${path}`, {
1700
1741
  root,
1701
1742
  path
1702
1743
  });
1703
- for (const symbol of guide.createGuide(text).surface()) {
1704
- const claimed = owners.get(symbol.name) ?? /* @__PURE__ */ new Set();
1705
- claimed.add(basename(path, ".md"));
1706
- owners.set(symbol.name, claimed);
1707
- }
1708
- }
1709
- const collisions = /* @__PURE__ */ new Map();
1710
- for (const name of [...owners.keys()].sort()) {
1711
- const claimed = owners.get(name);
1712
- if (claimed !== void 0 && claimed.size > 1) collisions.set(name, [...claimed].sort());
1713
- }
1714
- return collisions;
1744
+ return guide.createGuide(text).surface().map((symbol) => [symbol.name, basename(path, ".md")]);
1745
+ });
1746
+ const grouped = Map.groupBy(claims, ([name]) => name);
1747
+ return new Map([...grouped.keys()].sort().flatMap((name) => {
1748
+ const owners = [...new Set((grouped.get(name) ?? []).map(([, owner]) => owner))];
1749
+ return owners.length > 1 ? [[name, owners.sort()]] : [];
1750
+ }));
1715
1751
  }
1716
1752
  /**
1717
1753
  * Reads the Surface collision baseline from a committed inventory.
@@ -2461,17 +2497,15 @@ var WriteTransaction = class {
2461
2497
  paths
2462
2498
  });
2463
2499
  this.#target = resolve(target);
2464
- const expectations = /* @__PURE__ */ new Map();
2465
- for (const path of paths) {
2500
+ this.#expectations = new Map(Array.from(paths, (path) => {
2466
2501
  const expectation = readExpectation(this.#resolve(this.#target, path));
2467
2502
  if (expectation === void 0) throw new ScaffoldError("TARGET", `The destination at ${path} is a shape this package will not write over.`, {
2468
2503
  target: this.#target,
2469
2504
  path
2470
2505
  });
2471
- expectations.set(path, expectation);
2472
- }
2473
- this.#expectations = expectations;
2474
- const destinations = new Set([...expectations.values()].map((expectation) => expectation.path));
2506
+ return [path, expectation];
2507
+ }));
2508
+ const destinations = new Set([...this.#expectations.values()].map((expectation) => expectation.path));
2475
2509
  for (const precondition of preconditions ?? []) {
2476
2510
  if (!destinations.has(precondition.path)) throw new ScaffoldError("INVALID", `The precondition at ${precondition.path} names no destination of this transaction.`, {
2477
2511
  target: this.#target,
@@ -2660,8 +2694,14 @@ var WriteTransaction = class {
2660
2694
  const taken = [];
2661
2695
  const applied = attempt(() => {
2662
2696
  this.#preflight();
2663
- for (const path of this.#staged) this.#promote(path, promoted);
2664
- for (const path of this.#taken) this.#take(path, taken);
2697
+ for (const path of this.#staged) {
2698
+ this.#promote(path);
2699
+ promoted.push(path);
2700
+ }
2701
+ for (const path of this.#taken) {
2702
+ this.#take(path);
2703
+ taken.push(path);
2704
+ }
2665
2705
  });
2666
2706
  this.#open = false;
2667
2707
  if (!applied.success) {
@@ -2718,8 +2758,7 @@ var WriteTransaction = class {
2718
2758
  path
2719
2759
  });
2720
2760
  const base = resolve(root);
2721
- let ancestor = dirname(destination);
2722
- for (let depth = 0; depth <= 64; depth += 1) {
2761
+ for (const ancestor of listAncestors(destination, 66).slice(1)) {
2723
2762
  const state = readExpectation(ancestor);
2724
2763
  if (state === void 0 || state.shape === "file") throw new ScaffoldError("WRITE", `The path ${path} passes through a link or a file.`, {
2725
2764
  root,
@@ -2727,9 +2766,6 @@ var WriteTransaction = class {
2727
2766
  ancestor
2728
2767
  });
2729
2768
  if (ancestor === base) return destination;
2730
- const parent = dirname(ancestor);
2731
- if (parent === ancestor) break;
2732
- ancestor = parent;
2733
2769
  }
2734
2770
  throw new ScaffoldError("INVALID", `The path ${path} does not resolve beneath its root.`, {
2735
2771
  root,
@@ -2738,41 +2774,44 @@ var WriteTransaction = class {
2738
2774
  }
2739
2775
  #establish(path) {
2740
2776
  const destination = resolve(path);
2741
- const missing = [];
2742
- let current = destination;
2743
- let anchor = readAnchor(current);
2744
- for (let depth = 0; anchor === void 0 && depth <= 64; depth += 1) {
2745
- const state = readExpectation(current);
2746
- if (state === void 0 || state.shape !== "absent") throw new ScaffoldError("WRITE", `The directory at ${current} is not a physical directory.`, { path: destination });
2747
- missing.push(current);
2748
- const parent = dirname(current);
2749
- if (parent === current) throw new ScaffoldError("WRITE", `The directory at ${destination} has no existing ancestor.`, { path: destination });
2750
- current = parent;
2751
- anchor = readAnchor(current);
2752
- }
2753
- if (anchor === void 0) throw new ScaffoldError("WRITE", `The directory at ${destination} is nested past the ceiling.`, {
2754
- path: destination,
2755
- limit: 64
2756
- });
2777
+ const { anchor: located, missing } = this.#locate(destination);
2757
2778
  const created = [];
2758
2779
  for (const segment of [...missing].reverse()) {
2780
+ const anchor = created.at(-1) ?? located;
2759
2781
  if (!matchesAnchor(anchor)) throw new ScaffoldError("WRITE", `The directory at ${anchor.path} changed while writing.`, {
2760
2782
  path: destination,
2761
2783
  ancestor: anchor.path
2762
2784
  });
2763
2785
  mkdirSync(segment);
2764
- this.#created.push(segment);
2765
2786
  const established = readAnchor(segment);
2787
+ this.#created.push(established ?? segment);
2766
2788
  if (established === void 0) throw new ScaffoldError("WRITE", `The directory at ${segment} changed while writing.`, { path: destination });
2767
- anchor = established;
2768
- this.#created[this.#created.length - 1] = established;
2769
2789
  created.push(established);
2770
2790
  }
2771
2791
  return {
2772
- anchor,
2792
+ anchor: created.at(-1) ?? located,
2773
2793
  created
2774
2794
  };
2775
2795
  }
2796
+ #locate(destination) {
2797
+ const missing = [];
2798
+ for (const [depth, current] of listAncestors(destination, 66).entries()) {
2799
+ const anchor = readAnchor(current);
2800
+ if (anchor !== void 0) return {
2801
+ anchor,
2802
+ missing
2803
+ };
2804
+ if (depth > 64) break;
2805
+ const state = readExpectation(current);
2806
+ if (state === void 0 || state.shape !== "absent") throw new ScaffoldError("WRITE", `The directory at ${current} is not a physical directory.`, { path: destination });
2807
+ missing.push(current);
2808
+ if (dirname(current) === current) throw new ScaffoldError("WRITE", `The directory at ${destination} has no existing ancestor.`, { path: destination });
2809
+ }
2810
+ throw new ScaffoldError("WRITE", `The directory at ${destination} is nested past the ceiling.`, {
2811
+ path: destination,
2812
+ limit: 64
2813
+ });
2814
+ }
2776
2815
  #preflight() {
2777
2816
  for (const anchor of this.#created) {
2778
2817
  if (isString(anchor)) throw new ScaffoldError("WRITE", `The directory at ${anchor} changed while writing.`, {
@@ -2793,7 +2832,7 @@ var WriteTransaction = class {
2793
2832
  path
2794
2833
  });
2795
2834
  }
2796
- #promote(path, promoted) {
2835
+ #promote(path) {
2797
2836
  const expectation = this.#expectation(path);
2798
2837
  if (!matchesExpectation(expectation)) throw new ScaffoldError("WRITE", `The destination at ${path} moved while writing.`, { path });
2799
2838
  const staged = this.#resolve(this.#stage, path);
@@ -2804,23 +2843,19 @@ var WriteTransaction = class {
2804
2843
  linkSync(expectation.path, backup);
2805
2844
  }
2806
2845
  renameSync(staged, expectation.path);
2807
- promoted.push(path);
2808
2846
  }
2809
- #take(path, taken) {
2847
+ #take(path) {
2810
2848
  const expectation = this.#expectation(path);
2811
2849
  if (!matchesExpectation(expectation)) throw new ScaffoldError("WRITE", `The destination at ${path} moved while writing.`, { path });
2812
2850
  const backup = this.#resolve(this.#backup, path);
2813
2851
  mkdirSync(dirname(backup), { recursive: true });
2814
2852
  renameSync(expectation.path, backup);
2815
- taken.push(path);
2816
2853
  }
2817
2854
  #recover(promoted, taken) {
2818
- const residue = [];
2819
- for (const path of [...taken].reverse()) {
2855
+ const restoring = [...[...taken].reverse().flatMap((path) => {
2820
2856
  const restored = attempt(() => renameSync(this.#resolve(this.#backup, path), this.#expectation(path).path));
2821
- if (!restored.success) residue.push(restored.error);
2822
- }
2823
- for (const path of [...promoted].reverse()) {
2857
+ return restored.success ? [] : [restored.error];
2858
+ }), ...[...promoted].reverse().flatMap((path) => {
2824
2859
  const expectation = this.#expectation(path);
2825
2860
  const restored = attempt(() => {
2826
2861
  if (expectation.shape === "absent") {
@@ -2829,21 +2864,23 @@ var WriteTransaction = class {
2829
2864
  }
2830
2865
  renameSync(this.#resolve(this.#backup, path), expectation.path);
2831
2866
  });
2832
- if (!restored.success) residue.push(restored.error);
2833
- }
2834
- if (residue.length === 0) {
2835
- const cleared = attempt(() => rmSync(this.#root, {
2836
- recursive: true,
2837
- force: true
2838
- }));
2839
- if (!cleared.success) residue.push(cleared.error);
2840
- }
2841
- for (const created of [...this.#created].reverse()) {
2867
+ return restored.success ? [] : [restored.error];
2868
+ })];
2869
+ const cleared = restoring.length === 0 ? attempt(() => rmSync(this.#root, {
2870
+ recursive: true,
2871
+ force: true
2872
+ })) : void 0;
2873
+ const clearing = cleared === void 0 || cleared.success ? [] : [cleared.error];
2874
+ const removing = [...this.#created].reverse().flatMap((created) => {
2842
2875
  const path = isString(created) ? created : created.path;
2843
2876
  const removed = attempt(() => rmdirSync(path));
2844
- if (!removed.success && !matchesMissingPath(removed.error)) residue.push(removed.error);
2845
- }
2846
- return residue;
2877
+ return !removed.success && !matchesMissingPath(removed.error) ? [removed.error] : [];
2878
+ });
2879
+ return [
2880
+ ...restoring,
2881
+ ...clearing,
2882
+ ...removing
2883
+ ];
2847
2884
  }
2848
2885
  #stagePath(path) {
2849
2886
  const staged = this.#resolve(this.#stage, path);
@@ -3070,18 +3107,17 @@ var Materializer = class {
3070
3107
  const derived = this.#derive(accepted, directory, hydrated);
3071
3108
  this.#reconfirm(derived.findings, preview.findings, directory);
3072
3109
  const drifted = new Map(derived.findings.map((finding) => [finding.path, finding.drift]));
3073
- const writes = [];
3074
- const skipped = [];
3075
- const preconditions = [];
3076
- for (const artifact of hydrated.artifacts) {
3077
- const drift = drifted.get(artifact.path);
3078
- if (drift !== "missing" && drift !== "stale") {
3079
- skipped.push(artifact.path);
3080
- continue;
3081
- }
3082
- preconditions.push(this.#bind(directory, artifact.path, drift === "missing"));
3083
- writes.push(artifact);
3084
- }
3110
+ const judged = hydrated.artifacts.map((artifact) => ({
3111
+ artifact,
3112
+ drift: drifted.get(artifact.path)
3113
+ }));
3114
+ const skipped = judged.flatMap(({ artifact, drift }) => drift === "missing" || drift === "stale" ? [] : [artifact.path]);
3115
+ const selected = judged.flatMap(({ artifact, drift }) => drift === "missing" || drift === "stale" ? [{
3116
+ artifact,
3117
+ missing: drift === "missing"
3118
+ }] : []);
3119
+ const preconditions = selected.map(({ artifact, missing }) => this.#bind(directory, artifact.path, missing));
3120
+ const writes = selected.map(({ artifact }) => artifact);
3085
3121
  return this.#apply(directory, writes, [], skipped, preconditions);
3086
3122
  }
3087
3123
  /**
@@ -3106,15 +3142,15 @@ var Materializer = class {
3106
3142
  const writes = [];
3107
3143
  const skipped = [];
3108
3144
  const preconditions = [];
3109
- let remaining = MAX_TOTAL_ARTIFACT_BYTES;
3145
+ const spent = [];
3110
3146
  for (const fetched of accepted) {
3111
- const hex = fetched.lookup === "found" ? contentToHex(fetched.content) : fetched.observed === void 0 ? this.#reference(fetched.path, remaining) : void 0;
3147
+ const hex = fetched.lookup === "found" ? contentToHex(fetched.content) : fetched.observed === void 0 ? this.#reference(fetched.path, MAX_TOTAL_ARTIFACT_BYTES - computeTotal(spent)) : void 0;
3112
3148
  if (hex === void 0 || fetched.observed === hex) {
3113
3149
  skipped.push(fetched.path);
3114
3150
  continue;
3115
3151
  }
3116
- remaining -= hex.length / 2;
3117
- if (remaining < 0) throw this.#error("TARGET", "The guide mirrors exceed the total artifact byte limit.");
3152
+ spent.push(hex.length / 2);
3153
+ if (computeTotal(spent) > MAX_TOTAL_ARTIFACT_BYTES) throw this.#error("TARGET", "The guide mirrors exceed the total artifact byte limit.");
3118
3154
  const current = readFileHex(directory, fetched.path);
3119
3155
  if (current !== fetched.observed) throw this.#error("TARGET", `The mirror at ${fetched.path} moved since it was fetched.`, {
3120
3156
  target: directory,
@@ -3247,18 +3283,10 @@ var Materializer = class {
3247
3283
  const derived = this.#derive(accepted, directory);
3248
3284
  this.#reconfirmCandidates(derived.findings, preview.findings, directory);
3249
3285
  const tracked = new Set(state.tracked);
3250
- const removals = [];
3251
- const skipped = [];
3252
- for (const finding of derived.findings) {
3253
- if (finding.drift !== "foreign") continue;
3254
- if (!tracked.has(finding.path) || matchesProtectedPath(finding.path)) {
3255
- skipped.push(finding.path);
3256
- continue;
3257
- }
3258
- removals.push(finding.path);
3259
- }
3260
- const preconditions = [];
3261
- for (const path of removals) preconditions.push(this.#bind(directory, path, false));
3286
+ const foreign = derived.findings.filter((finding) => finding.drift === "foreign").map((finding) => finding.path);
3287
+ const skipped = foreign.filter((path) => !tracked.has(path) || matchesProtectedPath(path));
3288
+ const removals = foreign.filter((path) => tracked.has(path) && !matchesProtectedPath(path));
3289
+ const preconditions = removals.map((path) => this.#bind(directory, path, false));
3262
3290
  return this.#purge(directory, removals, skipped, preconditions);
3263
3291
  }
3264
3292
  /**
@@ -3318,49 +3346,51 @@ var Materializer = class {
3318
3346
  if (this.#entries.size !== manifest.entries.length) throw this.#error("TARGET", "The vendored host manifest maps two files to one destination.", { host: root });
3319
3347
  }
3320
3348
  #hydrate(plan) {
3321
- const artifacts = [];
3322
- let remaining = MAX_TOTAL_ARTIFACT_BYTES;
3349
+ const groups = [];
3350
+ const spent = [];
3323
3351
  for (const artifact of plan.artifacts) {
3324
3352
  if (artifact.origin !== "host") {
3325
- remaining -= computeBytes(artifact.content);
3326
- artifacts.push(artifact);
3353
+ spent.push(computeBytes(artifact.content));
3354
+ groups.push([artifact]);
3327
3355
  continue;
3328
3356
  }
3329
- const expanded = this.#expand(artifact, remaining);
3330
- for (const one of expanded) remaining -= one.origin === "host" ? (one.hex?.length ?? 0) / 2 : computeBytes(one.content);
3331
- artifacts.push(...expanded);
3357
+ const expanded = this.#expand(artifact, MAX_TOTAL_ARTIFACT_BYTES - computeTotal(spent));
3358
+ spent.push(computeTotal(expanded.map((one) => one.origin === "host" ? (one.hex?.length ?? 0) / 2 : computeBytes(one.content))));
3359
+ groups.push(expanded);
3332
3360
  }
3333
- if (remaining < 0) throw this.#error("TARGET", "The hydrated plan retains more bytes than one plan may.", {
3361
+ if (computeTotal(spent) > MAX_TOTAL_ARTIFACT_BYTES) throw this.#error("TARGET", "The hydrated plan retains more bytes than one plan may.", {
3334
3362
  host: this.#root,
3335
3363
  limit: MAX_TOTAL_ARTIFACT_BYTES
3336
3364
  });
3337
3365
  return {
3338
3366
  blueprint: plan.blueprint,
3339
3367
  groups: plan.groups,
3340
- artifacts
3368
+ artifacts: groups.flat()
3341
3369
  };
3342
3370
  }
3343
3371
  #derive(plan, target, hydrated = this.#hydrate(plan)) {
3344
- const paths = new Set(hydrated.artifacts.map((artifact) => artifact.path));
3345
- for (const root of this.#roots(plan)) {
3346
- const directory = resolveContainedPath(target, root);
3347
- if (directory === void 0) throw this.#error("TARGET", `The owned root at ${root} leaves its target.`, {
3348
- target,
3349
- path: root
3350
- });
3351
- for (const name of listFiles(directory)) paths.add(`${root}/${name}`);
3352
- }
3353
- for (const path of listCanonPaths(target, plan.groups)) paths.add(path);
3372
+ const paths = /* @__PURE__ */ new Set([
3373
+ ...hydrated.artifacts.map((artifact) => artifact.path),
3374
+ ...this.#roots(plan).flatMap((root) => {
3375
+ const directory = resolveContainedPath(target, root);
3376
+ if (directory === void 0) throw this.#error("TARGET", `The owned root at ${root} leaves its target.`, {
3377
+ target,
3378
+ path: root
3379
+ });
3380
+ return listFiles(directory).map((name) => `${root}/${name}`);
3381
+ }),
3382
+ ...listCanonPaths(target, plan.groups)
3383
+ ]);
3354
3384
  const questions = [];
3355
3385
  if (plan.groups.includes("guides")) {
3356
3386
  const directory = resolveContainedPath(target, "guides");
3357
- let remaining = MAX_TOTAL_ARTIFACT_BYTES;
3387
+ const spent = [];
3358
3388
  for (const file of directory === void 0 ? [] : listFiles(directory)) {
3359
3389
  const path = `guides/${file}`;
3360
3390
  if (file.includes("/") || file === "README.md" || !file.endsWith(".md") || path === nameToGuide(plan.blueprint.name)) continue;
3361
- const hosted = this.#reference(path, remaining);
3391
+ const hosted = this.#reference(path, MAX_TOTAL_ARTIFACT_BYTES - computeTotal(spent));
3362
3392
  if (hosted === void 0) continue;
3363
- remaining -= hosted.length / 2;
3393
+ spent.push(hosted.length / 2);
3364
3394
  const present = readFileHex(target, path);
3365
3395
  if (present !== void 0 && present !== hosted) questions.push({
3366
3396
  field: "guides",
@@ -3385,20 +3415,15 @@ var Materializer = class {
3385
3415
  return readFileHex(this.#root, path, Math.max(0, Math.min(MAX_ARTIFACT_BYTES, budget)));
3386
3416
  }
3387
3417
  #roots(plan) {
3388
- const roots = /* @__PURE__ */ new Set();
3389
- for (const artifact of plan.artifacts) {
3390
- if (artifact.origin !== "host") continue;
3418
+ return [...new Set(plan.artifacts.flatMap((artifact) => {
3419
+ if (artifact.origin !== "host") return [];
3391
3420
  const source = artifact.source ?? artifact.path;
3392
- if (this.#manifest?.roots.includes(source) === true) {
3393
- roots.add(artifact.path);
3394
- continue;
3395
- }
3396
- if (this.#manifest !== void 0) continue;
3421
+ if (this.#manifest?.roots.includes(source) === true) return [artifact.path];
3422
+ if (this.#manifest !== void 0) return [];
3397
3423
  const root = this.#root;
3398
3424
  const directory = root === void 0 ? void 0 : resolveContainedPath(root, source);
3399
- if (directory !== void 0 && isPhysicalDirectory(directory)) roots.add(artifact.path);
3400
- }
3401
- return [...roots];
3425
+ return directory !== void 0 && isPhysicalDirectory(directory) ? [artifact.path] : [];
3426
+ }))];
3402
3427
  }
3403
3428
  #expand(artifact, remaining) {
3404
3429
  const manifest = this.#manifest;
@@ -3411,15 +3436,15 @@ var Materializer = class {
3411
3436
  source
3412
3437
  });
3413
3438
  const expanded = [];
3414
- let budget = remaining;
3439
+ const spent = [];
3415
3440
  for (const entry of matched) {
3416
3441
  const path = this.#remap(artifact, entry.destination);
3417
3442
  if (isRetainedPath(path)) {
3418
3443
  expanded.push(this.#presence(artifact, path, entry.destination));
3419
3444
  continue;
3420
3445
  }
3421
- const hex = this.#read(entry, budget);
3422
- budget -= hex.length / 2;
3446
+ const hex = this.#read(entry, remaining - computeTotal(spent));
3447
+ spent.push(hex.length / 2);
3423
3448
  expanded.push(this.#hydrated(artifact, path, entry.destination, hex));
3424
3449
  }
3425
3450
  return expanded;
@@ -3440,7 +3465,7 @@ var Materializer = class {
3440
3465
  source
3441
3466
  });
3442
3467
  const expanded = [];
3443
- let budget = remaining;
3468
+ const spent = [];
3444
3469
  for (const name of listFiles(full)) {
3445
3470
  const path = `${artifact.path}/${name}`;
3446
3471
  const destination = `${source}/${name}`;
@@ -3448,8 +3473,8 @@ var Materializer = class {
3448
3473
  expanded.push(this.#presence(artifact, path, destination));
3449
3474
  continue;
3450
3475
  }
3451
- const hex = this.#readRoot(destination, budget);
3452
- budget -= hex.length / 2;
3476
+ const hex = this.#readRoot(destination, remaining - computeTotal(spent));
3477
+ spent.push(hex.length / 2);
3453
3478
  expanded.push(this.#hydrated(artifact, path, destination, hex));
3454
3479
  }
3455
3480
  return expanded;
@@ -3457,16 +3482,15 @@ var Materializer = class {
3457
3482
  #empty(plan) {
3458
3483
  const manifest = this.#manifest;
3459
3484
  if (manifest === void 0) return [];
3460
- const directories = /* @__PURE__ */ new Set();
3461
- for (const artifact of plan.artifacts) {
3462
- if (artifact.origin !== "host") continue;
3485
+ const directories = plan.artifacts.flatMap((artifact) => {
3486
+ if (artifact.origin !== "host") return [];
3463
3487
  const source = artifact.source ?? artifact.path;
3464
- for (const root of manifest.roots) {
3465
- if (root !== source && !root.startsWith(`${source}/`)) continue;
3466
- if (!manifest.entries.some((entry) => entry.destination === root || entry.destination.startsWith(`${root}/`))) directories.add(this.#remap(artifact, root));
3467
- }
3468
- }
3469
- return [...directories].sort();
3488
+ return manifest.roots.flatMap((root) => {
3489
+ if (root !== source && !root.startsWith(`${source}/`)) return [];
3490
+ return manifest.entries.some((entry) => entry.destination === root || entry.destination.startsWith(`${root}/`)) ? [] : [this.#remap(artifact, root)];
3491
+ });
3492
+ });
3493
+ return [...new Set(directories)].sort();
3470
3494
  }
3471
3495
  #remap(artifact, destination) {
3472
3496
  const source = artifact.source ?? artifact.path;
@@ -3663,11 +3687,7 @@ var Materializer = class {
3663
3687
  #fill(writes) {
3664
3688
  const value = this.#value;
3665
3689
  if (value === void 0) return void 0;
3666
- const destinations = /* @__PURE__ */ new Set();
3667
- for (const artifact of writes) {
3668
- if (artifact.origin !== "host") continue;
3669
- destinations.add(artifact.source ?? artifact.path);
3670
- }
3690
+ const destinations = new Set(writes.flatMap((artifact) => artifact.origin === "host" ? [artifact.source ?? artifact.path] : []));
3671
3691
  if (destinations.size === 0) return void 0;
3672
3692
  const opened = attempt(() => mkdtempSync(join(tmpdir(), "orkestrel-scaffold-fill-")));
3673
3693
  if (!opened.success) throw this.#error("WRITE", "The supplied host could not be filled into a private root.", { error: opened.error });
@@ -3737,8 +3757,7 @@ var Materializer = class {
3737
3757
  }
3738
3758
  #recatalog(entries) {
3739
3759
  const layers = catalogToLayers(entries);
3740
- const placed = /* @__PURE__ */ new Map();
3741
- for (const [index, layer] of layers.entries()) for (const name of layer) placed.set(name, index);
3760
+ const placed = new Map(layers.flatMap((layer, index) => layer.map((name) => [name, index])));
3742
3761
  const rows = entries.map((entry) => {
3743
3762
  if (entry.lookup !== "found") return [
3744
3763
  `\`${entry.name}\``,
@@ -3765,11 +3784,7 @@ var Materializer = class {
3765
3784
  "Runtime dependencies",
3766
3785
  "Peer dependencies"
3767
3786
  ];
3768
- const widths = headers.map((header, column) => {
3769
- let width = Math.max(3, header.length);
3770
- for (const row of rows) width = Math.max(width, row[column]?.length ?? 0);
3771
- return width;
3772
- });
3787
+ const widths = headers.map((header, column) => Math.max(3, header.length, ...rows.map((row) => row[column]?.length ?? 0)));
3773
3788
  const table = [
3774
3789
  headers,
3775
3790
  widths.map((width) => "-".repeat(width)),
@@ -3825,6 +3840,66 @@ var Materializer = class {
3825
3840
  }
3826
3841
  };
3827
3842
  //#endregion
3843
+ //#region src/server/ReadAllowance.ts
3844
+ /**
3845
+ * Represents the byte allowance one upstream call spends across every read it makes.
3846
+ *
3847
+ * @remarks
3848
+ * Each call constructs its own allowance from the reader's budget, so concurrent
3849
+ * calls never spend each other's bytes. A read that brings the call exactly to
3850
+ * its budget leaves `remaining` at zero and is accepted; the next request is
3851
+ * refused before it is sent, and a body that passes the budget is refused at the
3852
+ * chunk that overshoots.
3853
+ *
3854
+ * @example
3855
+ * ```ts
3856
+ * import { ReadAllowance } from '@orkestrel/scaffold/server'
3857
+ *
3858
+ * const allowance = new ReadAllowance(1_024)
3859
+ * allowance.spend(1_000)
3860
+ * allowance.remaining // 24
3861
+ * ```
3862
+ */
3863
+ var ReadAllowance = class {
3864
+ #remaining;
3865
+ /**
3866
+ * Constructs an allowance holding the whole budget.
3867
+ *
3868
+ * @param budget - The bytes the call may read in total.
3869
+ * @throws {@link ScaffoldError} coded `INVALID` when `budget` is not a
3870
+ * non-negative safe integer.
3871
+ */
3872
+ constructor(budget) {
3873
+ if (!isNonNegativeInteger(budget) || !Number.isSafeInteger(budget)) throw new ScaffoldError("INVALID", "The read budget is not a non-negative safe integer.", { field: "budget" });
3874
+ this.#remaining = budget;
3875
+ }
3876
+ /** The bytes the call has left; negative once a read overshoots the budget. */
3877
+ get remaining() {
3878
+ return this.#remaining;
3879
+ }
3880
+ /**
3881
+ * Spends bytes a read consumed from the allowance.
3882
+ *
3883
+ * @param bytes - The decoded bytes the read consumed.
3884
+ * @returns Nothing.
3885
+ * @throws {@link ScaffoldError} coded `INVALID` when `bytes` is not a
3886
+ * non-negative safe integer.
3887
+ *
3888
+ * @example
3889
+ * ```ts
3890
+ * import { ReadAllowance } from '@orkestrel/scaffold/server'
3891
+ *
3892
+ * const allowance = new ReadAllowance(10)
3893
+ * allowance.spend(12)
3894
+ * allowance.remaining // -2
3895
+ * ```
3896
+ */
3897
+ spend(bytes) {
3898
+ if (!isNonNegativeInteger(bytes) || !Number.isSafeInteger(bytes)) throw new ScaffoldError("INVALID", "The spent bytes are not a non-negative safe integer.", { field: "bytes" });
3899
+ this.#remaining -= bytes;
3900
+ }
3901
+ };
3902
+ //#endregion
3828
3903
  //#region src/server/Upstream.ts
3829
3904
  /**
3830
3905
  * Represents the reading spine: one bounded, unauthenticated, redirect-free request per answer.
@@ -3855,9 +3930,9 @@ var Materializer = class {
3855
3930
  * reader's own abort signal, so {@link Upstream.destroy} cancels what is in
3856
3931
  * flight instead of waiting for it.
3857
3932
  *
3858
- * The allowance is threaded through the private reads as a mutable
3859
- * {@link ReadAllowance} carrier rather than held on the instance, because
3860
- * concurrent calls each own their own budget and must not spend each other's.
3933
+ * Each call constructs its own {@link ReadAllowance} from the reader's budget and passes it
3934
+ * through the private reads rather than holding it on the instance, because concurrent calls
3935
+ * each own a budget and must not spend each other's.
3861
3936
  *
3862
3937
  * @example
3863
3938
  * ```ts
@@ -3950,7 +4025,7 @@ var Upstream = class {
3950
4025
  async lookup(dependencies) {
3951
4026
  this.#assertAlive();
3952
4027
  const accepted = this.#accept(dependencies, isDependencies, "dependencies");
3953
- const allowance = { remaining: this.#budget };
4028
+ const allowance = new ReadAllowance(this.#budget);
3954
4029
  return this.#gather(accepted, (dependency) => this.#release(dependency, allowance));
3955
4030
  }
3956
4031
  /**
@@ -3984,7 +4059,7 @@ var Upstream = class {
3984
4059
  this.#assertAlive();
3985
4060
  const accepted = this.#accept(names, isDependencyNames, "names");
3986
4061
  const observed = this.#accept(current, isSnapshot, "current");
3987
- const allowance = { remaining: this.#budget };
4062
+ const allowance = new ReadAllowance(this.#budget);
3988
4063
  return this.#gather(accepted, (name) => this.#mirror(name, observed, allowance));
3989
4064
  }
3990
4065
  /**
@@ -4031,7 +4106,7 @@ var Upstream = class {
4031
4106
  const accepted = this.#accept(paths, isPaths, "paths");
4032
4107
  const observed = this.#accept(current, isSnapshot, "current");
4033
4108
  if (accepted.length === 0) return [];
4034
- const allowance = { remaining: this.#budget };
4109
+ const allowance = new ReadAllowance(this.#budget);
4035
4110
  const inventory = await this.#inventory(allowance);
4036
4111
  return this.#gather(accepted, (path) => this.#file(path, inventory, observed, allowance));
4037
4112
  }
@@ -4064,7 +4139,7 @@ var Upstream = class {
4064
4139
  */
4065
4140
  async catalog() {
4066
4141
  this.#assertAlive();
4067
- const allowance = { remaining: this.#budget };
4142
+ const allowance = new ReadAllowance(this.#budget);
4068
4143
  const names = await this.#packages(allowance);
4069
4144
  return this.#gather(names, (name) => this.#entry(name, allowance));
4070
4145
  }
@@ -4233,16 +4308,10 @@ var Upstream = class {
4233
4308
  lookup: "failed",
4234
4309
  note: `the vendored inventory at ${url} does not match its own membership digest`
4235
4310
  };
4236
- const digests = /* @__PURE__ */ new Map();
4237
- const duplicates = /* @__PURE__ */ new Set();
4238
- for (const entry of manifest.entries) {
4239
- if (digests.has(entry.destination)) duplicates.add(entry.destination);
4240
- digests.set(entry.destination, entry.digest);
4241
- }
4242
4311
  return {
4243
4312
  lookup: "found",
4244
- digests,
4245
- duplicates,
4313
+ digests: new Map(manifest.entries.map((entry) => [entry.destination, entry.digest])),
4314
+ duplicates: new Set(manifest.entries.map((entry) => entry.destination).filter((destination, index, destinations) => destinations.indexOf(destination) !== index)),
4246
4315
  note: ""
4247
4316
  };
4248
4317
  }
@@ -4271,18 +4340,10 @@ var Upstream = class {
4271
4340
  if (!isRecord(manifest)) return [];
4272
4341
  const declared = manifest[section];
4273
4342
  if (!isRecord(declared)) return [];
4274
- const edges = [];
4275
- for (const [name, range] of Object.entries(declared)) {
4276
- if (edges.length >= MAX_COLLECTION_ITEMS) break;
4277
- if (!isString(range) || range.length === 0 || range.length > MAX_RANGE_LENGTH) continue;
4278
- if (CONTROL_CHARACTER_PATTERN.test(name) || CONTROL_CHARACTER_PATTERN.test(range)) continue;
4279
- if (name.length === 0 || name.length > MAX_DEPENDENCY_NAME_LENGTH) continue;
4280
- edges.push({
4281
- name,
4282
- range
4283
- });
4284
- }
4285
- return edges;
4343
+ return Object.entries(declared).flatMap(([name, range]) => !isString(range) || range.length === 0 || range.length > MAX_RANGE_LENGTH || CONTROL_CHARACTER_PATTERN.test(name) || CONTROL_CHARACTER_PATTERN.test(range) || name.length === 0 || name.length > MAX_DEPENDENCY_NAME_LENGTH ? [] : [{
4344
+ name,
4345
+ range
4346
+ }]).slice(0, MAX_COLLECTION_ITEMS);
4286
4347
  }
4287
4348
  async #packages(allowance) {
4288
4349
  const url = `${this.#registryBase}/-/org/${ORKESTREL_SCOPE}/package`;
@@ -4311,11 +4372,7 @@ var Upstream = class {
4311
4372
  const parsed = parseJSON(content);
4312
4373
  if (!isRecord(parsed)) return void 0;
4313
4374
  const versions = parsed.versions;
4314
- let selected;
4315
- if (isRecord(versions)) for (const version of Object.keys(versions)) {
4316
- if (!this.#admits(range, version)) continue;
4317
- if (selected === void 0 || compareVersions(version, selected) > 0) selected = version;
4318
- }
4375
+ const selected = isRecord(versions) ? Object.keys(versions).filter((version) => this.#admits(range, version)).reduce((highest, version) => highest === void 0 || compareVersions(version, highest) > 0 ? version : highest, void 0) : void 0;
4319
4376
  if (selected !== void 0) return selected;
4320
4377
  const latest = this.#latest(content);
4321
4378
  return latest !== void 0 && this.#admits(range, latest) ? latest : void 0;
@@ -4343,14 +4400,12 @@ var Upstream = class {
4343
4400
  #encode(path) {
4344
4401
  return path.split("/").map((segment) => encodeURIComponent(segment)).join("/");
4345
4402
  }
4346
- async #readWithRetries(url, timeout, allowance, accept, binary = false) {
4347
- let note = "";
4348
- for (let round = 0; round <= this.#retries; round += 1) {
4349
- this.#assertAlive();
4350
- const outcome = binary ? await this.#request(url, timeout, allowance, accept, true) : await this.#request(url, timeout, allowance, accept);
4351
- if (outcome.lookup !== "failed") return outcome;
4352
- note = outcome.note;
4353
- }
4403
+ async #readWithRetries(url, timeout, allowance, accept, binary = false, attempt = 0) {
4404
+ this.#assertAlive();
4405
+ const outcome = binary ? await this.#request(url, timeout, allowance, accept, true) : await this.#request(url, timeout, allowance, accept);
4406
+ if (outcome.lookup !== "failed") return outcome;
4407
+ if (attempt < this.#retries) return binary ? this.#readWithRetries(url, timeout, allowance, accept, true, attempt + 1) : this.#readWithRetries(url, timeout, allowance, accept, false, attempt + 1);
4408
+ const note = outcome.note;
4354
4409
  this.#error("FETCH", `The upstream read at ${url} produced no answer.`, {
4355
4410
  url,
4356
4411
  note
@@ -4454,14 +4509,14 @@ var Upstream = class {
4454
4509
  const reader = body.getReader();
4455
4510
  const decoder = binary ? void 0 : new TextDecoder("utf-8", { fatal: true });
4456
4511
  const chunks = [];
4457
- let total = 0;
4512
+ const sizes = [];
4458
4513
  try {
4459
4514
  for (;;) {
4460
4515
  const chunk = await reader.read();
4461
4516
  if (chunk.done) break;
4462
- total += chunk.value.byteLength;
4463
- allowance.remaining -= chunk.value.byteLength;
4464
- if (total > this.#limit) {
4517
+ sizes.push(chunk.value.byteLength);
4518
+ allowance.spend(chunk.value.byteLength);
4519
+ if (computeTotal(sizes) > this.#limit) {
4465
4520
  await reader.cancel();
4466
4521
  const note = `the response passed the ${String(this.#limit)}-byte response limit`;
4467
4522
  return binary ? {
@@ -4514,31 +4569,28 @@ var Upstream = class {
4514
4569
  return code === void 0 ? message : `${message} (${code})`;
4515
4570
  }
4516
4571
  async #gather(items, run) {
4517
- const results = [];
4518
- const state = {
4519
- cursor: 0,
4520
- failure: void 0
4521
- };
4522
- const workers = Array.from({ length: Math.min(this.#concurrency, items.length) }, () => this.#drain(items, run, results, state));
4523
- await Promise.allSettled(workers);
4524
- if (state.failure !== void 0) throw state.failure.error;
4525
- return results;
4572
+ const entries = items.entries();
4573
+ const failed = new AbortController();
4574
+ const workers = Array.from({ length: Math.min(this.#concurrency, items.length) }, () => this.#drain(entries, run, failed));
4575
+ const settled = await Promise.allSettled(workers);
4576
+ if (failed.signal.aborted) {
4577
+ const reason = failed.signal.reason;
4578
+ throw isRecord(reason) ? reason.error : reason;
4579
+ }
4580
+ return collectIndexed(settled.flatMap((worker) => worker.status === "fulfilled" ? worker.value : []));
4526
4581
  }
4527
- async #drain(items, run, results, state) {
4528
- for (;;) {
4529
- if (state.failure !== void 0) return;
4530
- const index = state.cursor;
4531
- state.cursor += 1;
4532
- if (index >= items.length) return;
4533
- const item = items[index];
4534
- if (item === void 0) return;
4582
+ async #drain(entries, run, failed) {
4583
+ const produced = [];
4584
+ for (const [index, item] of entries) {
4585
+ if (failed.signal.aborted || item === void 0) break;
4535
4586
  try {
4536
- results[index] = await run(item);
4587
+ produced.push([index, await run(item)]);
4537
4588
  } catch (error) {
4538
- state.failure ??= { error };
4539
- return;
4589
+ failed.abort(Object.freeze({ error }));
4590
+ break;
4540
4591
  }
4541
4592
  }
4593
+ return produced;
4542
4594
  }
4543
4595
  #accept(value, guard, field) {
4544
4596
  const snapshot = cloneValue(value);
@@ -4555,6 +4607,6 @@ var Upstream = class {
4555
4607
  }
4556
4608
  };
4557
4609
  //#endregion
4558
- export { BRANCH_PATTERN, DEFAULT_BRANCH, DEFAULT_REGISTRY_BASE, DEFAULT_REPOSITORY_BASE, DEFAULT_UPSTREAM_CONCURRENCY, DEFAULT_UPSTREAM_RETRIES, DEFAULT_UPSTREAM_TIMEOUT, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, ORKESTREL_SCOPE, PACKUMENT_MEDIA_TYPE, RESERVED_SEGMENT_PATTERN, SCAFFOLD_REPOSITORY, UNREADABLE_VERSION_NOTE, Upstream, WriteTransaction, computeDigest, computeFileDigest, computeManifestDigest, decodeHexText, filesToHost, hexToDigest, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHost, isHostManifest, isInventory, isManifestEntry, isManifestRegionSet, isMaterializerHooks, isMaterializerOptions, isMirrors, isPaths, isPhysicalDirectory, isPhysicalFile, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, isWorktree, listCanonPaths, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, pruneEmptiedDirectories, readAnchor, readExpectation, readFileHex, readFileText, readHostFloor, readHostManifest, readManifestEntry, readSnapshot, readSurfaceBaseline, readSurfaceCollisions, resolveContainedPath, resolveRealPath, stageBytes, stageHost, stageInventory };
4610
+ export { BRANCH_PATTERN, DEFAULT_BRANCH, DEFAULT_REGISTRY_BASE, DEFAULT_REPOSITORY_BASE, DEFAULT_UPSTREAM_CONCURRENCY, DEFAULT_UPSTREAM_RETRIES, DEFAULT_UPSTREAM_TIMEOUT, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, ORKESTREL_SCOPE, PACKUMENT_MEDIA_TYPE, RESERVED_SEGMENT_PATTERN, ReadAllowance, SCAFFOLD_REPOSITORY, UNREADABLE_VERSION_NOTE, Upstream, WriteTransaction, climbRealPath, collectIndexed, computeDigest, computeFileDigest, computeManifestDigest, decodeHexText, filesToHost, hexToDigest, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHost, isHostManifest, isInventory, isManifestEntry, isManifestRegionSet, isMaterializerHooks, isMaterializerOptions, isMirrors, isPaths, isPhysicalDirectory, isPhysicalFile, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, isWorktree, listAncestors, listCanonPaths, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, pruneEmptiedDirectories, readAnchor, readExpectation, readFileHex, readFileText, readHostFloor, readHostManifest, readManifestEntry, readSnapshot, readSurfaceBaseline, readSurfaceCollisions, resolveContainedPath, resolveRealPath, stageBytes, stageHost, stageInventory };
4559
4611
 
4560
4612
  //# sourceMappingURL=index.js.map