@hawkeyexl/manni 2.8.2 → 2.8.4

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.
@@ -8,7 +8,7 @@ var __export = (target, all) => {
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@hawkeyexl/manni",
11
- version: "2.8.2",
11
+ version: "2.8.4",
12
12
  description: "One command line for documentation that is meant to be checked. `manni meta` validates the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema, built for CI. Formerly docmeta.",
13
13
  type: "module",
14
14
  bin: {
@@ -393,8 +393,8 @@ function isMember(collection, relPath) {
393
393
  return !collection.exclude.some((glob) => matchesFileGlob(relPath, glob));
394
394
  }
395
395
  function normalizeEntry(entry) {
396
- const posix4 = entry.replace(/\\/g, "/").replace(/^\.\//, "");
397
- return posix4.endsWith("/") ? posix4.slice(0, -1) : posix4;
396
+ const posix5 = entry.replace(/\\/g, "/").replace(/^\.\//, "");
397
+ return posix5.endsWith("/") ? posix5.slice(0, -1) : posix5;
398
398
  }
399
399
  function isGlob(entry) {
400
400
  return picomatch2.scan(entry).isGlob;
@@ -2731,15 +2731,66 @@ function listFormats() {
2731
2731
  }
2732
2732
 
2733
2733
  // src/meta/core/write-file.ts
2734
- import { writeFile, rename, rm, stat, chmod } from "node:fs/promises";
2735
- import { dirname, join, basename } from "node:path";
2734
+ import { writeFile, rename, rm, stat as stat2, chmod } from "node:fs/promises";
2735
+ import { dirname, join, basename, resolve } from "node:path";
2736
+
2737
+ // src/meta/core/manifest-cache.ts
2738
+ import { stat } from "node:fs/promises";
2739
+ var caches = /* @__PURE__ */ new Set();
2740
+ function register(cache) {
2741
+ caches.add(new WeakRef(cache));
2742
+ }
2743
+ function invalidateManifestCache(path) {
2744
+ for (const ref of caches) {
2745
+ const cache = ref.deref();
2746
+ if (cache === void 0) caches.delete(ref);
2747
+ else cache.drop(path);
2748
+ }
2749
+ }
2750
+ async function signature(path) {
2751
+ try {
2752
+ const info = await stat(path);
2753
+ return { mtimeMs: info.mtimeMs, size: info.size };
2754
+ } catch {
2755
+ return null;
2756
+ }
2757
+ }
2758
+ var same = (a, b) => a.mtimeMs === b.mtimeMs && a.size === b.size;
2759
+ var ManifestCache = class {
2760
+ slots = /* @__PURE__ */ new Map();
2761
+ constructor() {
2762
+ register(this);
2763
+ }
2764
+ drop(path) {
2765
+ this.slots.delete(path);
2766
+ }
2767
+ /** The cached parse of `path` under `variant`, or `compute()`'s result. */
2768
+ async parse(path, variant, compute) {
2769
+ const before = await signature(path);
2770
+ if (before === null) return compute();
2771
+ const slot = this.slots.get(path);
2772
+ if (slot !== void 0 && same(slot.sig, before)) {
2773
+ const hit = slot.variants.get(variant);
2774
+ if (hit !== void 0) return hit;
2775
+ }
2776
+ const parsed2 = await compute();
2777
+ const after = await signature(path);
2778
+ if (after === null || !same(before, after)) return parsed2;
2779
+ const live = this.slots.get(path);
2780
+ if (live !== void 0 && same(live.sig, after)) live.variants.set(variant, parsed2);
2781
+ else this.slots.set(path, { sig: after, variants: /* @__PURE__ */ new Map([[variant, parsed2]]) });
2782
+ return parsed2;
2783
+ }
2784
+ };
2785
+
2786
+ // src/meta/core/write-file.ts
2736
2787
  var LOCKED = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES"]);
2737
2788
  var RENAME_ATTEMPTS = 3;
2738
2789
  function errorCode(err) {
2739
2790
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
2740
2791
  }
2741
- var wait = (ms) => new Promise((resolve21) => {
2742
- setTimeout(resolve21, ms);
2792
+ var wait = (ms) => new Promise((resolve22) => {
2793
+ setTimeout(resolve22, ms);
2743
2794
  });
2744
2795
  async function writeFileAtomic(path, contents) {
2745
2796
  const tmp = join(
@@ -2749,7 +2800,7 @@ async function writeFileAtomic(path, contents) {
2749
2800
  try {
2750
2801
  await writeFile(tmp, contents);
2751
2802
  try {
2752
- const { mode } = await stat(path);
2803
+ const { mode } = await stat2(path);
2753
2804
  await chmod(tmp, mode);
2754
2805
  } catch {
2755
2806
  }
@@ -2776,12 +2827,13 @@ async function writeFileAtomic(path, contents) {
2776
2827
  }
2777
2828
  } finally {
2778
2829
  await rm(tmp, { force: true });
2830
+ invalidateManifestCache(resolve(path));
2779
2831
  }
2780
2832
  }
2781
2833
 
2782
2834
  // src/meta/core/schema-cache.ts
2783
2835
  import { createHash as createHash2 } from "node:crypto";
2784
- import { mkdir, readFile, stat as stat2 } from "node:fs/promises";
2836
+ import { mkdir, readFile, stat as stat3 } from "node:fs/promises";
2785
2837
  import { join as join2 } from "node:path";
2786
2838
  var SCHEMA_CACHE_DIR = ".manni/meta/schema-cache";
2787
2839
  var SCHEMA_CACHE_VERSION = 1;
@@ -2828,7 +2880,7 @@ var SchemaCache = class {
2828
2880
  if (options.ignoreTtl !== true) {
2829
2881
  let mtimeMs;
2830
2882
  try {
2831
- ({ mtimeMs } = await stat2(file));
2883
+ ({ mtimeMs } = await stat3(file));
2832
2884
  } catch {
2833
2885
  return null;
2834
2886
  }
@@ -5292,8 +5344,8 @@ var SCHEMA_KEYS = [
5292
5344
  "multipleOf"
5293
5345
  ];
5294
5346
  var RETRY_DELAY_MS = 500;
5295
- var wait2 = (ms) => new Promise((resolve21) => {
5296
- setTimeout(resolve21, ms);
5347
+ var wait2 = (ms) => new Promise((resolve22) => {
5348
+ setTimeout(resolve22, ms);
5297
5349
  });
5298
5350
  var RetryableFetchError = class extends DocmetaError {
5299
5351
  };
@@ -5546,7 +5598,7 @@ async function loadSchema(ref, options = {}) {
5546
5598
  }
5547
5599
 
5548
5600
  // src/meta/core/resolve-schema.ts
5549
- import { isAbsolute, relative, resolve } from "node:path";
5601
+ import { isAbsolute, relative, resolve as resolve2 } from "node:path";
5550
5602
  var DEFAULT_SCHEMAS = Object.freeze([
5551
5603
  "google:okf:0.1",
5552
5604
  "passo-uno:seven-action:1.0"
@@ -5568,12 +5620,12 @@ function collectSchemaPins(config) {
5568
5620
  return pins;
5569
5621
  }
5570
5622
  function rebaseConfigSchemaRefs(config, configDir, cwd) {
5571
- if (resolve(configDir) === resolve(cwd)) return config;
5572
- const rebase = (ref) => classifyRef(ref).kind === "file" && !isAbsolute(ref) ? resolve(configDir, ref) : ref;
5573
- const rebaseEntry = (entry) => typeof entry === "string" ? rebase(entry) : {
5623
+ if (resolve2(configDir) === resolve2(cwd)) return config;
5624
+ const rebase2 = (ref) => classifyRef(ref).kind === "file" && !isAbsolute(ref) ? resolve2(configDir, ref) : ref;
5625
+ const rebaseEntry = (entry) => typeof entry === "string" ? rebase2(entry) : {
5574
5626
  ...entry,
5575
- ref: rebase(entry.ref),
5576
- ...entry.source !== void 0 ? { source: rebase(entry.source) } : {}
5627
+ ref: rebase2(entry.ref),
5628
+ ...entry.source !== void 0 ? { source: rebase2(entry.source) } : {}
5577
5629
  };
5578
5630
  return {
5579
5631
  ...config,
@@ -5581,7 +5633,7 @@ function rebaseConfigSchemaRefs(config, configDir, cwd) {
5581
5633
  ...config.overrides ? {
5582
5634
  overrides: config.overrides.map((o) => ({
5583
5635
  ...o,
5584
- schemas: o.schemas.map(rebase)
5636
+ schemas: o.schemas.map(rebase2)
5585
5637
  }))
5586
5638
  } : {}
5587
5639
  };
@@ -5645,7 +5697,7 @@ function assertDocumentRefAllowed(ref, mode, params) {
5645
5697
  }
5646
5698
  const root = params.trustRoot;
5647
5699
  if (!root) return;
5648
- const abs = resolve(params.fileBase ?? process.cwd(), ref);
5700
+ const abs = resolve2(params.fileBase ?? process.cwd(), ref);
5649
5701
  const within = relative(root.dir, abs);
5650
5702
  if (within !== "" && !within.startsWith("..") && !isAbsolute(within)) return;
5651
5703
  const boundary = root.source === "git" ? `the repository root (${root.dir})` : root.source === "config" ? `${root.dir} \u2014 no git repository was found, so the config file's own directory is the boundary` : `${root.dir} \u2014 no git repository and no config file were found, so the directory the command was run from is the boundary`;
@@ -5797,12 +5849,12 @@ function isPlainObject(v) {
5797
5849
  }
5798
5850
 
5799
5851
  // src/meta/core/config.ts
5800
- import { resolve as resolve5 } from "node:path";
5852
+ import { resolve as resolve6 } from "node:path";
5801
5853
  import { parse as parseYaml2 } from "yaml";
5802
5854
 
5803
5855
  // src/shared/config-file.ts
5804
5856
  import { readFile as readFile3 } from "node:fs/promises";
5805
- import { basename as basename2, dirname as dirname3, join as join4, relative as relative2, resolve as resolve4 } from "node:path";
5857
+ import { basename as basename2, dirname as dirname3, join as join4, relative as relative2, resolve as resolve5 } from "node:path";
5806
5858
  import { parse as parseYaml } from "yaml";
5807
5859
 
5808
5860
  // src/shared/encryption.ts
@@ -5933,9 +5985,9 @@ function keyedPin(text2, key) {
5933
5985
 
5934
5986
  // src/shared/git-root.ts
5935
5987
  import { existsSync } from "node:fs";
5936
- import { dirname as dirname2, join as join3, resolve as resolve2 } from "node:path";
5988
+ import { dirname as dirname2, join as join3, resolve as resolve3 } from "node:path";
5937
5989
  function findGitRoot(cwd) {
5938
- let dir = resolve2(cwd);
5990
+ let dir = resolve3(cwd);
5939
5991
  for (; ; ) {
5940
5992
  if (existsSync(join3(dir, ".git"))) return dir;
5941
5993
  const parent = dirname2(dir);
@@ -5944,7 +5996,7 @@ function findGitRoot(cwd) {
5944
5996
  }
5945
5997
  }
5946
5998
  function searchPath(cwd) {
5947
- const start = resolve2(cwd);
5999
+ const start = resolve3(cwd);
5948
6000
  const root = findGitRoot(start);
5949
6001
  if (root === null) return [start];
5950
6002
  const chain = [];
@@ -5959,7 +6011,7 @@ function searchPath(cwd) {
5959
6011
  }
5960
6012
 
5961
6013
  // src/shared/tools.ts
5962
- import { isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
6014
+ import { isAbsolute as isAbsolute2, resolve as resolve4 } from "node:path";
5963
6015
  var TOOL_KEYS = ["vale"];
5964
6016
  var VALE_KEYS = ["config"];
5965
6017
  function isMapping2(value) {
@@ -6004,7 +6056,7 @@ function parseVale(raw, source, toError) {
6004
6056
  function valeConfigPath(tools, configDir) {
6005
6057
  const config = tools.vale?.config;
6006
6058
  if (config === void 0) return void 0;
6007
- return isAbsolute2(config) ? config : resolve3(configDir, config);
6059
+ return isAbsolute2(config) ? config : resolve4(configDir, config);
6008
6060
  }
6009
6061
 
6010
6062
  // src/shared/warn.ts
@@ -6119,7 +6171,7 @@ var FAMILY_FILES = [
6119
6171
  { names: MOOSE_CONFIG_NAMES, kind: "moose" }
6120
6172
  ];
6121
6173
  async function findConfigFile(cwd, opts) {
6122
- const start = resolve4(cwd);
6174
+ const start = resolve5(cwd);
6123
6175
  for (const dir of searchPath(start)) {
6124
6176
  for (const { names, kind } of FAMILY_FILES) {
6125
6177
  for (const name2 of names) {
@@ -6167,7 +6219,7 @@ async function findConfigFile(cwd, opts) {
6167
6219
  return null;
6168
6220
  }
6169
6221
  async function readConfigFile(explicitPath, cwd, opts) {
6170
- const path = resolve4(cwd, explicitPath);
6222
+ const path = resolve5(cwd, explicitPath);
6171
6223
  const document = await readDocument(path, explicitPath, opts.toError);
6172
6224
  if (document === null) {
6173
6225
  throw opts.toError(`Config file not found: "${explicitPath}".`);
@@ -6191,7 +6243,7 @@ async function readConfigFile(explicitPath, cwd, opts) {
6191
6243
  };
6192
6244
  }
6193
6245
  async function findFamilyConfigFile(cwd, toError) {
6194
- const start = resolve4(cwd);
6246
+ const start = resolve5(cwd);
6195
6247
  for (const dir of searchPath(start)) {
6196
6248
  for (const { names, kind } of FAMILY_FILES) {
6197
6249
  for (const name2 of names) {
@@ -6218,7 +6270,7 @@ async function findFamilyConfigFile(cwd, toError) {
6218
6270
  return null;
6219
6271
  }
6220
6272
  async function readFamilyConfigFile(explicitPath, cwd, toError) {
6221
- const path = resolve4(cwd, explicitPath);
6273
+ const path = resolve5(cwd, explicitPath);
6222
6274
  const document = await readDocument(path, explicitPath, toError);
6223
6275
  if (document === null) {
6224
6276
  throw toError(`Config file not found: "${explicitPath}".`);
@@ -6887,8 +6939,8 @@ function parseFill(value, source) {
6887
6939
  function schemaTrustRoot(cwd, configDir) {
6888
6940
  const git2 = findGitRoot(cwd);
6889
6941
  if (git2 !== null) return { dir: git2, source: "git" };
6890
- if (configDir !== void 0) return { dir: resolve5(configDir), source: "config" };
6891
- return { dir: resolve5(cwd), source: "cwd" };
6942
+ if (configDir !== void 0) return { dir: resolve6(configDir), source: "config" };
6943
+ return { dir: resolve6(cwd), source: "cwd" };
6892
6944
  }
6893
6945
  async function loadConfig(explicitPath, cwd = process.cwd()) {
6894
6946
  const file = explicitPath ? await readConfigFile(explicitPath, cwd, CONFIG_FILE) : await findConfigFile(cwd, CONFIG_FILE);
@@ -6957,17 +7009,17 @@ import { isAbsolute as isAbsolute3 } from "node:path";
6957
7009
  import { createHash as createHash3 } from "node:crypto";
6958
7010
  import { existsSync as existsSync2 } from "node:fs";
6959
7011
  import { readFile as readFile4 } from "node:fs/promises";
6960
- import { relative as relative5, resolve as resolve8 } from "node:path";
7012
+ import { relative as relative5, resolve as resolve9 } from "node:path";
6961
7013
 
6962
7014
  // src/meta/core/load-files.ts
6963
- import { stat as stat3 } from "node:fs/promises";
6964
- import { extname, relative as relative4, resolve as resolve7 } from "node:path";
7015
+ import { stat as stat4 } from "node:fs/promises";
7016
+ import { extname, relative as relative4, resolve as resolve8 } from "node:path";
6965
7017
  import fg from "fast-glob";
6966
7018
  import picomatch3 from "picomatch";
6967
7019
 
6968
7020
  // src/meta/core/gitignore.ts
6969
7021
  import { spawn } from "node:child_process";
6970
- import { dirname as dirname4, relative as relative3, resolve as resolve6, sep } from "node:path";
7022
+ import { dirname as dirname4, relative as relative3, resolve as resolve7, sep } from "node:path";
6971
7023
  var GITIGNORE_UNAVAILABLE = ".gitignore filtering was requested but git could not answer here (no repository, or no git on PATH); no files were skipped.";
6972
7024
  var unavailable = () => ({
6973
7025
  ignored: /* @__PURE__ */ new Set(),
@@ -6981,7 +7033,7 @@ async function gitIgnored(paths, cwd) {
6981
7033
  const byRoot = /* @__PURE__ */ new Map();
6982
7034
  let inSomeRepo = false;
6983
7035
  for (const spelled of paths) {
6984
- const abs = resolve6(cwd, spelled);
7036
+ const abs = resolve7(cwd, spelled);
6985
7037
  const dir = dirname4(abs);
6986
7038
  let root = rootOf.get(dir);
6987
7039
  if (root === void 0) {
@@ -7012,12 +7064,12 @@ async function gitIgnored(paths, cwd) {
7012
7064
  return answered > 0 ? { ignored, available: true } : unavailable();
7013
7065
  }
7014
7066
  function checkIgnore(paths, cwd) {
7015
- return new Promise((settle) => {
7067
+ return new Promise((settle2) => {
7016
7068
  let done = false;
7017
7069
  const finish2 = (answer) => {
7018
7070
  if (done) return;
7019
7071
  done = true;
7020
- settle(answer);
7072
+ settle2(answer);
7021
7073
  };
7022
7074
  let child;
7023
7075
  try {
@@ -7063,7 +7115,7 @@ function toPosix(p) {
7063
7115
  }
7064
7116
  async function statOrNull(p) {
7065
7117
  try {
7066
- return await stat3(p);
7118
+ return await stat4(p);
7067
7119
  } catch {
7068
7120
  return null;
7069
7121
  }
@@ -7093,7 +7145,7 @@ async function resolveTargetSet(opts) {
7093
7145
  for (const input of opts.inputs) {
7094
7146
  if (input === STDIN_TOKEN) continue;
7095
7147
  const posixInput = toPosix(input);
7096
- const abs = resolve7(cwd, posixInput);
7148
+ const abs = resolve8(cwd, posixInput);
7097
7149
  const st = await statOrNull(abs);
7098
7150
  if (st?.isFile()) {
7099
7151
  named.add(toPosix(relative4(cwd, abs)));
@@ -7178,12 +7230,12 @@ var FINGERPRINT_RE = /^[0-9a-f]{16}$/;
7178
7230
  function canonicalFilePath(file, ctx) {
7179
7231
  if (!ctx) return file;
7180
7232
  const from = ctx.runBase ?? ctx.base;
7181
- return relative5(ctx.base, resolve8(from, file)).replace(/\\/g, "/");
7233
+ return relative5(ctx.base, resolve9(from, file)).replace(/\\/g, "/");
7182
7234
  }
7183
7235
  function canonicalSchemaRef(ref, ctx) {
7184
7236
  if (!ctx) return ref;
7185
7237
  if (classifyRef(ref).kind !== "file") return ref;
7186
- const abs = resolve8(ctx.cwd, ref);
7238
+ const abs = resolve9(ctx.cwd, ref);
7187
7239
  return relative5(ctx.base, abs).replace(/\\/g, "/");
7188
7240
  }
7189
7241
  function fingerprint(e, ctx) {
@@ -7341,17 +7393,17 @@ function countFingerprints(baseline) {
7341
7393
  }
7342
7394
  function resolveBaselineRequest(opts, configured, configDir, cwd, defaults) {
7343
7395
  const named = (label) => ({
7344
- absPath: resolve8(cwd, label),
7396
+ absPath: resolve9(cwd, label),
7345
7397
  label
7346
7398
  });
7347
7399
  const implied = () => {
7348
7400
  const base = configDir ?? cwd;
7349
7401
  if (configured !== void 0) {
7350
- return { absPath: resolve8(base, configured), label: configured };
7402
+ return { absPath: resolve9(base, configured), label: configured };
7351
7403
  }
7352
- const current = resolve8(base, defaults.current);
7404
+ const current = resolve9(base, defaults.current);
7353
7405
  if (defaults.legacy !== void 0) {
7354
- const legacy = resolve8(base, defaults.legacy);
7406
+ const legacy = resolve9(base, defaults.legacy);
7355
7407
  if (!existsSync2(current) && existsSync2(legacy)) {
7356
7408
  warn(
7357
7409
  `"${defaults.legacy}" is the pre-rename baseline file name. Rename it to "${defaults.current}".`
@@ -7858,7 +7910,7 @@ async function readCapped(url, res, maxBytes) {
7858
7910
 
7859
7911
  // src/meta/core/external-metadata.ts
7860
7912
  import { readFile as readFile6 } from "node:fs/promises";
7861
- import { isAbsolute as isAbsolute4, relative as relative7, resolve as resolve10, sep as sep2 } from "node:path";
7913
+ import { isAbsolute as isAbsolute4, relative as relative7, resolve as resolve11, sep as sep2 } from "node:path";
7862
7914
  import {
7863
7915
  LineCounter as LineCounter2,
7864
7916
  isMap as isMap4,
@@ -7871,20 +7923,20 @@ import {
7871
7923
  // src/shared/encryption-key.ts
7872
7924
  import { spawnSync } from "node:child_process";
7873
7925
  import { readFile as readFile5 } from "node:fs/promises";
7874
- import { basename as basename4, dirname as dirname6, join as join6, relative as relative6, resolve as resolve9 } from "node:path";
7926
+ import { basename as basename4, dirname as dirname6, join as join6, relative as relative6, resolve as resolve10 } from "node:path";
7875
7927
  import { isDeepStrictEqual } from "node:util";
7876
7928
  import { isMap as isMap3, parseDocument as parseDocument3, parse as parseYaml3, stringify } from "yaml";
7877
7929
 
7878
7930
  // src/shared/write-file.ts
7879
- import { chmod as chmod2, rename as rename2, rm as rm2, stat as stat4, writeFile as writeFile2 } from "node:fs/promises";
7931
+ import { chmod as chmod2, rename as rename2, rm as rm2, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
7880
7932
  import { basename as basename3, dirname as dirname5, join as join5 } from "node:path";
7881
7933
  var LOCKED2 = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES"]);
7882
7934
  var RENAME_ATTEMPTS2 = 3;
7883
7935
  function errorCode2(err) {
7884
7936
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
7885
7937
  }
7886
- var wait3 = (ms) => new Promise((resolve21) => {
7887
- setTimeout(resolve21, ms);
7938
+ var wait3 = (ms) => new Promise((resolve22) => {
7939
+ setTimeout(resolve22, ms);
7888
7940
  });
7889
7941
  async function writeTextAtomic(path, text2) {
7890
7942
  const tmp = join5(
@@ -7894,7 +7946,7 @@ async function writeTextAtomic(path, text2) {
7894
7946
  try {
7895
7947
  await writeFile2(tmp, text2, "utf8");
7896
7948
  try {
7897
- const { mode } = await stat4(path);
7949
+ const { mode } = await stat5(path);
7898
7950
  await chmod2(tmp, mode);
7899
7951
  } catch {
7900
7952
  }
@@ -7933,7 +7985,7 @@ function resolveEncryptionKey(opts) {
7933
7985
  return { key: void 0, source: "none" };
7934
7986
  }
7935
7987
  function relativeSource2(cwd, path) {
7936
- return relative6(resolve9(cwd), path).replace(/\\/g, "/");
7988
+ return relative6(resolve10(cwd), path).replace(/\\/g, "/");
7937
7989
  }
7938
7990
  function errorCode3(err) {
7939
7991
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
@@ -7956,7 +8008,7 @@ async function fileTarget(file, toError) {
7956
8008
  return { path: file.path, source: file.source, text: text2 ?? file.text };
7957
8009
  }
7958
8010
  async function defaultTarget(cwd) {
7959
- const root = findGitRoot(cwd) ?? resolve9(cwd);
8011
+ const root = findGitRoot(cwd) ?? resolve10(cwd);
7960
8012
  for (const name2 of [...FAMILY_CONFIG_NAMES, ...MOOSE_CONFIG_NAMES]) {
7961
8013
  const path2 = join6(root, name2);
7962
8014
  const text2 = await readIfPresent(path2);
@@ -8242,11 +8294,15 @@ var EXTERNAL_OWNED_SCHEMA = "external:owned";
8242
8294
  var EXTERNAL_DUPLICATE_SCHEMA = "external:duplicate";
8243
8295
  var EXTERNAL_KEYWORD = "external";
8244
8296
  var PATH_JOIN = "path";
8297
+ var parsedManifests = new ManifestCache();
8245
8298
  var posix = (p) => p.split(sep2).join("/");
8246
8299
  function reportedPath(abs, base) {
8247
8300
  const rel = relative7(base, abs);
8248
8301
  return rel === "" ? "." : posix(rel);
8249
8302
  }
8303
+ function reported(of, file) {
8304
+ return of.file === file ? of : { ...of, file };
8305
+ }
8250
8306
  function externalMetadataJoin(manifest) {
8251
8307
  return manifest.join ?? PATH_JOIN;
8252
8308
  }
@@ -8260,27 +8316,56 @@ async function loadExternalMetadata(collections, opts) {
8260
8316
  const byField = /* @__PURE__ */ new Map();
8261
8317
  const entries = [];
8262
8318
  for (const { collection, manifest } of configured) {
8263
- let text2;
8319
+ const join11 = externalMetadataJoin(manifest);
8320
+ let parsed2;
8264
8321
  let file;
8265
8322
  if (classifyRef(manifest.file).kind === "url") {
8266
8323
  file = manifest.file;
8267
- text2 = await fetchExternalMetadata(manifest.file, {
8324
+ const text2 = await fetchExternalMetadata(manifest.file, {
8268
8325
  ...manifest.tokenEnv !== void 0 ? { tokenEnv: manifest.tokenEnv } : {},
8269
8326
  ...opts.offline !== void 0 ? { offline: opts.offline } : {},
8270
8327
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
8271
8328
  ...opts.env !== void 0 ? { env: opts.env } : {}
8272
8329
  });
8330
+ parsed2 = parseManifest(manifest, collection, text2, file, opts.configDir, join11);
8273
8331
  } else {
8274
- const abs = isAbsolute4(manifest.file) ? manifest.file : resolve10(opts.configDir, manifest.file);
8275
- file = reportedPath(abs, opts.base);
8276
- text2 = await readManifest(abs, file);
8332
+ const abs = isAbsolute4(manifest.file) ? manifest.file : resolve11(opts.configDir, manifest.file);
8333
+ const label = reportedPath(abs, opts.base);
8334
+ file = label;
8335
+ parsed2 = await parsedManifests.parse(
8336
+ abs,
8337
+ // The keys are sorted because they reach the variant as an array, and
8338
+ // two declarations that own the same keys in a different order parse
8339
+ // to the same thing.
8340
+ //
8341
+ // `label` is deliberately not part of this. It is the manifest as this
8342
+ // run reports it, which is a function of the run's base rather than of
8343
+ // the bytes, so two runs over one corpus from two directories parse
8344
+ // identically and differ only in a string each value carries. Keying
8345
+ // on it would miss the cache for exactly the runs that share a
8346
+ // process, which is what a test suite is. The copy-in below writes
8347
+ // this run's spelling onto every value and entry instead.
8348
+ JSON.stringify([
8349
+ collection,
8350
+ join11,
8351
+ opts.configDir,
8352
+ [...manifest.keys].sort()
8353
+ ]),
8354
+ async () => parseManifest(
8355
+ manifest,
8356
+ collection,
8357
+ await readManifest(abs, label),
8358
+ label,
8359
+ opts.configDir,
8360
+ join11
8361
+ )
8362
+ );
8277
8363
  }
8278
8364
  for (const key of manifest.keys) {
8279
8365
  const list2 = owners.get(key);
8280
8366
  if (list2) list2.push({ collection, file });
8281
8367
  else owners.set(key, [{ collection, file }]);
8282
8368
  }
8283
- const join11 = externalMetadataJoin(manifest);
8284
8369
  let target;
8285
8370
  if (join11 === PATH_JOIN) {
8286
8371
  target = byPath;
@@ -8292,16 +8377,12 @@ async function loadExternalMetadata(collections, opts) {
8292
8377
  byField.set(join11, target);
8293
8378
  }
8294
8379
  }
8295
- parseManifest(
8296
- manifest,
8297
- collection,
8298
- text2,
8299
- file,
8300
- opts.configDir,
8301
- join11,
8302
- target,
8303
- entries
8304
- );
8380
+ for (const [indexKey, values] of parsed2.values) {
8381
+ const into = target.get(indexKey) ?? /* @__PURE__ */ new Map();
8382
+ for (const [key, value] of values) into.set(key, reported(value, file));
8383
+ target.set(indexKey, into);
8384
+ }
8385
+ for (const entry of parsed2.entries) entries.push(reported(entry, file));
8305
8386
  }
8306
8387
  return { owners, byPath, byField, entries };
8307
8388
  }
@@ -8315,7 +8396,9 @@ async function readManifest(abs, file) {
8315
8396
  );
8316
8397
  }
8317
8398
  }
8318
- function parseManifest(manifest, collection, text2, file, configDir, join11, target, entries) {
8399
+ function parseManifest(manifest, collection, text2, file, configDir, join11) {
8400
+ const target = /* @__PURE__ */ new Map();
8401
+ const entries = [];
8319
8402
  const lc = new LineCounter2();
8320
8403
  const doc = parseDocument4(text2, { lineCounter: lc, uniqueKeys: false });
8321
8404
  const problem = doc.errors[0];
@@ -8325,7 +8408,8 @@ function parseManifest(manifest, collection, text2, file, configDir, join11, tar
8325
8408
  );
8326
8409
  }
8327
8410
  const root = doc.contents;
8328
- if (root === null || isScalar2(root) && root.value === null) return;
8411
+ if (root === null || isScalar2(root) && root.value === null)
8412
+ return { values: target, entries };
8329
8413
  if (!isMap4(root)) {
8330
8414
  throw new DocmetaError(
8331
8415
  `Manifest ${file}: the manifest must be a mapping from document ${join11 === PATH_JOIN ? "path" : `"${join11}"`} to owned keys.`
@@ -8353,7 +8437,7 @@ function parseManifest(manifest, collection, text2, file, configDir, join11, tar
8353
8437
  `Manifest ${where}: "${spelled}" must be a mapping of owned keys to values.`
8354
8438
  );
8355
8439
  }
8356
- const indexKey = join11 === PATH_JOIN ? resolve10(configDir, spelled) : spelled;
8440
+ const indexKey = join11 === PATH_JOIN ? resolve11(configDir, spelled) : spelled;
8357
8441
  const values = target.get(indexKey) ?? /* @__PURE__ */ new Map();
8358
8442
  for (const kv of pair.value.items) {
8359
8443
  const key = isScalar2(kv.key) ? String(kv.key.value) : String(kv.key);
@@ -8388,6 +8472,7 @@ function parseManifest(manifest, collection, text2, file, configDir, join11, tar
8388
8472
  ...entryLine === void 0 ? {} : { line: entryLine }
8389
8473
  });
8390
8474
  }
8475
+ return { values: target, entries };
8391
8476
  }
8392
8477
  function nodeLines(node, lineAt, prefix = "", out = /* @__PURE__ */ new Map()) {
8393
8478
  if (isMap4(node)) {
@@ -8431,7 +8516,7 @@ function mergeExternalMetadata(label, extracted, index, memberOf2, base, options
8431
8516
  const sources = [];
8432
8517
  const joins = [];
8433
8518
  if (label !== STDIN_LABEL) {
8434
- const byPath = index.byPath.get(resolve10(base, label));
8519
+ const byPath = index.byPath.get(resolve11(base, label));
8435
8520
  if (byPath) sources.push(byPath);
8436
8521
  }
8437
8522
  for (const [field, byValue] of index.byField) {
@@ -8526,7 +8611,7 @@ function externalMetadataPointer(key) {
8526
8611
  }
8527
8612
  function orphanEntries(index, loaded, base, collections) {
8528
8613
  if (!index) return [];
8529
- const have = new Set(loaded.map((l) => resolve10(base, l)));
8614
+ const have = new Set(loaded.map((l) => resolve11(base, l)));
8530
8615
  return index.entries.filter(
8531
8616
  (e) => inCollections(e, collections) && e.join === PATH_JOIN && e.abs !== void 0 && !have.has(e.abs)
8532
8617
  );
@@ -9323,12 +9408,12 @@ var MAX_OUTPUT_BYTES = 8 * 1024 * 1024;
9323
9408
  var BinMissing = class extends Error {
9324
9409
  };
9325
9410
  function run(bin, args, opts) {
9326
- return new Promise((settle, reject) => {
9411
+ return new Promise((settle2, reject) => {
9327
9412
  let done = false;
9328
9413
  const finish2 = (r) => {
9329
9414
  if (done) return;
9330
9415
  done = true;
9331
- settle(r);
9416
+ settle2(r);
9332
9417
  };
9333
9418
  const fail2 = (err) => {
9334
9419
  if (done) return;
@@ -9821,12 +9906,12 @@ function utcDate(iso) {
9821
9906
  }
9822
9907
 
9823
9908
  // src/meta/core/derive/index.ts
9824
- import { dirname as dirname9, resolve as resolve12 } from "node:path";
9909
+ import { dirname as dirname9, resolve as resolve13 } from "node:path";
9825
9910
 
9826
9911
  // src/meta/core/derive/codeowners.ts
9827
9912
  import { existsSync as existsSync3 } from "node:fs";
9828
9913
  import { readFile as readFile7 } from "node:fs/promises";
9829
- import { dirname as dirname7, relative as relative9, resolve as resolve11, sep as sep4 } from "node:path";
9914
+ import { dirname as dirname7, relative as relative9, resolve as resolve12, sep as sep4 } from "node:path";
9830
9915
  import picomatch4 from "picomatch";
9831
9916
  var CODEOWNERS_LOCATIONS = [
9832
9917
  ".github/CODEOWNERS",
@@ -9836,11 +9921,11 @@ var CODEOWNERS_LOCATIONS = [
9836
9921
  ];
9837
9922
  function findCodeowners(root, explicit) {
9838
9923
  if (explicit !== void 0) {
9839
- const path = resolve11(root, explicit);
9924
+ const path = resolve12(root, explicit);
9840
9925
  return existsSync3(path) ? path : null;
9841
9926
  }
9842
9927
  for (const loc of CODEOWNERS_LOCATIONS) {
9843
- const path = resolve11(root, ...loc.split("/"));
9928
+ const path = resolve12(root, ...loc.split("/"));
9844
9929
  if (existsSync3(path)) return path;
9845
9930
  }
9846
9931
  return null;
@@ -9955,7 +10040,7 @@ function toGlobs(pattern) {
9955
10040
  var NOT_FOUND_REASON = `no CODEOWNERS file found (looked for ${CODEOWNERS_LOCATIONS.join(", ")})`;
9956
10041
  async function deriveFromCodeowners(inputs, opts) {
9957
10042
  const records = /* @__PURE__ */ new Map();
9958
- const explicitPath = opts.explicit === void 0 ? void 0 : resolve11(opts.configDir ?? process.cwd(), opts.explicit);
10043
+ const explicitPath = opts.explicit === void 0 ? void 0 : resolve12(opts.configDir ?? process.cwd(), opts.explicit);
9959
10044
  if (explicitPath !== void 0 && !existsSync3(explicitPath)) {
9960
10045
  return {
9961
10046
  status: { available: false, reason: `CODEOWNERS not found at ${explicitPath}` },
@@ -10095,14 +10180,14 @@ function findWindows(lines, length, pin, key, opts) {
10095
10180
  const first = original[0];
10096
10181
  for (let start = 1; start <= lastStart; start++) {
10097
10182
  if (lines[start - 1] !== first) continue;
10098
- let same = true;
10183
+ let same2 = true;
10099
10184
  for (let i = 1; i < length; i++) {
10100
10185
  if (lines[start - 1 + i] !== original[i]) {
10101
- same = false;
10186
+ same2 = false;
10102
10187
  break;
10103
10188
  }
10104
10189
  }
10105
- if (same && hashLines(joined(start), key) === pin) starts.push(start);
10190
+ if (same2 && hashLines(joined(start), key) === pin) starts.push(start);
10106
10191
  }
10107
10192
  return { starts, truncated: false };
10108
10193
  }
@@ -10432,10 +10517,10 @@ function planProvenanceWrite(comparisons, derivation) {
10432
10517
  if (r.status === "current") kept.push({ entry: r.entry, start: r.span.start });
10433
10518
  else if (r.status === "moved") kept.push({ entry: { ...r.entry, lines: lineSpec(r.span) }, start: r.span.start });
10434
10519
  }
10435
- const same = (a, b) => a["generated-by"] === b["generated-by"] && String(a.lines) === String(b.lines) && a.integrity === b.integrity;
10520
+ const same2 = (a, b) => a["generated-by"] === b["generated-by"] && String(a.lines) === String(b.lines) && a.integrity === b.integrity;
10436
10521
  const out = [...kept];
10437
10522
  for (const d of derivation.derived) {
10438
- if (!kept.some((k) => same(k.entry, d.entry))) out.push({ entry: d.entry, start: d.span.start });
10523
+ if (!kept.some((k) => same2(k.entry, d.entry))) out.push({ entry: d.entry, start: d.span.start });
10439
10524
  }
10440
10525
  return out.sort((a, b) => a.start - b.start).map((k) => k.entry);
10441
10526
  }
@@ -11154,8 +11239,8 @@ function manifestStamp(text2, key, join11) {
11154
11239
  }
11155
11240
  if (!isRecord5(data)) return [];
11156
11241
  for (const [candidate, value] of Object.entries(data)) {
11157
- const same = join11 === "path" ? posix2.normalize(candidate) === posix2.normalize(key) : candidate === key;
11158
- if (same && isRecord5(value)) return provenanceEntries(value[PROVENANCE_FIELD]);
11242
+ const same2 = join11 === "path" ? posix2.normalize(candidate) === posix2.normalize(key) : candidate === key;
11243
+ if (same2 && isRecord5(value)) return provenanceEntries(value[PROVENANCE_FIELD]);
11159
11244
  }
11160
11245
  return [];
11161
11246
  }
@@ -11226,12 +11311,12 @@ function text(out) {
11226
11311
  }
11227
11312
  }
11228
11313
  function runGit(args, cwd, stdin, maxBytes) {
11229
- return new Promise((settle, reject) => {
11314
+ return new Promise((settle2, reject) => {
11230
11315
  let done = false;
11231
11316
  const finish2 = (out) => {
11232
11317
  if (done) return;
11233
11318
  done = true;
11234
- settle(out);
11319
+ settle2(out);
11235
11320
  };
11236
11321
  const fail2 = (err) => {
11237
11322
  if (done) return;
@@ -11464,7 +11549,7 @@ async function deriveReviewsByRoot(inputs, git2, rootFor, ctx, requested) {
11464
11549
  if (byRoot.size === 0) {
11465
11550
  return unavailable3(requested, "no git repository contains the documents");
11466
11551
  }
11467
- const cacheDir = resolve12(ctx.configDir ?? ctx.cwd, REVIEW_CACHE_DIR);
11552
+ const cacheDir = resolve13(ctx.configDir ?? ctx.cwd, REVIEW_CACHE_DIR);
11468
11553
  for (const [root, bucket] of byRoot) {
11469
11554
  const client = ctx.reviews ?? await createReviewClient(root, { cwd: ctx.cwd, cache: ctx.cache, cacheDir, requested });
11470
11555
  const identity = await client.detect();
@@ -11645,8 +11730,8 @@ async function deriveForTable(inputs, ctx, hint, fields) {
11645
11730
  import { readFile as readFile9 } from "node:fs/promises";
11646
11731
 
11647
11732
  // src/meta/core/relocation.ts
11648
- import { access, readFile as readFile8, stat as stat5, unlink } from "node:fs/promises";
11649
- import { basename as basename5, extname as extname3, isAbsolute as isAbsolute7, join as join8, relative as relative11, resolve as resolve13, sep as sep6 } from "node:path";
11733
+ import { access, readFile as readFile8, stat as stat6, unlink } from "node:fs/promises";
11734
+ import { basename as basename5, extname as extname3, isAbsolute as isAbsolute7, join as join8, relative as relative11, resolve as resolve14, sep as sep6 } from "node:path";
11650
11735
  import picomatch6 from "picomatch";
11651
11736
  import {
11652
11737
  LineCounter as LineCounter4,
@@ -11697,7 +11782,7 @@ function spliceManifestValue(text2, options) {
11697
11782
  const r = rangeOf(node);
11698
11783
  return r ? lc.linePos(r[0]).line : void 0;
11699
11784
  };
11700
- const same = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11785
+ const same2 = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11701
11786
  const root = doc.contents;
11702
11787
  let spelled = entry;
11703
11788
  let edit;
@@ -11709,7 +11794,7 @@ function spliceManifestValue(text2, options) {
11709
11794
  );
11710
11795
  } else {
11711
11796
  const style = detectStyle(text2, root, eol);
11712
- const matches = root.items.filter((p) => same(keyString(p.key), entry));
11797
+ const matches = root.items.filter((p) => same2(keyString(p.key), entry));
11713
11798
  const [first, second] = matches;
11714
11799
  if (first && second) {
11715
11800
  throw new DocmetaError(
@@ -11775,8 +11860,8 @@ function readManifestValue(text2, options) {
11775
11860
  if (doc.errors.length > 0) return void 0;
11776
11861
  const root = doc.contents;
11777
11862
  if (!isMap5(root)) return void 0;
11778
- const same = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11779
- const pair = root.items.find((p) => same(keyString(p.key), options.entry));
11863
+ const same2 = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11864
+ const pair = root.items.find((p) => same2(keyString(p.key), options.entry));
11780
11865
  const held = pair?.value;
11781
11866
  if (!isMap5(held)) return void 0;
11782
11867
  const kv = held.items.find((p) => keyString(p.key) === options.key);
@@ -11809,8 +11894,8 @@ function removeManifestKey(text2, options) {
11809
11894
  `${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN ? "path" : `"${join11}"`} to owned keys.`
11810
11895
  );
11811
11896
  }
11812
- const same = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11813
- const matches = root.items.filter((p) => same(keyString(p.key), entry));
11897
+ const same2 = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11898
+ const matches = root.items.filter((p) => same2(keyString(p.key), entry));
11814
11899
  const [first, second] = matches;
11815
11900
  if (first && second) {
11816
11901
  throw new DocmetaError(
@@ -11897,15 +11982,15 @@ function renameManifestEntry(text2, options) {
11897
11982
  `${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN ? "path" : `"${join11}"`} to owned keys.`
11898
11983
  );
11899
11984
  }
11900
- const same = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11901
- const [first, second] = root.items.filter((p) => same(keyString(p.key), entry));
11985
+ const same2 = join11 === PATH_JOIN ? (a, b) => posix3.normalize(a) === posix3.normalize(b) : (a, b) => a === b;
11986
+ const [first, second] = root.items.filter((p) => same2(keyString(p.key), entry));
11902
11987
  if (first && second) {
11903
11988
  throw new DocmetaError(
11904
11989
  `${at2(keyLine(second.key))}: "${keyString(second.key)}" is named twice (first at line ${String(keyLine(first.key) ?? "?")}). Merge the two entries into one.`
11905
11990
  );
11906
11991
  }
11907
11992
  if (first === void 0) return { text: text2 };
11908
- const taken = root.items.find((p) => same(keyString(p.key), to));
11993
+ const taken = root.items.find((p) => same2(keyString(p.key), to));
11909
11994
  if (taken !== void 0) {
11910
11995
  throw new DocmetaError(
11911
11996
  `${at2(keyLine(taken.key))}: "${keyString(taken.key)}" already has an entry, so "${keyString(first.key)}" cannot be renamed to it. Merge the two entries into one.`
@@ -12171,7 +12256,7 @@ function relocationContext(run2, extras) {
12171
12256
  };
12172
12257
  }
12173
12258
  var toPosix3 = (p) => p.split(sep6).join("/");
12174
- function reported(abs, base) {
12259
+ function reported2(abs, base) {
12175
12260
  const rel = relative11(base, abs);
12176
12261
  return rel === "" ? "." : toPosix3(rel);
12177
12262
  }
@@ -12194,14 +12279,14 @@ var Model = class {
12194
12279
  for (const c of this.collections) {
12195
12280
  c.externalMetadata.forEach((m, index) => {
12196
12281
  const url = classifyRef(m.file).kind === "url";
12197
- const absPath = url ? void 0 : isAbsolute7(m.file) ? m.file : resolve13(configDir, m.file);
12282
+ const absPath = url ? void 0 : isAbsolute7(m.file) ? m.file : resolve14(configDir, m.file);
12198
12283
  this.manifests.push({
12199
12284
  collection: c.name,
12200
12285
  index,
12201
12286
  written: m.file,
12202
12287
  url,
12203
12288
  absPath,
12204
- file: absPath === void 0 ? m.file : reported(absPath, ctx.base),
12289
+ file: absPath === void 0 ? m.file : reported2(absPath, ctx.base),
12205
12290
  join: externalMetadataJoin(m),
12206
12291
  created: false,
12207
12292
  keysBefore: [...m.keys],
@@ -12299,7 +12384,7 @@ var Model = class {
12299
12384
  if (local !== void 0) return { manifest: local, proposed: proposedOf(local) };
12300
12385
  const fileName = `${name2}.metadata.yaml`;
12301
12386
  const absPath = join8(this.configDir, fileName);
12302
- const file = reported(absPath, this.ctx.base);
12387
+ const file = reported2(absPath, this.ctx.base);
12303
12388
  if (!commit) return { proposed: proposedOf({ file, created: true }) };
12304
12389
  if (await exists(absPath, file)) {
12305
12390
  throw new DocmetaError(
@@ -12351,7 +12436,7 @@ var Model = class {
12351
12436
  /** A label relative to the config directory, posix; undefined outside it. */
12352
12437
  relative(label) {
12353
12438
  if (label === "<stdin>") return void 0;
12354
- const rel = toPosix3(relative11(this.configDir, resolve13(this.ctx.base, label)));
12439
+ const rel = toPosix3(relative11(this.configDir, resolve14(this.ctx.base, label)));
12355
12440
  return isAbsolute7(rel) || rel.startsWith("../") ? void 0 : rel;
12356
12441
  }
12357
12442
  };
@@ -12363,20 +12448,20 @@ function bare(path) {
12363
12448
  }
12364
12449
  async function collectionPath(target, cwd, configDir) {
12365
12450
  if (target === STDIN_TOKEN) return void 0;
12366
- const posix4 = target.replace(/\\/g, "/");
12367
- const scanned = picomatch6.scan(posix4);
12451
+ const posix5 = target.replace(/\\/g, "/");
12452
+ const scanned = picomatch6.scan(posix5);
12368
12453
  if (scanned.isGlob) {
12369
- const rel2 = toPosix3(relative11(configDir, resolve13(cwd, scanned.base === "" ? "." : scanned.base)));
12454
+ const rel2 = toPosix3(relative11(configDir, resolve14(cwd, scanned.base === "" ? "." : scanned.base)));
12370
12455
  if (isAbsolute7(rel2) || rel2 === ".." || rel2.startsWith("../")) return void 0;
12371
12456
  return rel2 === "" ? scanned.glob : `${rel2}/${scanned.glob}`;
12372
12457
  }
12373
- const abs = resolve13(cwd, posix4);
12458
+ const abs = resolve14(cwd, posix5);
12374
12459
  const rel = toPosix3(relative11(configDir, abs));
12375
12460
  if (isAbsolute7(rel) || rel.startsWith("..")) return void 0;
12376
- let directory = posix4.endsWith("/");
12461
+ let directory = posix5.endsWith("/");
12377
12462
  if (!directory) {
12378
12463
  try {
12379
- directory = (await stat5(abs)).isDirectory();
12464
+ directory = (await stat6(abs)).isDirectory();
12380
12465
  } catch {
12381
12466
  directory = false;
12382
12467
  }
@@ -12394,7 +12479,7 @@ async function exists(absPath, file) {
12394
12479
  }
12395
12480
  }
12396
12481
  function plannedConfigDir(ctx) {
12397
- return ctx.configDir ?? findGitRoot(ctx.cwd) ?? resolve13(ctx.cwd);
12482
+ return ctx.configDir ?? findGitRoot(ctx.cwd) ?? resolve14(ctx.cwd);
12398
12483
  }
12399
12484
  async function keyHome(ctx, label, data, key) {
12400
12485
  const model = new Model(ctx, plannedConfigDir(ctx));
@@ -12415,7 +12500,7 @@ async function keyHome(ctx, label, data, key) {
12415
12500
  return { kind: "unowned", home: (await model.home(label, false)).proposed };
12416
12501
  }
12417
12502
  function entryFor(m, label, data, configDir, base, key) {
12418
- if (m.join === PATH_JOIN) return toPosix3(relative11(configDir, resolve13(base, label)));
12503
+ if (m.join === PATH_JOIN) return toPosix3(relative11(configDir, resolve14(base, label)));
12419
12504
  let raw = data[m.join];
12420
12505
  if (isEncryptedValue(raw)) {
12421
12506
  const k = key();
@@ -12456,7 +12541,7 @@ async function planRelocation(ctx, request) {
12456
12541
  if (beyond) return void 0;
12457
12542
  throw new DocmetaError(`Unsupported file type "${extname3(label)}" for "${label}". Use --as to override.`);
12458
12543
  }
12459
- const absPath = resolve13(ctx.base, label);
12544
+ const absPath = resolve14(ctx.base, label);
12460
12545
  const elements = resolveElements(label, ctx.config, currentMembers(label));
12461
12546
  let content = "";
12462
12547
  let own2 = {};
@@ -12669,7 +12754,7 @@ async function planRelocation(ctx, request) {
12669
12754
  });
12670
12755
  const labels = dedupe2([
12671
12756
  ...request.files,
12672
- ...walked.files.map((f) => reported(resolve13(configDir, f), ctx.base))
12757
+ ...walked.files.map((f) => reported2(resolve14(configDir, f), ctx.base))
12673
12758
  ]).filter((label) => model.members(label).includes(name2));
12674
12759
  for (const label of labels) {
12675
12760
  const page = await load(label, !runSet.has(label));
@@ -13113,7 +13198,7 @@ function buildResult(input) {
13113
13198
  async function applyRelocation(ctx, plan, io = {}) {
13114
13199
  const write = io.write ?? ((path, text2) => writeFileAtomic(path, text2));
13115
13200
  const remove = io.remove ?? ((path) => unlink(path));
13116
- const label = (w) => w.kind === "config" ? configSource(w.path, ctx.cwd) : reported(w.path, ctx.base);
13201
+ const label = (w) => w.kind === "config" ? configSource(w.path, ctx.cwd) : reported2(w.path, ctx.base);
13117
13202
  for (const w of plan.writes) {
13118
13203
  let now;
13119
13204
  try {
@@ -13284,7 +13369,7 @@ function relocationOffers(plan) {
13284
13369
  }
13285
13370
 
13286
13371
  // src/meta/commands/validate.ts
13287
- import { resolve as resolve15, extname as extname4 } from "node:path";
13372
+ import { resolve as resolve16, extname as extname4 } from "node:path";
13288
13373
 
13289
13374
  // src/meta/core/checks.ts
13290
13375
  var CHECK_KEYWORD = "check";
@@ -13422,7 +13507,7 @@ async function runChecks(checks, entries, ctx = {}) {
13422
13507
  }
13423
13508
 
13424
13509
  // src/meta/core/derive/provenance-place.ts
13425
- import { isAbsolute as isAbsolute8, relative as relative12, resolve as resolve14, sep as sep7 } from "node:path";
13510
+ import { isAbsolute as isAbsolute8, relative as relative12, resolve as resolve15, sep as sep7 } from "node:path";
13426
13511
  var toPosix4 = (p) => p.split(sep7).join("/");
13427
13512
  function provenanceManifests(collections, configDir, base) {
13428
13513
  const out = [];
@@ -13434,7 +13519,7 @@ function provenanceManifests(collections, configDir, base) {
13434
13519
  `collection ${collection.name}: ${PROVENANCE_FIELD} cannot come from a URL manifest, because manni meta derive writes it.`
13435
13520
  );
13436
13521
  }
13437
- const absPath = isAbsolute8(manifest.file) ? manifest.file : resolve14(configDir, manifest.file);
13522
+ const absPath = isAbsolute8(manifest.file) ? manifest.file : resolve15(configDir, manifest.file);
13438
13523
  const rel = relative12(base, absPath);
13439
13524
  out.push({
13440
13525
  collection: collection.name,
@@ -13458,7 +13543,7 @@ function provenancePlace(label, data, manifests, collections, configDir, base) {
13458
13543
  );
13459
13544
  }
13460
13545
  if (manifest.join === PATH_JOIN) {
13461
- const entry = toPosix4(relative12(configDir, resolve14(base, label)));
13546
+ const entry = toPosix4(relative12(configDir, resolve15(base, label)));
13462
13547
  return { manifest, absPath: manifest.absPath, entry, join: manifest.join };
13463
13548
  }
13464
13549
  const value = data[manifest.join];
@@ -13722,7 +13807,7 @@ async function runValidate(opts) {
13722
13807
  const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, extracted.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
13723
13808
  deriveInputs.push({
13724
13809
  label,
13725
- absPath: resolve15(base, label),
13810
+ absPath: resolve16(base, label),
13726
13811
  content,
13727
13812
  extracted,
13728
13813
  ...place !== void 0 ? { provenanceManifest: place } : {}
@@ -13853,7 +13938,7 @@ async function runValidate(opts) {
13853
13938
  await processOne(STDIN_LABEL, content, forcedExtractor.extensions[0] ?? "");
13854
13939
  }
13855
13940
  for (const file of files) {
13856
- const content = await readFile9(resolve15(base, file), "utf8");
13941
+ const content = await readFile9(resolve16(base, file), "utf8");
13857
13942
  await processOne(file, content, extname4(file));
13858
13943
  }
13859
13944
  if (unverified > 0) opts.onNotice?.(unverifiedWarning(unverified));
@@ -13967,7 +14052,7 @@ async function runValidate(opts) {
13967
14052
  }
13968
14053
  }
13969
14054
  const frame = { cwd, base: configDir ?? cwd, runBase: base };
13970
- const { results: reported2, baseline } = await settleBaseline(
14055
+ const { results: reported3, baseline } = await settleBaseline(
13971
14056
  results,
13972
14057
  resolveBaselineRequest(opts, config?.baseline, configDir, cwd, {
13973
14058
  current: DEFAULT_BASELINE_PATH,
@@ -13975,13 +14060,13 @@ async function runValidate(opts) {
13975
14060
  }),
13976
14061
  frame
13977
14062
  );
13978
- const failed = reported2.filter((r) => !r.ok).length;
13979
- const count2 = (keep) => reported2.reduce((n, r) => n + r.errors.filter(keep).length, 0);
14063
+ const failed = reported3.filter((r) => !r.ok).length;
14064
+ const count2 = (keep) => reported3.reduce((n, r) => n + r.errors.filter(keep).length, 0);
13980
14065
  const warnings = count2((e) => e.severity === "warning");
13981
14066
  const notices = count2((e) => e.severity === "notice");
13982
14067
  const summary = {
13983
- files: reported2.length,
13984
- passed: reported2.length - failed,
14068
+ files: reported3.length,
14069
+ passed: reported3.length - failed,
13985
14070
  failed,
13986
14071
  errors: count2(isErrorSeverity),
13987
14072
  // Omitted at zero, like `gitignoreSkipped` below: only the location
@@ -13994,12 +14079,12 @@ async function runValidate(opts) {
13994
14079
  ...gitignoreSkipped > 0 ? { gitignoreSkipped } : {},
13995
14080
  ...baseline ? { baseline } : {}
13996
14081
  };
13997
- return { results: reported2, summary, frame };
14082
+ return { results: reported3, summary, frame };
13998
14083
  }
13999
14084
 
14000
14085
  // src/meta/commands/get.ts
14001
14086
  import { readFile as readFile10 } from "node:fs/promises";
14002
- import { resolve as resolve16, extname as extname5 } from "node:path";
14087
+ import { resolve as resolve17, extname as extname5 } from "node:path";
14003
14088
  async function runGet(opts) {
14004
14089
  const cwd = opts.cwd ?? process.cwd();
14005
14090
  if (opts.fields.length === 0) {
@@ -14085,7 +14170,7 @@ async function runGet(opts) {
14085
14170
  const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, own2.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
14086
14171
  deriveInputs.push({
14087
14172
  label,
14088
- absPath: resolve16(base, label),
14173
+ absPath: resolve17(base, label),
14089
14174
  content,
14090
14175
  extracted: own2,
14091
14176
  ...place !== void 0 ? { provenanceManifest: place } : {}
@@ -14127,7 +14212,7 @@ async function runGet(opts) {
14127
14212
  readOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
14128
14213
  }
14129
14214
  for (const file of files) {
14130
- const content = await readFile10(resolve16(base, file), "utf8");
14215
+ const content = await readFile10(resolve17(base, file), "utf8");
14131
14216
  readOne(file, content, extname5(file));
14132
14217
  }
14133
14218
  if (deriving) {
@@ -14254,7 +14339,7 @@ function parseJsonPointer(pointer) {
14254
14339
  // src/meta/commands/schemas.ts
14255
14340
  import { existsSync as existsSync4 } from "node:fs";
14256
14341
  import { mkdir as mkdir2, readFile as readFile11 } from "node:fs/promises";
14257
- import { dirname as dirname10, extname as extname6, isAbsolute as isAbsolute9, join as join9, relative as relative13, resolve as resolve17, sep as sep8 } from "node:path";
14342
+ import { dirname as dirname10, extname as extname6, isAbsolute as isAbsolute9, join as join9, relative as relative13, resolve as resolve18, sep as sep8 } from "node:path";
14258
14343
  import { parseDocument as parseDocument7, parse as parseYaml6, stringify as stringify3 } from "yaml";
14259
14344
  function getSchemasInfo() {
14260
14345
  return { builtins: listBuiltins(), formats: listFormats() };
@@ -14348,9 +14433,9 @@ async function runVendorSchema(opts) {
14348
14433
  );
14349
14434
  }
14350
14435
  const loaded = await loadConfig(opts.configPath, cwd);
14351
- const configPath = loaded?.path ?? resolve17(cwd, DEFAULT_CONFIG_NAME);
14436
+ const configPath = loaded?.path ?? resolve18(cwd, DEFAULT_CONFIG_NAME);
14352
14437
  const configDir = loaded?.dir ?? cwd;
14353
- const absDir = resolve17(cwd, opts.dir ?? DEFAULT_VENDOR_DIR);
14438
+ const absDir = resolve18(cwd, opts.dir ?? DEFAULT_VENDOR_DIR);
14354
14439
  const absFile = join9(absDir, vendorFileName(url));
14355
14440
  await assertNotIgnored(absFile, absDir, cwd, opts.onNotice);
14356
14441
  const fromConfig = posixRelative(configDir, absFile);
@@ -14531,7 +14616,7 @@ async function runInferSchema(opts) {
14531
14616
  }
14532
14617
  let absOut;
14533
14618
  if (opts.out !== void 0) {
14534
- absOut = resolve17(cwd, opts.out);
14619
+ absOut = resolve18(cwd, opts.out);
14535
14620
  await assertNotIgnored(
14536
14621
  absOut,
14537
14622
  dirname10(absOut),
@@ -14610,42 +14695,42 @@ async function runInferSchema(opts) {
14610
14695
  return;
14611
14696
  }
14612
14697
  for (const [key, value] of Object.entries(extracted.data)) {
14613
- const stat6 = stats.get(key) ?? emptyStats();
14614
- recordValue(stat6, label, value, extracted.lineFor(key));
14615
- stats.set(key, stat6);
14698
+ const stat7 = stats.get(key) ?? emptyStats();
14699
+ recordValue(stat7, label, value, extracted.lineFor(key));
14700
+ stats.set(key, stat7);
14616
14701
  }
14617
14702
  };
14618
14703
  if (usingStdin && forced) {
14619
14704
  scanOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
14620
14705
  }
14621
14706
  for (const file of files) {
14622
- const content = await readFile11(resolve17(base, file), "utf8");
14707
+ const content = await readFile11(resolve18(base, file), "utf8");
14623
14708
  scanOne(file, content, extname6(file));
14624
14709
  }
14625
14710
  for (const u of unreadable) {
14626
14711
  opts.onNotice?.(`could not read metadata from "${u.file}": ${u.message}`);
14627
14712
  }
14628
- const all = [...stats.entries()].map(([key, stat6]) => {
14629
- const dominantType = dominantTypeOf(stat6);
14630
- const enumValues = enumFor(stat6, dominantType);
14631
- const format = formatOf(stat6, dominantType);
14632
- const outliers = [...stat6.locations.entries()].filter(([type]) => type !== dominantType).flatMap(([, where]) => where);
14633
- const outlierCount = [...stat6.types.entries()].filter(([type]) => type !== dominantType).reduce((sum, [, count2]) => sum + count2, 0);
14634
- const sample = [...stat6.values.values()].filter((v) => v.type === dominantType).sort((a, b) => b.count - a.count)[0]?.value;
14713
+ const all = [...stats.entries()].map(([key, stat7]) => {
14714
+ const dominantType = dominantTypeOf(stat7);
14715
+ const enumValues = enumFor(stat7, dominantType);
14716
+ const format = formatOf(stat7, dominantType);
14717
+ const outliers = [...stat7.locations.entries()].filter(([type]) => type !== dominantType).flatMap(([, where]) => where);
14718
+ const outlierCount = [...stat7.types.entries()].filter(([type]) => type !== dominantType).reduce((sum, [, count2]) => sum + count2, 0);
14719
+ const sample = [...stat7.values.values()].filter((v) => v.type === dominantType).sort((a, b) => b.count - a.count)[0]?.value;
14635
14720
  return {
14636
14721
  key,
14637
- present: stat6.present,
14638
- coverage: filesScanned === 0 ? 0 : stat6.present / filesScanned * 100,
14639
- types: [...stat6.types.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([type, count2]) => ({ type, count: count2 })),
14722
+ present: stat7.present,
14723
+ coverage: filesScanned === 0 ? 0 : stat7.present / filesScanned * 100,
14724
+ types: [...stat7.types.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([type, count2]) => ({ type, count: count2 })),
14640
14725
  dominantType,
14641
14726
  outliers,
14642
14727
  outlierCount,
14643
- distinct: stat6.values.size,
14644
- distinctCapped: stat6.distinctCapped,
14728
+ distinct: stat7.values.size,
14729
+ distinctCapped: stat7.distinctCapped,
14645
14730
  ...enumValues ? { enumValues } : {},
14646
14731
  ...sample !== void 0 ? { sample } : {},
14647
14732
  ...format !== void 0 ? { format } : {},
14648
- sawEmptyString: stat6.sawEmptyString
14733
+ sawEmptyString: stat7.sawEmptyString
14649
14734
  };
14650
14735
  });
14651
14736
  const kept = all.filter((k) => k.coverage >= minCoverage).sort((a, b) => b.coverage - a.coverage || a.key.localeCompare(b.key));
@@ -14681,7 +14766,7 @@ async function runInferSchema(opts) {
14681
14766
  import { randomBytes as randomBytes2 } from "node:crypto";
14682
14767
  import { existsSync as existsSync5 } from "node:fs";
14683
14768
  import { mkdir as mkdir3, open as open2, readFile as readFile12, rename as rename3, rm as rm3 } from "node:fs/promises";
14684
- import { dirname as dirname11, isAbsolute as isAbsolute10, resolve as resolve18, extname as extname7, sep as sep9 } from "node:path";
14769
+ import { dirname as dirname11, isAbsolute as isAbsolute10, resolve as resolve19, extname as extname7, sep as sep9 } from "node:path";
14685
14770
 
14686
14771
  // src/shared/prompt.ts
14687
14772
  import { createInterface } from "node:readline";
@@ -15020,10 +15105,10 @@ async function runQuery(opts) {
15020
15105
  readOne(STDIN_LABEL, opts.stdinContent ?? "", ext);
15021
15106
  }
15022
15107
  for (const file of files) {
15023
- const content = await readFile12(resolve18(base, file), "utf8");
15108
+ const content = await readFile12(resolve19(base, file), "utf8");
15024
15109
  readOne(file, content, extname7(file));
15025
15110
  }
15026
- const db = opts.db === void 0 ? void 0 : { resolved: resolve18(cwd, opts.db), display: opts.db };
15111
+ const db = opts.db === void 0 ? void 0 : { resolved: resolve19(cwd, opts.db), display: opts.db };
15027
15112
  const run2 = await runSql(sql, entries, {
15028
15113
  target: db,
15029
15114
  params: boundParams,
@@ -15164,7 +15249,7 @@ async function runSql(sql, entries, ctx) {
15164
15249
  const place = manifests.length === 0 ? void 0 : readerPlace(e.label, e.own.data, manifests, ctx.declaredCollections, manifestRoot, ctx.base);
15165
15250
  return {
15166
15251
  label: e.label,
15167
- absPath: resolve18(ctx.base, e.label),
15252
+ absPath: resolve19(ctx.base, e.label),
15168
15253
  content: e.content,
15169
15254
  extracted: e.own,
15170
15255
  ...place !== void 0 ? { provenanceManifest: place } : {}
@@ -15635,14 +15720,14 @@ function assertSchemaWriteWithin(ctx, abs) {
15635
15720
  );
15636
15721
  }
15637
15722
  function foldPath(p) {
15638
- const abs = resolve18(p);
15723
+ const abs = resolve19(p);
15639
15724
  return process.platform === "win32" ? abs.toLowerCase() : abs;
15640
15725
  }
15641
15726
  function filePinsByPath(ctx) {
15642
15727
  const byPath = /* @__PURE__ */ new Map();
15643
15728
  for (const [ref, pin] of collectSchemaPins(ctx.config)) {
15644
15729
  if (classifyRef(ref).kind !== "file") continue;
15645
- byPath.set(foldPath(resolve18(ctx.cwd, ref)), pin);
15730
+ byPath.set(foldPath(resolve19(ctx.cwd, ref)), pin);
15646
15731
  }
15647
15732
  return byPath;
15648
15733
  }
@@ -15670,7 +15755,7 @@ async function loadSetMembers(refs, ctx) {
15670
15755
  });
15671
15756
  continue;
15672
15757
  }
15673
- const abs = resolve18(ctx.cwd, ref);
15758
+ const abs = resolve19(ctx.cwd, ref);
15674
15759
  const canon = foldPath(abs);
15675
15760
  if (seenFiles.has(canon)) continue;
15676
15761
  seenFiles.add(canon);
@@ -15875,7 +15960,7 @@ async function planSchemaMutation(ops, entries, ctx) {
15875
15960
  const [, name2, ver] = target.builtinId.split(":");
15876
15961
  const safe = (s) => s.replace(/[^A-Za-z0-9._-]/g, "-");
15877
15962
  const forkName = `${safe(name2 ?? "schema")}-${safe(ver ?? "0")}.local.json`;
15878
- schemaAbs = resolve18(ctx.configDir ?? ctx.cwd, "schemas", forkName);
15963
+ schemaAbs = resolve19(ctx.configDir ?? ctx.cwd, "schemas", forkName);
15879
15964
  assertSchemaWriteWithin(ctx, schemaAbs);
15880
15965
  if (existsSync5(schemaAbs)) {
15881
15966
  throw new DocmetaError(
@@ -16042,7 +16127,7 @@ async function planConfigEdit(ctx, edit, runRefs) {
16042
16127
  }
16043
16128
  return void 0;
16044
16129
  };
16045
- const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !isAbsolute10(raw) ? resolve18(configDir, raw) : raw;
16130
+ const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !isAbsolute10(raw) ? resolve19(configDir, raw) : raw;
16046
16131
  const wantSet = runRefs.map(rebaseRaw).sort().join("\n");
16047
16132
  const seqResolvesToRunSet = (node) => {
16048
16133
  if (!isSeq5(node)) return false;
@@ -16087,7 +16172,7 @@ async function planConfigEdit(ctx, edit, runRefs) {
16087
16172
  if (!isMap8(item)) continue;
16088
16173
  const raw = rawRefOf(item);
16089
16174
  if (raw === void 0 || classifyRef(raw).kind !== "file") continue;
16090
- const abs = isAbsolute10(raw) ? raw : resolve18(configDir, raw);
16175
+ const abs = isAbsolute10(raw) ? raw : resolve19(configDir, raw);
16091
16176
  if (foldPath(abs) !== wantPath) continue;
16092
16177
  pinFrom = item.get("integrity");
16093
16178
  item.set("integrity", edit.integrity.value);
@@ -16316,7 +16401,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
16316
16401
  `"${file}": no writable format for that extension.`
16317
16402
  );
16318
16403
  }
16319
- if (existsSync5(resolve18(ctx.base, file))) {
16404
+ if (existsSync5(resolve19(ctx.base, file))) {
16320
16405
  throw new DocmetaError(
16321
16406
  `"${file}" already exists; INSERT creates new files only.`
16322
16407
  );
@@ -16335,7 +16420,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
16335
16420
  `"${from}" -> "${to}": a rename may not change the extension.`
16336
16421
  );
16337
16422
  }
16338
- if (existsSync5(resolve18(ctx.base, to))) {
16423
+ if (existsSync5(resolve19(ctx.base, to))) {
16339
16424
  throw new DocmetaError(
16340
16425
  `"${to}" already exists; the rename would overwrite it.`
16341
16426
  );
@@ -16368,9 +16453,9 @@ function validateNewPath(p, base) {
16368
16453
  if (p.split(/[\\/]/).some((segment) => segment === "..")) {
16369
16454
  refuse("it traverses upward");
16370
16455
  }
16371
- const abs = resolve18(base, p);
16372
- if (abs === resolve18(base)) refuse("it points at the corpus root, not a file");
16373
- if (!abs.startsWith(resolve18(base) + sep9)) refuse("it escapes the corpus");
16456
+ const abs = resolve19(base, p);
16457
+ if (abs === resolve19(base)) refuse("it points at the corpus root, not a file");
16458
+ if (!abs.startsWith(resolve19(base) + sep9)) refuse("it escapes the corpus");
16374
16459
  }
16375
16460
  function refuseJoinFieldChanges(changes, entries, ctx) {
16376
16461
  const index = ctx.externalMetadata;
@@ -16521,7 +16606,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
16521
16606
  );
16522
16607
  const index = await leftOut;
16523
16608
  if (index === null) return void 0;
16524
- const abs = resolve18(ctx.base, file);
16609
+ const abs = resolve19(ctx.base, file);
16525
16610
  const named = index.entries.find(
16526
16611
  (e) => e.join === PATH_JOIN && e.abs === abs && excluded.includes(e.collection)
16527
16612
  );
@@ -16568,7 +16653,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
16568
16653
  continue;
16569
16654
  }
16570
16655
  if ("renamed" in c) {
16571
- const supplied = ctx.externalMetadata?.byPath.get(resolve18(ctx.base, c.file));
16656
+ const supplied = ctx.externalMetadata?.byPath.get(resolve19(ctx.base, c.file));
16572
16657
  const seen = /* @__PURE__ */ new Set();
16573
16658
  for (const [key, sv] of supplied ?? []) {
16574
16659
  if (seen.has(sv.file) || !ctx.memberships(c.file).includes(sv.collection)) continue;
@@ -16870,14 +16955,14 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
16870
16955
  const pendingWrites = [];
16871
16956
  const pendingRenames = [];
16872
16957
  for (const [label, ops] of grouped) {
16873
- const path = resolve18(ctx.base, label);
16958
+ const path = resolve19(ctx.base, label);
16874
16959
  if (ops.renamedTo !== void 0) {
16875
16960
  if (!existsSync5(path)) {
16876
16961
  throw new DocmetaError(
16877
16962
  `"${label}" is gone from disk since it was read; re-run the query.`
16878
16963
  );
16879
16964
  }
16880
- const toDisk = resolve18(ctx.base, ops.renamedTo);
16965
+ const toDisk = resolve19(ctx.base, ops.renamedTo);
16881
16966
  if (existsSync5(toDisk)) {
16882
16967
  throw new DocmetaError(
16883
16968
  `"${ops.renamedTo}" appeared on disk since the plan; re-run the query.`
@@ -17130,8 +17215,8 @@ function skipExpression(sql, from) {
17130
17215
  }
17131
17216
 
17132
17217
  // src/meta/commands/fill.ts
17133
- import { readFile as readFile13 } from "node:fs/promises";
17134
- import { resolve as resolve19, extname as extname8, join as join10 } from "node:path";
17218
+ import { readFile as readFile14 } from "node:fs/promises";
17219
+ import { resolve as resolve20, extname as extname8, join as join10 } from "node:path";
17135
17220
  import {
17136
17221
  completeValidatedJSON,
17137
17222
  makeProvider,
@@ -17145,6 +17230,107 @@ import {
17145
17230
  InferenceError
17146
17231
  } from "@hawkeyexl/inference";
17147
17232
 
17233
+ // src/meta/core/manifest-writes.ts
17234
+ import { readFile as readFile13 } from "node:fs/promises";
17235
+
17236
+ // src/shared/manifest-cas.ts
17237
+ import { posix as posix4 } from "node:path";
17238
+ var COMMIT_ATTEMPTS = 5;
17239
+ function conflictRefusal(file) {
17240
+ return `${file} changed under the command while it was being written. Nothing was written to it. Re-run the command.`;
17241
+ }
17242
+ function heldManifest(path, file, before) {
17243
+ return { path, file, before, text: before, ops: [], bases: /* @__PURE__ */ new Map() };
17244
+ }
17245
+ function encodeValue(value) {
17246
+ return value === void 0 ? "absent" : JSON.stringify(value);
17247
+ }
17248
+ function baseKey(at2) {
17249
+ const entry = at2.join === "path" ? posix4.normalize(at2.entry) : at2.entry;
17250
+ return `${entry}\0${at2.key}`;
17251
+ }
17252
+ function rebaseable(held, op, codec) {
17253
+ const at2 = baseKey(op);
17254
+ if (held.bases.has(at2)) return;
17255
+ held.bases.set(at2, {
17256
+ entry: op.entry,
17257
+ key: op.key,
17258
+ join: op.join,
17259
+ value: encodeValue(codec.read(held.before, op))
17260
+ });
17261
+ }
17262
+ function rebase(held, current, codec) {
17263
+ for (const base of held.bases.values()) {
17264
+ if (encodeValue(codec.read(current, base)) !== base.value) return void 0;
17265
+ }
17266
+ let text2 = current;
17267
+ for (const op of held.ops) text2 = codec.apply(text2, op);
17268
+ return text2;
17269
+ }
17270
+ function rebaseline(held) {
17271
+ held.before = held.text;
17272
+ held.ops = [];
17273
+ held.bases.clear();
17274
+ }
17275
+ async function settle(held, io) {
17276
+ for (let attempt = 1; attempt <= COMMIT_ATTEMPTS; attempt++) {
17277
+ let current;
17278
+ try {
17279
+ current = await io.read(held.path);
17280
+ } catch (error) {
17281
+ const reason = error instanceof Error ? error.message : String(error);
17282
+ throw io.toError(`Manifest ${held.file} could not be read: ${reason}`);
17283
+ }
17284
+ if (current === held.before) {
17285
+ await io.write(held.path, held.text);
17286
+ return;
17287
+ }
17288
+ const replayed = rebase(held, current, io.codec);
17289
+ if (replayed === void 0) throw io.toError(conflictRefusal(held.file));
17290
+ held.before = current;
17291
+ held.text = replayed;
17292
+ }
17293
+ throw io.toError(conflictRefusal(held.file));
17294
+ }
17295
+
17296
+ // src/meta/core/manifest-writes.ts
17297
+ var manifestCodec = {
17298
+ apply(text2, op) {
17299
+ const where = { entry: op.entry, key: op.key, join: op.join, file: op.file };
17300
+ return op.kind === "remove" ? removeManifestKey(text2, where).text : spliceManifestValue(text2, { ...where, value: op.value }).text;
17301
+ },
17302
+ read(text2, at2) {
17303
+ return readManifestValue(text2, at2);
17304
+ }
17305
+ };
17306
+ function applyManifestOp(text2, op) {
17307
+ return manifestCodec.apply(text2, op);
17308
+ }
17309
+ async function holdManifestFile(path, file) {
17310
+ let before;
17311
+ try {
17312
+ before = await readFile13(path, "utf8");
17313
+ } catch (err) {
17314
+ throw new DocmetaError(`Manifest ${file} could not be read: ${errorMessage(err)}`);
17315
+ }
17316
+ return heldManifest(path, file, before);
17317
+ }
17318
+ function recordManifestOp(held, op) {
17319
+ rebaseable(held, op, manifestCodec);
17320
+ held.ops.push(op);
17321
+ }
17322
+ async function settleManifest(held, io = {}) {
17323
+ if (held.text === held.before) return false;
17324
+ await settle(held, {
17325
+ codec: manifestCodec,
17326
+ write: io.write ?? writeFileAtomic,
17327
+ read: io.read ?? ((at2) => readFile13(at2, "utf8")),
17328
+ toError: (message) => new DocmetaError(message)
17329
+ });
17330
+ rebaseline(held);
17331
+ return true;
17332
+ }
17333
+
17148
17334
  // src/meta/commands/fill-prompt.ts
17149
17335
  var FILL_PROMPT_VERSION = 4;
17150
17336
  var DEFAULT_CHUNK_CHARS = 12e3;
@@ -17444,28 +17630,34 @@ async function runFill(opts) {
17444
17630
  });
17445
17631
  const heldManifests = /* @__PURE__ */ new Map();
17446
17632
  const holding = /* @__PURE__ */ new Map();
17447
- const saveManifest = (held) => {
17448
- held.saving = held.saving.then(async () => {
17449
- const text2 = held.text;
17450
- if (text2 === held.written) return;
17451
- await writeFileAtomic(held.path, text2);
17452
- held.written = text2;
17633
+ const saveManifest = (h, ops) => {
17634
+ h.saving = h.saving.then(async () => {
17635
+ for (const op of ops) {
17636
+ const after = applyManifestOp(h.held.text, op);
17637
+ if (after === h.held.text) continue;
17638
+ recordManifestOp(h.held, op);
17639
+ h.held.text = after;
17640
+ }
17641
+ if (!dryRun) await settleManifest(h.held);
17453
17642
  });
17454
- return held.saving;
17643
+ return h.saving;
17644
+ };
17645
+ const restorePage = async (label, before) => {
17646
+ try {
17647
+ await writeFileAtomic(resolve20(base, label), before);
17648
+ return `${label} was restored.`;
17649
+ } catch (err) {
17650
+ return `${label} could not be restored: ${errorMessage(err)}. Restore it from version control.`;
17651
+ }
17455
17652
  };
17456
17653
  const holdManifest = (home) => {
17457
17654
  let held = holding.get(home.absPath);
17458
17655
  if (held === void 0) {
17459
- held = readFile13(home.absPath, "utf8").then(
17460
- (before) => {
17461
- const h = { path: home.absPath, text: before, written: before, saving: Promise.resolve() };
17462
- heldManifests.set(home.absPath, h);
17463
- return h;
17464
- },
17465
- (err) => {
17466
- throw new DocmetaError(`Manifest ${home.file} could not be read: ${errorMessage(err)}`);
17467
- }
17468
- );
17656
+ held = holdManifestFile(home.absPath, home.file).then((m) => {
17657
+ const h = { held: m, saving: Promise.resolve() };
17658
+ heldManifests.set(home.absPath, h);
17659
+ return h;
17660
+ });
17469
17661
  holding.set(home.absPath, held);
17470
17662
  }
17471
17663
  return held;
@@ -17967,52 +18159,54 @@ async function runFill(opts) {
17967
18159
  metaProvenance = { written: false, skipReason: "unwritable" };
17968
18160
  }
17969
18161
  const helds = await Promise.all(entryWrites.map((w) => holdManifest(w.home)));
17970
- const splice = () => {
17971
- const texts = /* @__PURE__ */ new Map();
17972
- for (const [i, w] of entryWrites.entries()) {
17973
- const held = helds[i];
17974
- if (held === void 0) continue;
17975
- const text2 = texts.get(held.path) ?? held.text;
17976
- texts.set(
17977
- held.path,
17978
- spliceManifestValue(text2, {
17979
- entry: w.home.entry,
17980
- key: w.key,
17981
- value: w.value,
17982
- join: w.home.join,
17983
- file: w.home.file
17984
- }).text
17985
- );
17986
- }
17987
- return texts;
17988
- };
18162
+ const ops = [];
18163
+ for (const [i, w] of entryWrites.entries()) {
18164
+ const at2 = helds[i];
18165
+ if (at2 === void 0) continue;
18166
+ ops.push({
18167
+ at: at2,
18168
+ op: {
18169
+ kind: "splice",
18170
+ entry: w.home.entry,
18171
+ key: w.key,
18172
+ value: w.value,
18173
+ join: w.home.join,
18174
+ file: w.home.file
18175
+ }
18176
+ });
18177
+ }
17989
18178
  let manifestChanged = false;
17990
18179
  try {
17991
- manifestChanged = [...splice()].some(([path, text2]) => heldManifests.get(path)?.text !== text2);
18180
+ const texts = /* @__PURE__ */ new Map();
18181
+ for (const { at: at2, op } of ops) {
18182
+ texts.set(at2.held.path, applyManifestOp(texts.get(at2.held.path) ?? at2.held.text, op));
18183
+ }
18184
+ manifestChanged = [...texts].some(([path, text2]) => heldManifests.get(path)?.held.text !== text2);
17992
18185
  } catch (err) {
17993
18186
  if (!(err instanceof DocmetaError)) throw err;
17994
18187
  return errorResult(label, extractor.name, err.message, schemaSet, fields);
17995
18188
  }
17996
18189
  const changed = next !== content || manifestChanged;
17997
- if (next !== content && !dryRun && label !== "<stdin>") {
17998
- await writeFileAtomic(resolve19(base, label), next);
18190
+ const pageWritten = next !== content && !dryRun && label !== "<stdin>";
18191
+ if (pageWritten) {
18192
+ await writeFileAtomic(resolve20(base, label), next);
17999
18193
  }
18000
18194
  if (manifestChanged) {
18001
- let texts;
18195
+ const perManifest = /* @__PURE__ */ new Map();
18196
+ for (const { at: at2, op } of ops) {
18197
+ const list2 = perManifest.get(at2);
18198
+ if (list2 === void 0) perManifest.set(at2, [op]);
18199
+ else list2.push(op);
18200
+ }
18201
+ const saves = [...perManifest].map(([at2, list2]) => saveManifest(at2, list2));
18002
18202
  try {
18003
- texts = splice();
18203
+ await Promise.all(saves);
18004
18204
  } catch (err) {
18005
- if (!(err instanceof DocmetaError)) throw err;
18006
- return errorResult(label, extractor.name, err.message, schemaSet, fields);
18007
- }
18008
- const saves = [];
18009
- for (const [path, text2] of texts) {
18010
- const held = heldManifests.get(path);
18011
- if (held === void 0 || held.text === text2) continue;
18012
- held.text = text2;
18013
- if (!dryRun) saves.push(saveManifest(held));
18205
+ if (!pageWritten) throw err;
18206
+ const note = await restorePage(label, content);
18207
+ if (err instanceof DocmetaError) throw new DocmetaError(`${err.message} ${note}`);
18208
+ throw err;
18014
18209
  }
18015
- await Promise.all(saves);
18016
18210
  }
18017
18211
  return {
18018
18212
  file: label,
@@ -18027,7 +18221,7 @@ async function runFill(opts) {
18027
18221
  const prepareAll = async () => ({
18028
18222
  stdin: usingStdin ? await prepareOne("<stdin>", opts.stdinContent ?? "", forcedExtractor?.extensions[0] ?? "") : void 0,
18029
18223
  files: await mapConcurrent(files, concurrency, async (file) => {
18030
- const content = await readFile13(resolve19(base, file), "utf8");
18224
+ const content = await readFile14(resolve20(base, file), "utf8");
18031
18225
  return prepareOne(file, content, extname8(file));
18032
18226
  })
18033
18227
  });
@@ -18051,7 +18245,7 @@ async function runFill(opts) {
18051
18245
  const results = [];
18052
18246
  if (prepared.stdin !== void 0) results.push(await finish2(prepared.stdin));
18053
18247
  results.push(...await mapConcurrent(prepared.files, concurrency, finish2));
18054
- await Promise.all([...heldManifests.values()].map((held) => held.saving));
18248
+ await Promise.all([...heldManifests.values()].map((h) => h.saving));
18055
18249
  if (flagged.length > 0) {
18056
18250
  const landed = flagged.filter((w) => {
18057
18251
  const r = results.find((x) => x.file === w.label);
@@ -18456,8 +18650,8 @@ async function mapConcurrent(items2, limit, fn) {
18456
18650
  }
18457
18651
 
18458
18652
  // src/meta/commands/derive.ts
18459
- import { readFile as readFile14 } from "node:fs/promises";
18460
- import { extname as extname9, relative as relative14, resolve as resolve20, sep as sep10 } from "node:path";
18653
+ import { readFile as readFile15 } from "node:fs/promises";
18654
+ import { extname as extname9, relative as relative14, resolve as resolve21, sep as sep10 } from "node:path";
18461
18655
  var GENERATED_BY_ENV = "MANNI_GENERATED_BY";
18462
18656
  var SOURCE_HINT = "narrow --sources or --fields";
18463
18657
  async function runDerive(opts) {
@@ -18568,7 +18762,7 @@ async function runDerive(opts) {
18568
18762
  const files = fromCollections ? retainMembers(walked, membersFor) : walked;
18569
18763
  const rangesByPage = /* @__PURE__ */ new Map();
18570
18764
  for (const t of targets) {
18571
- const label = relative14(base, resolve20(base, t.page)).split(sep10).join("/");
18765
+ const label = relative14(base, resolve21(base, t.page)).split(sep10).join("/");
18572
18766
  if (!files.includes(label)) {
18573
18767
  throw new DocmetaError(
18574
18768
  `${t.target} does not name one file that derive reads; a range names lines of one file.`
@@ -18593,7 +18787,7 @@ async function runDerive(opts) {
18593
18787
  const loaded2 = /* @__PURE__ */ new Map();
18594
18788
  const errors2 = /* @__PURE__ */ new Map();
18595
18789
  for (const label of files) {
18596
- const absPath = resolve20(base, label);
18790
+ const absPath = resolve21(base, label);
18597
18791
  const extractor = forcedExtractor ?? extractorForExtension(extname9(label));
18598
18792
  if (!extractor) {
18599
18793
  errors2.set(label, {
@@ -18602,7 +18796,7 @@ async function runDerive(opts) {
18602
18796
  });
18603
18797
  continue;
18604
18798
  }
18605
- const content = await readFile14(absPath, "utf8");
18799
+ const content = await readFile15(absPath, "utf8");
18606
18800
  const elements = resolveElements(label, config, membersFor(label));
18607
18801
  try {
18608
18802
  loaded2.set(label, {
@@ -18823,24 +19017,13 @@ async function runDerive(opts) {
18823
19017
  const holdManifest = async (manifest) => {
18824
19018
  const already = heldManifests.get(manifest.absPath);
18825
19019
  if (already !== void 0) return already;
18826
- let before;
18827
- try {
18828
- before = await readFile14(manifest.absPath, "utf8");
18829
- } catch (err) {
18830
- throw new DocmetaError(`Manifest ${manifest.file} could not be read: ${errorMessage(err)}`);
18831
- }
18832
- const held = { path: manifest.absPath, written: before, text: before };
19020
+ const held = await holdManifestFile(manifest.absPath, manifest.file);
18833
19021
  heldManifests.set(manifest.absPath, held);
18834
19022
  return held;
18835
19023
  };
18836
19024
  const results = [];
18837
19025
  const saveManifests = async () => {
18838
- for (const held of heldManifests.values()) {
18839
- if (held.text !== held.written) {
18840
- await writeFileAtomic(held.path, held.text);
18841
- held.written = held.text;
18842
- }
18843
- }
19026
+ for (const held of heldManifests.values()) await settleManifest(held);
18844
19027
  };
18845
19028
  let settled = false;
18846
19029
  try {
@@ -18870,7 +19053,7 @@ async function runDerive(opts) {
18870
19053
  const shown = () => compared.map(
18871
19054
  (f) => f.field !== PROVENANCE_FIELD && isMarked(f.field) ? redactedDerived(f) : f
18872
19055
  );
18873
- const findingsOf = (reported3) => reported3.flatMap(
19056
+ const findingsOf = (reported4) => reported4.flatMap(
18874
19057
  (f) => f.field === PROVENANCE_FIELD && provenance?.judged !== void 0 ? provenanceFindings(provenance.judged.comparisons, provenance.judged.derivation.page.bodyLine) : staleFindings([f], doc.extracted.lineFor, marks.locate)
18875
19058
  );
18876
19059
  if (provenance?.judged !== void 0 && flagGeneratedBy !== void 0 && doc.attribution === void 0 && ![...provenance.judged.derivation.evidenceByLine.values()].some((e) => e.rule === 1)) {
@@ -18917,12 +19100,15 @@ async function runDerive(opts) {
18917
19100
  }
18918
19101
  let changed = false;
18919
19102
  const staged = /* @__PURE__ */ new Map();
18920
- const stage = async (manifest, edit) => {
19103
+ const stagedOps = [];
19104
+ const stage = async (manifest, op) => {
18921
19105
  const held = await holdManifest(manifest);
18922
19106
  const before = staged.get(held.path) ?? held.text;
18923
- const after = edit(before);
19107
+ const after = applyManifestOp(before, op);
18924
19108
  staged.set(held.path, after);
18925
- return after !== before;
19109
+ if (after === before) return false;
19110
+ stagedOps.push({ held, op });
19111
+ return true;
18926
19112
  };
18927
19113
  const manifestWritten = [];
18928
19114
  const entryWritten = [];
@@ -18931,7 +19117,7 @@ async function runDerive(opts) {
18931
19117
  const plan = toManifest.judged.plan;
18932
19118
  const edited = await stage(
18933
19119
  place.manifest,
18934
- (text2) => plan.length === 0 ? removeManifestKey(text2, where).text : spliceManifestValue(text2, { ...where, value: plan }).text
19120
+ plan.length === 0 ? { ...where, kind: "remove" } : { ...where, kind: "splice", value: plan }
18935
19121
  );
18936
19122
  if (edited) {
18937
19123
  changed = true;
@@ -18941,16 +19127,14 @@ async function runDerive(opts) {
18941
19127
  try {
18942
19128
  for (const { f, home, entry } of toEntries) {
18943
19129
  const value = isMarked(f.field) ? await sealField(f.field, f.derived, marks.marked) : f.derived;
18944
- const edited = await stage(
18945
- home,
18946
- (text2) => spliceManifestValue(text2, {
18947
- entry,
18948
- key: f.field,
18949
- value,
18950
- join: home.join,
18951
- file: home.file
18952
- }).text
18953
- );
19130
+ const edited = await stage(home, {
19131
+ kind: "splice",
19132
+ entry,
19133
+ key: f.field,
19134
+ value,
19135
+ join: home.join,
19136
+ file: home.file
19137
+ });
18954
19138
  if (edited) {
18955
19139
  changed = true;
18956
19140
  manifestWritten.push(f);
@@ -19013,14 +19197,15 @@ async function runDerive(opts) {
19013
19197
  }
19014
19198
  }
19015
19199
  }
19200
+ for (const { held, op } of stagedOps) recordManifestOp(held, op);
19016
19201
  for (const [path, text2] of staged) {
19017
19202
  const held = heldManifests.get(path);
19018
19203
  if (held !== void 0) held.text = text2;
19019
19204
  }
19020
19205
  if (!dryRun) for (const f of manifestWritten) markWritten(f);
19021
- const reported2 = shown();
19206
+ const reported3 = shown();
19022
19207
  for (const { f, home, entry } of toEntries) {
19023
- const shownField = reported2.find((r) => r.field === f.field);
19208
+ const shownField = reported3.find((r) => r.field === f.field);
19024
19209
  if (shownField !== void 0 && entryWritten.includes(f)) {
19025
19210
  lineRequests.push({ field: shownField, absPath: home.absPath, entry, join: home.join });
19026
19211
  }
@@ -19028,9 +19213,9 @@ async function runDerive(opts) {
19028
19213
  results.push({
19029
19214
  file: label,
19030
19215
  format: doc.format,
19031
- fields: reported2,
19216
+ fields: reported3,
19032
19217
  changed,
19033
- ...check ? { findings: findingsOf(reported2) } : {}
19218
+ ...check ? { findings: findingsOf(reported3) } : {}
19034
19219
  });
19035
19220
  }
19036
19221
  settled = true;
@@ -19944,6 +20129,9 @@ export {
19944
20129
  runVendorSchema,
19945
20130
  runInferSchema,
19946
20131
  runQuery,
20132
+ heldManifest,
20133
+ rebaseable,
20134
+ settle,
19947
20135
  runFill,
19948
20136
  runDerive,
19949
20137
  deriveFailed,
@@ -19962,4 +20150,4 @@ export {
19962
20150
  renderQuery,
19963
20151
  renderQueryCsv
19964
20152
  };
19965
- //# sourceMappingURL=chunk-KEW557TN.js.map
20153
+ //# sourceMappingURL=chunk-XHH5OSQQ.js.map