truecourse 0.7.0-next.8 → 0.7.0-next.9

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.
package/cli.mjs CHANGED
@@ -972,8 +972,8 @@ var require_command = __commonJS({
972
972
  "node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
973
973
  var EventEmitter2 = __require("node:events").EventEmitter;
974
974
  var childProcess = __require("node:child_process");
975
- var path80 = __require("node:path");
976
- var fs71 = __require("node:fs");
975
+ var path81 = __require("node:path");
976
+ var fs72 = __require("node:fs");
977
977
  var process2 = __require("node:process");
978
978
  var { Argument: Argument2, humanReadableArgName } = require_argument();
979
979
  var { CommanderError: CommanderError2 } = require_error();
@@ -1905,11 +1905,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1905
1905
  let launchWithNode = false;
1906
1906
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1907
1907
  function findFile(baseDir, baseName) {
1908
- const localBin = path80.resolve(baseDir, baseName);
1909
- if (fs71.existsSync(localBin)) return localBin;
1910
- if (sourceExt.includes(path80.extname(baseName))) return void 0;
1908
+ const localBin = path81.resolve(baseDir, baseName);
1909
+ if (fs72.existsSync(localBin)) return localBin;
1910
+ if (sourceExt.includes(path81.extname(baseName))) return void 0;
1911
1911
  const foundExt = sourceExt.find(
1912
- (ext2) => fs71.existsSync(`${localBin}${ext2}`)
1912
+ (ext2) => fs72.existsSync(`${localBin}${ext2}`)
1913
1913
  );
1914
1914
  if (foundExt) return `${localBin}${foundExt}`;
1915
1915
  return void 0;
@@ -1921,21 +1921,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1921
1921
  if (this._scriptPath) {
1922
1922
  let resolvedScriptPath;
1923
1923
  try {
1924
- resolvedScriptPath = fs71.realpathSync(this._scriptPath);
1924
+ resolvedScriptPath = fs72.realpathSync(this._scriptPath);
1925
1925
  } catch (err) {
1926
1926
  resolvedScriptPath = this._scriptPath;
1927
1927
  }
1928
- executableDir = path80.resolve(
1929
- path80.dirname(resolvedScriptPath),
1928
+ executableDir = path81.resolve(
1929
+ path81.dirname(resolvedScriptPath),
1930
1930
  executableDir
1931
1931
  );
1932
1932
  }
1933
1933
  if (executableDir) {
1934
1934
  let localFile = findFile(executableDir, executableFile);
1935
1935
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1936
- const legacyName = path80.basename(
1936
+ const legacyName = path81.basename(
1937
1937
  this._scriptPath,
1938
- path80.extname(this._scriptPath)
1938
+ path81.extname(this._scriptPath)
1939
1939
  );
1940
1940
  if (legacyName !== this._name) {
1941
1941
  localFile = findFile(
@@ -1946,7 +1946,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1946
1946
  }
1947
1947
  executableFile = localFile || executableFile;
1948
1948
  }
1949
- launchWithNode = sourceExt.includes(path80.extname(executableFile));
1949
+ launchWithNode = sourceExt.includes(path81.extname(executableFile));
1950
1950
  let proc;
1951
1951
  if (process2.platform !== "win32") {
1952
1952
  if (launchWithNode) {
@@ -2786,7 +2786,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2786
2786
  * @return {Command}
2787
2787
  */
2788
2788
  nameFromFilename(filename) {
2789
- this._name = path80.basename(filename, path80.extname(filename));
2789
+ this._name = path81.basename(filename, path81.extname(filename));
2790
2790
  return this;
2791
2791
  }
2792
2792
  /**
@@ -2800,9 +2800,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2800
2800
  * @param {string} [path]
2801
2801
  * @return {(string|null|Command)}
2802
2802
  */
2803
- executableDir(path81) {
2804
- if (path81 === void 0) return this._executableDir;
2805
- this._executableDir = path81;
2803
+ executableDir(path82) {
2804
+ if (path82 === void 0) return this._executableDir;
2805
+ this._executableDir = path82;
2806
2806
  return this;
2807
2807
  }
2808
2808
  /**
@@ -5206,8 +5206,8 @@ var init_parseUtil = __esm({
5206
5206
  init_errors();
5207
5207
  init_en();
5208
5208
  makeIssue = (params) => {
5209
- const { data, path: path80, errorMaps, issueData } = params;
5210
- const fullPath = [...path80, ...issueData.path || []];
5209
+ const { data, path: path81, errorMaps, issueData } = params;
5210
+ const fullPath = [...path81, ...issueData.path || []];
5211
5211
  const fullIssue = {
5212
5212
  ...issueData,
5213
5213
  path: fullPath
@@ -5515,11 +5515,11 @@ var init_types = __esm({
5515
5515
  init_parseUtil();
5516
5516
  init_util();
5517
5517
  ParseInputLazyPath = class {
5518
- constructor(parent, value, path80, key4) {
5518
+ constructor(parent, value, path81, key4) {
5519
5519
  this._cachedPath = [];
5520
5520
  this.parent = parent;
5521
5521
  this.data = value;
5522
- this._path = path80;
5522
+ this._path = path81;
5523
5523
  this._key = key4;
5524
5524
  }
5525
5525
  get path() {
@@ -11976,10 +11976,10 @@ var require_src3 = __commonJS({
11976
11976
  var fs_1 = __require("fs");
11977
11977
  var debug_1 = __importDefault(require_src2());
11978
11978
  var log2 = debug_1.default("@kwsites/file-exists");
11979
- function check(path80, isFile, isDirectory) {
11980
- log2(`checking %s`, path80);
11979
+ function check(path81, isFile, isDirectory) {
11980
+ log2(`checking %s`, path81);
11981
11981
  try {
11982
- const stat = fs_1.statSync(path80);
11982
+ const stat = fs_1.statSync(path81);
11983
11983
  if (stat.isFile() && isFile) {
11984
11984
  log2(`[OK] path represents a file`);
11985
11985
  return true;
@@ -11999,8 +11999,8 @@ var require_src3 = __commonJS({
11999
11999
  throw e;
12000
12000
  }
12001
12001
  }
12002
- function exists2(path80, type2 = exports.READABLE) {
12003
- return check(path80, (type2 & exports.FILE) > 0, (type2 & exports.FOLDER) > 0);
12002
+ function exists2(path81, type2 = exports.READABLE) {
12003
+ return check(path81, (type2 & exports.FILE) > 0, (type2 & exports.FOLDER) > 0);
12004
12004
  }
12005
12005
  exports.exists = exists2;
12006
12006
  exports.FILE = 1;
@@ -12073,8 +12073,8 @@ function pathspec(...paths) {
12073
12073
  cache.set(key4, paths);
12074
12074
  return key4;
12075
12075
  }
12076
- function isPathSpec(path80) {
12077
- return path80 instanceof String && cache.has(path80);
12076
+ function isPathSpec(path81) {
12077
+ return path81 instanceof String && cache.has(path81);
12078
12078
  }
12079
12079
  function toPaths(pathSpec) {
12080
12080
  return cache.get(pathSpec) || [];
@@ -12118,8 +12118,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
12118
12118
  function forEachLineWithContent(input, callback) {
12119
12119
  return toLinesWithContent(input, true).map((line) => callback(line));
12120
12120
  }
12121
- function folderExists(path80) {
12122
- return (0, import_file_exists.exists)(path80, import_file_exists.FOLDER);
12121
+ function folderExists(path81) {
12122
+ return (0, import_file_exists.exists)(path81, import_file_exists.FOLDER);
12123
12123
  }
12124
12124
  function append(target, item) {
12125
12125
  if (Array.isArray(target)) {
@@ -12310,8 +12310,8 @@ function checkIsRepoRootTask() {
12310
12310
  commands,
12311
12311
  format: "utf-8",
12312
12312
  onError,
12313
- parser(path80) {
12314
- return /^\.(git)?$/.test(path80.trim());
12313
+ parser(path81) {
12314
+ return /^\.(git)?$/.test(path81.trim());
12315
12315
  }
12316
12316
  };
12317
12317
  }
@@ -12567,11 +12567,11 @@ function parseGrep(grep) {
12567
12567
  const paths = /* @__PURE__ */ new Set();
12568
12568
  const results = {};
12569
12569
  forEachLineWithContent(grep, (input) => {
12570
- const [path80, line, preview] = input.split(NULL);
12571
- paths.add(path80);
12572
- (results[path80] = results[path80] || []).push({
12570
+ const [path81, line, preview] = input.split(NULL);
12571
+ paths.add(path81);
12572
+ (results[path81] = results[path81] || []).push({
12573
12573
  line: asNumber(line),
12574
- path: path80,
12574
+ path: path81,
12575
12575
  preview
12576
12576
  });
12577
12577
  });
@@ -12868,14 +12868,14 @@ function hashObjectTask(filePath, write) {
12868
12868
  }
12869
12869
  return straightThroughStringTask(commands, true);
12870
12870
  }
12871
- function parseInit(bare, path80, text4) {
12871
+ function parseInit(bare, path81, text4) {
12872
12872
  const response = String(text4).trim();
12873
12873
  let result;
12874
12874
  if (result = initResponseRegex.exec(response)) {
12875
- return new InitSummary(bare, path80, false, result[1]);
12875
+ return new InitSummary(bare, path81, false, result[1]);
12876
12876
  }
12877
12877
  if (result = reInitResponseRegex.exec(response)) {
12878
- return new InitSummary(bare, path80, true, result[1]);
12878
+ return new InitSummary(bare, path81, true, result[1]);
12879
12879
  }
12880
12880
  let gitDir = "";
12881
12881
  const tokens = response.split(" ");
@@ -12886,12 +12886,12 @@ function parseInit(bare, path80, text4) {
12886
12886
  break;
12887
12887
  }
12888
12888
  }
12889
- return new InitSummary(bare, path80, /^re/i.test(response), gitDir);
12889
+ return new InitSummary(bare, path81, /^re/i.test(response), gitDir);
12890
12890
  }
12891
12891
  function hasBareCommand(command) {
12892
12892
  return command.includes(bareCommand);
12893
12893
  }
12894
- function initTask(bare = false, path80, customArgs) {
12894
+ function initTask(bare = false, path81, customArgs) {
12895
12895
  const commands = ["init", ...customArgs];
12896
12896
  if (bare && !hasBareCommand(commands)) {
12897
12897
  commands.splice(1, 0, bareCommand);
@@ -12900,7 +12900,7 @@ function initTask(bare = false, path80, customArgs) {
12900
12900
  commands,
12901
12901
  format: "utf-8",
12902
12902
  parser(text4) {
12903
- return parseInit(commands.includes("--bare"), path80, text4);
12903
+ return parseInit(commands.includes("--bare"), path81, text4);
12904
12904
  }
12905
12905
  };
12906
12906
  }
@@ -13179,14 +13179,14 @@ function splitLine(result, lineStr) {
13179
13179
  default:
13180
13180
  return;
13181
13181
  }
13182
- function data(index, workingDir, path80) {
13182
+ function data(index, workingDir, path81) {
13183
13183
  const raw = `${index}${workingDir}`;
13184
13184
  const handler = parsers6.get(raw);
13185
13185
  if (handler) {
13186
- handler(result, path80);
13186
+ handler(result, path81);
13187
13187
  }
13188
13188
  if (raw !== "##" && raw !== "!!") {
13189
- result.files.push(new FileStatusSummary(path80, index, workingDir));
13189
+ result.files.push(new FileStatusSummary(path81, index, workingDir));
13190
13190
  }
13191
13191
  }
13192
13192
  }
@@ -13373,8 +13373,8 @@ function deleteBranchTask(branch, forceDelete = false) {
13373
13373
  return task;
13374
13374
  }
13375
13375
  function toPath(input) {
13376
- const path80 = input.trim().replace(/^["']|["']$/g, "");
13377
- return path80 && normalize(path80);
13376
+ const path81 = input.trim().replace(/^["']|["']$/g, "");
13377
+ return path81 && normalize(path81);
13378
13378
  }
13379
13379
  function checkIgnoreTask(paths) {
13380
13380
  return {
@@ -13513,8 +13513,8 @@ function stashListTask(opt = {}, customArgs) {
13513
13513
  parser: parser4
13514
13514
  };
13515
13515
  }
13516
- function addSubModuleTask(repo, path80) {
13517
- return subModuleTask(["add", repo, path80]);
13516
+ function addSubModuleTask(repo, path81) {
13517
+ return subModuleTask(["add", repo, path81]);
13518
13518
  }
13519
13519
  function initSubModuleTask(customArgs) {
13520
13520
  return subModuleTask(["init", ...customArgs]);
@@ -14826,9 +14826,9 @@ var init_esm2 = __esm({
14826
14826
  "src/lib/responses/InitSummary.ts"() {
14827
14827
  "use strict";
14828
14828
  InitSummary = class {
14829
- constructor(bare, path80, existing, gitDir) {
14829
+ constructor(bare, path81, existing, gitDir) {
14830
14830
  this.bare = bare;
14831
- this.path = path80;
14831
+ this.path = path81;
14832
14832
  this.existing = existing;
14833
14833
  this.gitDir = gitDir;
14834
14834
  }
@@ -15362,12 +15362,12 @@ var init_esm2 = __esm({
15362
15362
  "use strict";
15363
15363
  fromPathRegex = /^(.+)\0(.+)$/;
15364
15364
  FileStatusSummary = class {
15365
- constructor(path80, index, working_dir) {
15366
- this.path = path80;
15365
+ constructor(path81, index, working_dir) {
15366
+ this.path = path81;
15367
15367
  this.index = index;
15368
15368
  this.working_dir = working_dir;
15369
15369
  if (index === "R" || working_dir === "R") {
15370
- const detail = fromPathRegex.exec(path80) || [null, path80, path80];
15370
+ const detail = fromPathRegex.exec(path81) || [null, path81, path81];
15371
15371
  this.from = detail[2] || "";
15372
15372
  this.path = detail[1] || "";
15373
15373
  }
@@ -15630,9 +15630,9 @@ var init_esm2 = __esm({
15630
15630
  next
15631
15631
  );
15632
15632
  }
15633
- hashObject(path80, write) {
15633
+ hashObject(path81, write) {
15634
15634
  return this._runTask(
15635
- hashObjectTask(path80, write === true),
15635
+ hashObjectTask(path81, write === true),
15636
15636
  trailingFunctionArgument(arguments)
15637
15637
  );
15638
15638
  }
@@ -16269,8 +16269,8 @@ var init_esm2 = __esm({
16269
16269
  }
16270
16270
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
16271
16271
  };
16272
- Git2.prototype.submoduleAdd = function(repo, path80, then) {
16273
- return this._runTask(addSubModuleTask2(repo, path80), trailingFunctionArgument2(arguments));
16272
+ Git2.prototype.submoduleAdd = function(repo, path81, then) {
16273
+ return this._runTask(addSubModuleTask2(repo, path81), trailingFunctionArgument2(arguments));
16274
16274
  };
16275
16275
  Git2.prototype.submoduleUpdate = function(args, then) {
16276
16276
  return this._runTask(
@@ -16896,7 +16896,7 @@ var require_ignore = __commonJS({
16896
16896
  // path matching.
16897
16897
  // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
16898
16898
  // @returns {TestResult} true if a file is ignored
16899
- test(path80, checkUnignored, mode) {
16899
+ test(path81, checkUnignored, mode) {
16900
16900
  let ignored = false;
16901
16901
  let unignored = false;
16902
16902
  let matchedRule;
@@ -16905,7 +16905,7 @@ var require_ignore = __commonJS({
16905
16905
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
16906
16906
  return;
16907
16907
  }
16908
- const matched = rule[mode].test(path80);
16908
+ const matched = rule[mode].test(path81);
16909
16909
  if (!matched) {
16910
16910
  return;
16911
16911
  }
@@ -16926,17 +16926,17 @@ var require_ignore = __commonJS({
16926
16926
  var throwError2 = (message, Ctor) => {
16927
16927
  throw new Ctor(message);
16928
16928
  };
16929
- var checkPath = (path80, originalPath, doThrow) => {
16930
- if (!isString(path80)) {
16929
+ var checkPath = (path81, originalPath, doThrow) => {
16930
+ if (!isString(path81)) {
16931
16931
  return doThrow(
16932
16932
  `path must be a string, but got \`${originalPath}\``,
16933
16933
  TypeError
16934
16934
  );
16935
16935
  }
16936
- if (!path80) {
16936
+ if (!path81) {
16937
16937
  return doThrow(`path must not be empty`, TypeError);
16938
16938
  }
16939
- if (checkPath.isNotRelative(path80)) {
16939
+ if (checkPath.isNotRelative(path81)) {
16940
16940
  const r = "`path.relative()`d";
16941
16941
  return doThrow(
16942
16942
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -16945,7 +16945,7 @@ var require_ignore = __commonJS({
16945
16945
  }
16946
16946
  return true;
16947
16947
  };
16948
- var isNotRelative = (path80) => REGEX_TEST_INVALID_PATH.test(path80);
16948
+ var isNotRelative = (path81) => REGEX_TEST_INVALID_PATH.test(path81);
16949
16949
  checkPath.isNotRelative = isNotRelative;
16950
16950
  checkPath.convert = (p2) => p2;
16951
16951
  var Ignore = class {
@@ -16975,19 +16975,19 @@ var require_ignore = __commonJS({
16975
16975
  }
16976
16976
  // @returns {TestResult}
16977
16977
  _test(originalPath, cache3, checkUnignored, slices) {
16978
- const path80 = originalPath && checkPath.convert(originalPath);
16978
+ const path81 = originalPath && checkPath.convert(originalPath);
16979
16979
  checkPath(
16980
- path80,
16980
+ path81,
16981
16981
  originalPath,
16982
16982
  this._strictPathCheck ? throwError2 : RETURN_FALSE
16983
16983
  );
16984
- return this._t(path80, cache3, checkUnignored, slices);
16984
+ return this._t(path81, cache3, checkUnignored, slices);
16985
16985
  }
16986
- checkIgnore(path80) {
16987
- if (!REGEX_TEST_TRAILING_SLASH.test(path80)) {
16988
- return this.test(path80);
16986
+ checkIgnore(path81) {
16987
+ if (!REGEX_TEST_TRAILING_SLASH.test(path81)) {
16988
+ return this.test(path81);
16989
16989
  }
16990
- const slices = path80.split(SLASH).filter(Boolean);
16990
+ const slices = path81.split(SLASH).filter(Boolean);
16991
16991
  slices.pop();
16992
16992
  if (slices.length) {
16993
16993
  const parent = this._t(
@@ -17000,18 +17000,18 @@ var require_ignore = __commonJS({
17000
17000
  return parent;
17001
17001
  }
17002
17002
  }
17003
- return this._rules.test(path80, false, MODE_CHECK_IGNORE);
17003
+ return this._rules.test(path81, false, MODE_CHECK_IGNORE);
17004
17004
  }
17005
- _t(path80, cache3, checkUnignored, slices) {
17006
- if (path80 in cache3) {
17007
- return cache3[path80];
17005
+ _t(path81, cache3, checkUnignored, slices) {
17006
+ if (path81 in cache3) {
17007
+ return cache3[path81];
17008
17008
  }
17009
17009
  if (!slices) {
17010
- slices = path80.split(SLASH).filter(Boolean);
17010
+ slices = path81.split(SLASH).filter(Boolean);
17011
17011
  }
17012
17012
  slices.pop();
17013
17013
  if (!slices.length) {
17014
- return cache3[path80] = this._rules.test(path80, checkUnignored, MODE_IGNORE);
17014
+ return cache3[path81] = this._rules.test(path81, checkUnignored, MODE_IGNORE);
17015
17015
  }
17016
17016
  const parent = this._t(
17017
17017
  slices.join(SLASH) + SLASH,
@@ -17019,29 +17019,29 @@ var require_ignore = __commonJS({
17019
17019
  checkUnignored,
17020
17020
  slices
17021
17021
  );
17022
- return cache3[path80] = parent.ignored ? parent : this._rules.test(path80, checkUnignored, MODE_IGNORE);
17022
+ return cache3[path81] = parent.ignored ? parent : this._rules.test(path81, checkUnignored, MODE_IGNORE);
17023
17023
  }
17024
- ignores(path80) {
17025
- return this._test(path80, this._ignoreCache, false).ignored;
17024
+ ignores(path81) {
17025
+ return this._test(path81, this._ignoreCache, false).ignored;
17026
17026
  }
17027
17027
  createFilter() {
17028
- return (path80) => !this.ignores(path80);
17028
+ return (path81) => !this.ignores(path81);
17029
17029
  }
17030
17030
  filter(paths) {
17031
17031
  return makeArray(paths).filter(this.createFilter());
17032
17032
  }
17033
17033
  // @returns {TestResult}
17034
- test(path80) {
17035
- return this._test(path80, this._testCache, true);
17034
+ test(path81) {
17035
+ return this._test(path81, this._testCache, true);
17036
17036
  }
17037
17037
  };
17038
17038
  var factory = (options) => new Ignore(options);
17039
- var isPathValid = (path80) => checkPath(path80 && checkPath.convert(path80), path80, RETURN_FALSE);
17039
+ var isPathValid = (path81) => checkPath(path81 && checkPath.convert(path81), path81, RETURN_FALSE);
17040
17040
  var setupWindows = () => {
17041
17041
  const makePosix = (str2) => /^\\\\\?\\/.test(str2) || /["<>|\u0000-\u001F]+/u.test(str2) ? str2 : str2.replace(/\\/g, "/");
17042
17042
  checkPath.convert = makePosix;
17043
17043
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
17044
- checkPath.isNotRelative = (path80) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path80) || isNotRelative(path80);
17044
+ checkPath.isNotRelative = (path81) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path81) || isNotRelative(path81);
17045
17045
  };
17046
17046
  if (
17047
17047
  // Detect `process` so that it can run in browsers.
@@ -18782,18 +18782,18 @@ function extractRouterMount(callNode, filePath) {
18782
18782
  const routerName = args[0]?.type === "identifier" ? args[0].text : null;
18783
18783
  if (!routerName)
18784
18784
  return null;
18785
- let path80 = "/";
18785
+ let path81 = "/";
18786
18786
  for (const arg of args) {
18787
18787
  if (arg.type === "keyword_argument") {
18788
18788
  const key4 = arg.childForFieldName("name")?.text;
18789
18789
  const value = arg.childForFieldName("value");
18790
18790
  if ((key4 === "url_prefix" || key4 === "prefix") && value) {
18791
- path80 = value.text.replace(/^["']|["']$/g, "");
18791
+ path81 = value.text.replace(/^["']|["']$/g, "");
18792
18792
  }
18793
18793
  }
18794
18794
  }
18795
18795
  return {
18796
- path: path80,
18796
+ path: path81,
18797
18797
  routerName,
18798
18798
  location: {
18799
18799
  filePath,
@@ -18817,11 +18817,11 @@ function extractChainedRoute(outerCall, filePath) {
18817
18817
  const innerArgs = innerCall.childForFieldName("arguments");
18818
18818
  if (!innerArgs)
18819
18819
  return null;
18820
- let path80 = null;
18820
+ let path81 = null;
18821
18821
  let httpMethod = methodName3 === "route" ? "GET" : methodName3.toUpperCase();
18822
18822
  for (const arg of innerArgs.namedChildren) {
18823
- if (!path80 && arg.type === "string") {
18824
- path80 = arg.text.replace(/^["']|["']$/g, "");
18823
+ if (!path81 && arg.type === "string") {
18824
+ path81 = arg.text.replace(/^["']|["']$/g, "");
18825
18825
  }
18826
18826
  if (arg.type === "keyword_argument") {
18827
18827
  const key4 = arg.childForFieldName("name")?.text;
@@ -18833,14 +18833,14 @@ function extractChainedRoute(outerCall, filePath) {
18833
18833
  }
18834
18834
  }
18835
18835
  }
18836
- if (!path80)
18836
+ if (!path81)
18837
18837
  return null;
18838
18838
  const outerArgs = outerCall.childForFieldName("arguments");
18839
18839
  const handlerArg = outerArgs?.namedChildren[0];
18840
18840
  const handlerName = handlerArg?.type === "identifier" ? handlerArg.text : "anonymous";
18841
18841
  return {
18842
18842
  httpMethod,
18843
- path: path80,
18843
+ path: path81,
18844
18844
  handlerName,
18845
18845
  location: {
18846
18846
  filePath,
@@ -18902,11 +18902,11 @@ function collectGroupPrefixes(root2) {
18902
18902
  const fn = child.childForFieldName("function");
18903
18903
  if (fn?.type === "member_access_expression" && fn.childForFieldName("name")?.text === "MapGroup") {
18904
18904
  const args = child.childForFieldName("arguments");
18905
- const path80 = args ? extractFirstStringArg(args) : null;
18906
- if (name && path80) {
18905
+ const path81 = args ? extractFirstStringArg(args) : null;
18906
+ if (name && path81) {
18907
18907
  const receiver = fn.childForFieldName("expression")?.text ?? "";
18908
18908
  const parentPrefix = prefixes.get(receiver) ?? "";
18909
- prefixes.set(name, joinRoute(parentPrefix, path80));
18909
+ prefixes.set(name, joinRoute(parentPrefix, path81));
18910
18910
  }
18911
18911
  }
18912
18912
  }
@@ -18930,9 +18930,9 @@ function extractClassRoutePrefix(classNode) {
18930
18930
  continue;
18931
18931
  const args = childOfType(attr, "attribute_argument_list");
18932
18932
  if (args) {
18933
- const path80 = extractFirstStringArg(args);
18934
- if (path80)
18935
- return path80;
18933
+ const path81 = extractFirstStringArg(args);
18934
+ if (path81)
18935
+ return path81;
18936
18936
  }
18937
18937
  }
18938
18938
  }
@@ -18955,16 +18955,16 @@ function extractAttributeRoute(methodNode, filePath, classContext) {
18955
18955
  httpMethod = method;
18956
18956
  const args = childOfType(attr, "attribute_argument_list");
18957
18957
  if (args) {
18958
- const path80 = extractFirstStringArg(args);
18959
- if (path80)
18960
- routePath = path80;
18958
+ const path81 = extractFirstStringArg(args);
18959
+ if (path81)
18960
+ routePath = path81;
18961
18961
  }
18962
18962
  } else if (name === "Route" && !routePath) {
18963
18963
  const args = childOfType(attr, "attribute_argument_list");
18964
18964
  if (args) {
18965
- const path80 = extractFirstStringArg(args);
18966
- if (path80)
18967
- routePath = path80;
18965
+ const path81 = extractFirstStringArg(args);
18966
+ if (path81)
18967
+ routePath = path81;
18968
18968
  }
18969
18969
  }
18970
18970
  }
@@ -18998,12 +18998,12 @@ function extractMinimalApiRoute(callNode, filePath, groupPrefixes) {
18998
18998
  const argsNode = callNode.childForFieldName("arguments");
18999
18999
  if (!argsNode)
19000
19000
  return null;
19001
- const path80 = extractFirstStringArg(argsNode);
19002
- if (path80 === null)
19001
+ const path81 = extractFirstStringArg(argsNode);
19002
+ if (path81 === null)
19003
19003
  return null;
19004
19004
  const receiver = funcNode.childForFieldName("expression")?.text ?? "";
19005
19005
  const prefix = groupPrefixes.get(receiver) ?? "";
19006
- let fullPath = joinRoute(prefix, path80);
19006
+ let fullPath = joinRoute(prefix, path81);
19007
19007
  if (!fullPath.startsWith("/"))
19008
19008
  fullPath = "/" + fullPath;
19009
19009
  let handlerName = "anonymous";
@@ -19030,11 +19030,11 @@ function childOfType(node2, type2) {
19030
19030
  }
19031
19031
  return null;
19032
19032
  }
19033
- function joinRoute(prefix, path80) {
19033
+ function joinRoute(prefix, path81) {
19034
19034
  const p2 = prefix.replace(/\/$/, "");
19035
- const s = path80.replace(/^\//, "");
19035
+ const s = path81.replace(/^\//, "");
19036
19036
  if (!p2)
19037
- return path80;
19037
+ return path81;
19038
19038
  if (!s)
19039
19039
  return p2;
19040
19040
  return `${p2}/${s}`;
@@ -19143,8 +19143,8 @@ function extractRoute(methodName3, argsNode, filePath, callNode) {
19143
19143
  const firstArg = argsNode.namedChild(0);
19144
19144
  if (!firstArg)
19145
19145
  return null;
19146
- const path80 = extractStringLiteral(firstArg);
19147
- if (!path80)
19146
+ const path81 = extractStringLiteral(firstArg);
19147
+ if (!path81)
19148
19148
  return null;
19149
19149
  const argCount = argsNode.namedChildCount;
19150
19150
  if (argCount < 2)
@@ -19157,7 +19157,7 @@ function extractRoute(methodName3, argsNode, filePath, callNode) {
19157
19157
  return null;
19158
19158
  return {
19159
19159
  httpMethod: methodName3.toUpperCase(),
19160
- path: path80,
19160
+ path: path81,
19161
19161
  handlerName,
19162
19162
  location: {
19163
19163
  filePath,
@@ -19174,8 +19174,8 @@ function extractMount(argsNode, filePath, callNode) {
19174
19174
  const firstArg = argsNode.namedChild(0);
19175
19175
  if (!firstArg)
19176
19176
  return null;
19177
- const path80 = extractStringLiteral(firstArg);
19178
- if (!path80)
19177
+ const path81 = extractStringLiteral(firstArg);
19178
+ if (!path81)
19179
19179
  return null;
19180
19180
  const secondArg = argsNode.namedChild(1);
19181
19181
  if (!secondArg)
@@ -19184,7 +19184,7 @@ function extractMount(argsNode, filePath, callNode) {
19184
19184
  if (!routerName)
19185
19185
  return null;
19186
19186
  return {
19187
- path: path80,
19187
+ path: path81,
19188
19188
  routerName,
19189
19189
  location: {
19190
19190
  filePath,
@@ -21715,11 +21715,11 @@ function buildCSharpSymbolIndex(files, rootPath) {
21715
21715
  byFullName.get(full).push(decl);
21716
21716
  }
21717
21717
  const stats = { resolvedRefs: 0, ambiguousRefs: 0 };
21718
- function resolveQualified(path80) {
21719
- const exact = byFullName.get(path80);
21718
+ function resolveQualified(path81) {
21719
+ const exact = byFullName.get(path81);
21720
21720
  if (exact)
21721
21721
  return exact;
21722
- const parts = path80.split(".");
21722
+ const parts = path81.split(".");
21723
21723
  for (let i = parts.length - 1; i > 0; i--) {
21724
21724
  const prefix = parts.slice(0, i).join(".");
21725
21725
  const found = byFullName.get(prefix);
@@ -21733,8 +21733,8 @@ function buildCSharpSymbolIndex(files, rootPath) {
21733
21733
  const firstDot = ref.name.indexOf(".");
21734
21734
  const head = ref.name.slice(0, firstDot);
21735
21735
  const aliasTarget2 = aliases.get(head);
21736
- const path80 = aliasTarget2 ? `${aliasTarget2}${ref.name.slice(firstDot)}` : ref.name;
21737
- return resolveQualified(path80).filter((d3) => isDeclVisibleFrom(d3, ctx.project, fileProjects.get(d3.filePath)));
21736
+ const path81 = aliasTarget2 ? `${aliasTarget2}${ref.name.slice(firstDot)}` : ref.name;
21737
+ return resolveQualified(path81).filter((d3) => isDeclVisibleFrom(d3, ctx.project, fileProjects.get(d3.filePath)));
21738
21738
  }
21739
21739
  const aliasTarget = aliases.get(ref.name);
21740
21740
  if (aliasTarget) {
@@ -24855,9 +24855,9 @@ function detectDockerComposeServices(rootPath, allFiles) {
24855
24855
  ];
24856
24856
  let composePath2 = null;
24857
24857
  for (const file of composeFiles) {
24858
- const path80 = join8(rootPath, file);
24859
- if (existsSync7(path80)) {
24860
- composePath2 = path80;
24858
+ const path81 = join8(rootPath, file);
24859
+ if (existsSync7(path81)) {
24860
+ composePath2 = path81;
24861
24861
  break;
24862
24862
  }
24863
24863
  }
@@ -28077,9 +28077,9 @@ function findSimpleCycles(component, componentSet, adjacency) {
28077
28077
  for (const next of successors) {
28078
28078
  if (!componentSet.has(next))
28079
28079
  continue;
28080
- if (next === start && path80.length >= 2) {
28081
- const chain = [...path80, start];
28082
- const minNode = path80.reduce((a, b) => a < b ? a : b);
28080
+ if (next === start && path81.length >= 2) {
28081
+ const chain = [...path81, start];
28082
+ const minNode = path81.reduce((a, b) => a < b ? a : b);
28083
28083
  if (minNode === start) {
28084
28084
  cycles.push(chain);
28085
28085
  }
@@ -28087,15 +28087,15 @@ function findSimpleCycles(component, componentSet, adjacency) {
28087
28087
  }
28088
28088
  if (!visited.has(next) && !seen.has(next)) {
28089
28089
  visited.add(next);
28090
- path80.push(next);
28090
+ path81.push(next);
28091
28091
  dfs2(next);
28092
- path80.pop();
28092
+ path81.pop();
28093
28093
  visited.delete(next);
28094
28094
  }
28095
28095
  }
28096
28096
  };
28097
28097
  var dfs = dfs2;
28098
- const path80 = [start];
28098
+ const path81 = [start];
28099
28099
  const visited = /* @__PURE__ */ new Set([start]);
28100
28100
  dfs2(start);
28101
28101
  seen.add(start);
@@ -28117,7 +28117,7 @@ function findShortestCycle(start, componentSet, adjacency) {
28117
28117
  visited.add(next);
28118
28118
  }
28119
28119
  while (queue.length > 0) {
28120
- const { node: node2, path: path80 } = queue.shift();
28120
+ const { node: node2, path: path81 } = queue.shift();
28121
28121
  const nexts = adjacency.get(node2);
28122
28122
  if (!nexts)
28123
28123
  continue;
@@ -28125,11 +28125,11 @@ function findShortestCycle(start, componentSet, adjacency) {
28125
28125
  if (!componentSet.has(next))
28126
28126
  continue;
28127
28127
  if (next === start) {
28128
- return [...path80, start];
28128
+ return [...path81, start];
28129
28129
  }
28130
28130
  if (!visited.has(next)) {
28131
28131
  visited.add(next);
28132
- queue.push({ node: next, path: [...path80, next] });
28132
+ queue.push({ node: next, path: [...path81, next] });
28133
28133
  }
28134
28134
  }
28135
28135
  }
@@ -105838,11 +105838,8 @@ var init_guard = __esm({
105838
105838
  });
105839
105839
 
105840
105840
  // packages/shared/dist/spec/overlap-resolution.js
105841
- function coveringRelationInAreas(relations, a, b, areas) {
105842
- return relations.find((r) => {
105843
- const samePair = r.older === a && r.newer === b || r.older === b && r.newer === a;
105844
- return samePair && (r.scope === void 0 || areas.includes(r.scope));
105845
- });
105841
+ function normalizeQuote(text4) {
105842
+ return text4.replace(/[`*_~]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
105846
105843
  }
105847
105844
  function dedupeCrossAreaOverlaps(entries) {
105848
105845
  const byPair = /* @__PURE__ */ new Map();
@@ -105916,9 +105913,23 @@ function dedupeCrossAreaOverlaps(entries) {
105916
105913
  });
105917
105914
  return merged;
105918
105915
  }
105916
+ function resolutionMatchesConflict(r, a, b, sections) {
105917
+ if (!samePair(r.docA, r.docB, a, b))
105918
+ return false;
105919
+ const rSide = (doc) => doc === r.docA ? { anchor: r.anchorA, quote: r.quoteA } : { anchor: r.anchorB, quote: r.quoteB };
105920
+ const cSide = (doc) => (sections ?? []).find((s) => s.doc === doc);
105921
+ const bothHaveQuotes = !!r.quoteA && !!r.quoteB && !!cSide(a)?.quote && !!cSide(b)?.quote;
105922
+ if (bothHaveQuotes) {
105923
+ const quoteMatch = (doc) => normalizeQuote(rSide(doc).quote ?? "") === normalizeQuote(cSide(doc)?.quote ?? "");
105924
+ return quoteMatch(a) && quoteMatch(b);
105925
+ }
105926
+ const anchorMatch = (doc) => anchorKey(rSide(doc).anchor) === anchorKey(cSide(doc)?.heading);
105927
+ return anchorMatch(a) && anchorMatch(b);
105928
+ }
105929
+ function matchResolution(decisions, a, b, sections) {
105930
+ return (decisions.conflictResolutions ?? []).find((r) => resolutionMatchesConflict(r, a, b, sections));
105931
+ }
105919
105932
  function buildCorpusConflicts(corpus, decisions) {
105920
- const userRelations = decisions.relations ?? [];
105921
- const effectiveRels = [...corpus.relations, ...userRelations];
105922
105933
  const excludes = new Set(decisions.manualExcludes ?? []);
105923
105934
  const entries = [];
105924
105935
  for (const area of corpus.areas)
@@ -105928,43 +105939,46 @@ function buildCorpusConflicts(corpus, decisions) {
105928
105939
  const flagged = [];
105929
105940
  for (const m of mergedOverlaps) {
105930
105941
  const [a, b] = m.overlap.docs;
105931
- const relation = coveringRelationInAreas(effectiveRels, a, b, m.areas);
105932
- const userRelation = coveringRelationInAreas(userRelations, a, b, m.areas);
105942
+ const sections = m.overlap.sections ? [...m.overlap.sections] : void 0;
105933
105943
  const excludedRef = excludes.has(a) ? a : excludes.has(b) ? b : void 0;
105944
+ const resolution = matchResolution(decisions, a, b, sections);
105934
105945
  flagged.push({
105935
105946
  area: m.area,
105936
105947
  areas: m.areas,
105937
105948
  a,
105938
105949
  b,
105939
105950
  note: m.overlap.note ?? "",
105940
- resolved: relation !== void 0 || excludedRef !== void 0,
105941
- synthesized: false,
105942
- ...relation ? { relation } : {},
105943
- ...userRelation ? { userRelation } : {},
105944
- ...excludedRef ? { excludedRef } : {}
105951
+ ...sections ? { sections } : {},
105952
+ resolved: excludedRef !== void 0 || resolution !== void 0,
105953
+ ...excludedRef ? { excludedRef } : {},
105954
+ ...resolution ? { resolution } : {}
105945
105955
  });
105946
105956
  }
105947
- const coversFlagged = (r) => flagged.some((o) => {
105948
- const samePair = o.a === r.older && o.b === r.newer || o.a === r.newer && o.b === r.older;
105949
- return samePair && (r.scope === void 0 || o.areas.includes(r.scope));
105950
- });
105951
- const synthesized = userRelations.filter((r) => !coversFlagged(r)).map((r) => ({
105952
- area: r.scope ?? "",
105953
- areas: r.scope ? [r.scope] : [],
105954
- a: r.older,
105955
- b: r.newer,
105956
- note: r.note ?? "",
105957
- resolved: true,
105958
- synthesized: true,
105959
- relation: r,
105960
- userRelation: r
105961
- }));
105962
- return [...flagged, ...synthesized];
105957
+ return flagged;
105963
105958
  }
105964
105959
  function openConflicts(corpus, decisions) {
105965
105960
  return buildCorpusConflicts(corpus, decisions).filter((c2) => !c2.resolved);
105966
105961
  }
105967
- var PREAMBLE_PTR, NUL, unorderedPairKey, sectionPointerKeys, preambleCount;
105962
+ function orphanedConflictResolutions(corpus, decisions) {
105963
+ const resolutions = decisions.conflictResolutions ?? [];
105964
+ if (resolutions.length === 0)
105965
+ return [];
105966
+ const conflicts2 = buildCorpusConflicts(corpus, decisions);
105967
+ return resolutions.filter((r) => !conflicts2.some((c2) => resolutionMatchesConflict(r, c2.a, c2.b, c2.sections)));
105968
+ }
105969
+ function suppressedClaims(corpus, decisions) {
105970
+ const out = [];
105971
+ for (const c2 of buildCorpusConflicts(corpus, decisions)) {
105972
+ const r = c2.resolution;
105973
+ if (!r || r.verdict === "dismissed")
105974
+ continue;
105975
+ const loser = r.verdict === "a" ? { doc: r.docB, anchor: r.anchorB, quote: r.quoteB } : { doc: r.docA, anchor: r.anchorA, quote: r.quoteA };
105976
+ if (loser.quote && loser.quote.trim())
105977
+ out.push({ doc: loser.doc, anchor: loser.anchor, quote: loser.quote });
105978
+ }
105979
+ return out;
105980
+ }
105981
+ var PREAMBLE_PTR, NUL, unorderedPairKey, sectionPointerKeys, preambleCount, samePair, anchorKey;
105968
105982
  var init_overlap_resolution = __esm({
105969
105983
  "packages/shared/dist/spec/overlap-resolution.js"() {
105970
105984
  "use strict";
@@ -105973,6 +105987,8 @@ var init_overlap_resolution = __esm({
105973
105987
  unorderedPairKey = (a, b) => a < b ? `${a}${NUL}${b}` : `${b}${NUL}${a}`;
105974
105988
  sectionPointerKeys = (ov) => (ov.sections ?? []).map((s) => `${s.doc}${NUL}${s.heading ?? PREAMBLE_PTR}`);
105975
105989
  preambleCount = (ov) => (ov.sections ?? []).filter((s) => s.heading === null || s.heading === void 0).length;
105990
+ samePair = (a1, b1, a2, b2) => a1 === a2 && b1 === b2 || a1 === b2 && b1 === a2;
105991
+ anchorKey = (h) => h === null || h === void 0 ? null : h.replace(/[`*_~]/g, "").trim().toLowerCase();
105976
105992
  }
105977
105993
  });
105978
105994
 
@@ -112402,14 +112418,14 @@ var init_missing_error_status_code = __esm({
112402
112418
  });
112403
112419
 
112404
112420
  // packages/analyzer/dist/rules/architecture/visitors/javascript/route-without-auth-middleware.js
112405
- function isPublicPath(path80) {
112406
- return PUBLIC_PATH_PATTERNS.some((re2) => re2.test(path80));
112421
+ function isPublicPath(path81) {
112422
+ return PUBLIC_PATH_PATTERNS.some((re2) => re2.test(path81));
112407
112423
  }
112408
- function isUrlCredentialAuthedPath(path80) {
112409
- return URL_CREDENTIAL_PARAMS.test(path80);
112424
+ function isUrlCredentialAuthedPath(path81) {
112425
+ return URL_CREDENTIAL_PARAMS.test(path81);
112410
112426
  }
112411
- function isApiDocsPath(path80) {
112412
- return API_DOCS_PATH.test(path80);
112427
+ function isApiDocsPath(path81) {
112428
+ return API_DOCS_PATH.test(path81);
112413
112429
  }
112414
112430
  function isFrameworkRequestHandler(arg) {
112415
112431
  if (!arg)
@@ -112558,14 +112574,14 @@ var init_route_without_auth_middleware = __esm({
112558
112574
  return null;
112559
112575
  const firstArg = args.namedChildren[0];
112560
112576
  if (firstArg?.type === "string" || firstArg?.type === "template_string") {
112561
- const path80 = firstArg.text.replace(/^['"`]|['"`]$/g, "");
112562
- if (isPublicPath(path80))
112577
+ const path81 = firstArg.text.replace(/^['"`]|['"`]$/g, "");
112578
+ if (isPublicPath(path81))
112563
112579
  return null;
112564
- if (isUrlCredentialAuthedPath(path80))
112580
+ if (isUrlCredentialAuthedPath(path81))
112565
112581
  return null;
112566
- if (isApiDocsPath(path80))
112582
+ if (isApiDocsPath(path81))
112567
112583
  return null;
112568
- if (path80 === "*" || path80 === "(.*)" || path80 === "/*") {
112584
+ if (path81 === "*" || path81 === "(.*)" || path81 === "/*") {
112569
112585
  if (isFrameworkRequestHandler(args.namedChildren[args.namedChildren.length - 1])) {
112570
112586
  return null;
112571
112587
  }
@@ -147471,8 +147487,8 @@ var require_windows = __commonJS({
147471
147487
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module) {
147472
147488
  module.exports = isexe;
147473
147489
  isexe.sync = sync;
147474
- var fs71 = __require("fs");
147475
- function checkPathExt(path80, options) {
147490
+ var fs72 = __require("fs");
147491
+ function checkPathExt(path81, options) {
147476
147492
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
147477
147493
  if (!pathext) {
147478
147494
  return true;
@@ -147483,25 +147499,25 @@ var require_windows = __commonJS({
147483
147499
  }
147484
147500
  for (var i = 0; i < pathext.length; i++) {
147485
147501
  var p2 = pathext[i].toLowerCase();
147486
- if (p2 && path80.substr(-p2.length).toLowerCase() === p2) {
147502
+ if (p2 && path81.substr(-p2.length).toLowerCase() === p2) {
147487
147503
  return true;
147488
147504
  }
147489
147505
  }
147490
147506
  return false;
147491
147507
  }
147492
- function checkStat(stat, path80, options) {
147508
+ function checkStat(stat, path81, options) {
147493
147509
  if (!stat.isSymbolicLink() && !stat.isFile()) {
147494
147510
  return false;
147495
147511
  }
147496
- return checkPathExt(path80, options);
147512
+ return checkPathExt(path81, options);
147497
147513
  }
147498
- function isexe(path80, options, cb) {
147499
- fs71.stat(path80, function(er, stat) {
147500
- cb(er, er ? false : checkStat(stat, path80, options));
147514
+ function isexe(path81, options, cb) {
147515
+ fs72.stat(path81, function(er, stat) {
147516
+ cb(er, er ? false : checkStat(stat, path81, options));
147501
147517
  });
147502
147518
  }
147503
- function sync(path80, options) {
147504
- return checkStat(fs71.statSync(path80), path80, options);
147519
+ function sync(path81, options) {
147520
+ return checkStat(fs72.statSync(path81), path81, options);
147505
147521
  }
147506
147522
  }
147507
147523
  });
@@ -147511,14 +147527,14 @@ var require_mode = __commonJS({
147511
147527
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module) {
147512
147528
  module.exports = isexe;
147513
147529
  isexe.sync = sync;
147514
- var fs71 = __require("fs");
147515
- function isexe(path80, options, cb) {
147516
- fs71.stat(path80, function(er, stat) {
147530
+ var fs72 = __require("fs");
147531
+ function isexe(path81, options, cb) {
147532
+ fs72.stat(path81, function(er, stat) {
147517
147533
  cb(er, er ? false : checkStat(stat, options));
147518
147534
  });
147519
147535
  }
147520
- function sync(path80, options) {
147521
- return checkStat(fs71.statSync(path80), options);
147536
+ function sync(path81, options) {
147537
+ return checkStat(fs72.statSync(path81), options);
147522
147538
  }
147523
147539
  function checkStat(stat, options) {
147524
147540
  return stat.isFile() && checkMode(stat, options);
@@ -147542,7 +147558,7 @@ var require_mode = __commonJS({
147542
147558
  // node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
147543
147559
  var require_isexe = __commonJS({
147544
147560
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
147545
- var fs71 = __require("fs");
147561
+ var fs72 = __require("fs");
147546
147562
  var core2;
147547
147563
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
147548
147564
  core2 = require_windows();
@@ -147551,7 +147567,7 @@ var require_isexe = __commonJS({
147551
147567
  }
147552
147568
  module.exports = isexe;
147553
147569
  isexe.sync = sync;
147554
- function isexe(path80, options, cb) {
147570
+ function isexe(path81, options, cb) {
147555
147571
  if (typeof options === "function") {
147556
147572
  cb = options;
147557
147573
  options = {};
@@ -147561,7 +147577,7 @@ var require_isexe = __commonJS({
147561
147577
  throw new TypeError("callback not provided");
147562
147578
  }
147563
147579
  return new Promise(function(resolve12, reject) {
147564
- isexe(path80, options || {}, function(er, is) {
147580
+ isexe(path81, options || {}, function(er, is) {
147565
147581
  if (er) {
147566
147582
  reject(er);
147567
147583
  } else {
@@ -147570,7 +147586,7 @@ var require_isexe = __commonJS({
147570
147586
  });
147571
147587
  });
147572
147588
  }
147573
- core2(path80, options || {}, function(er, is) {
147589
+ core2(path81, options || {}, function(er, is) {
147574
147590
  if (er) {
147575
147591
  if (er.code === "EACCES" || options && options.ignoreErrors) {
147576
147592
  er = null;
@@ -147580,9 +147596,9 @@ var require_isexe = __commonJS({
147580
147596
  cb(er, is);
147581
147597
  });
147582
147598
  }
147583
- function sync(path80, options) {
147599
+ function sync(path81, options) {
147584
147600
  try {
147585
- return core2.sync(path80, options || {});
147601
+ return core2.sync(path81, options || {});
147586
147602
  } catch (er) {
147587
147603
  if (options && options.ignoreErrors || er.code === "EACCES") {
147588
147604
  return false;
@@ -147598,7 +147614,7 @@ var require_isexe = __commonJS({
147598
147614
  var require_which = __commonJS({
147599
147615
  "node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports, module) {
147600
147616
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
147601
- var path80 = __require("path");
147617
+ var path81 = __require("path");
147602
147618
  var COLON = isWindows ? ";" : ":";
147603
147619
  var isexe = require_isexe();
147604
147620
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -147636,7 +147652,7 @@ var require_which = __commonJS({
147636
147652
  return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
147637
147653
  const ppRaw = pathEnv[i];
147638
147654
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
147639
- const pCmd = path80.join(pathPart, cmd);
147655
+ const pCmd = path81.join(pathPart, cmd);
147640
147656
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
147641
147657
  resolve12(subStep(p2, i, 0));
147642
147658
  });
@@ -147663,7 +147679,7 @@ var require_which = __commonJS({
147663
147679
  for (let i = 0; i < pathEnv.length; i++) {
147664
147680
  const ppRaw = pathEnv[i];
147665
147681
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
147666
- const pCmd = path80.join(pathPart, cmd);
147682
+ const pCmd = path81.join(pathPart, cmd);
147667
147683
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
147668
147684
  for (let j2 = 0; j2 < pathExt.length; j2++) {
147669
147685
  const cur = p2 + pathExt[j2];
@@ -147711,7 +147727,7 @@ var require_path_key = __commonJS({
147711
147727
  var require_resolveCommand = __commonJS({
147712
147728
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
147713
147729
  "use strict";
147714
- var path80 = __require("path");
147730
+ var path81 = __require("path");
147715
147731
  var which = require_which();
147716
147732
  var getPathKey = require_path_key();
147717
147733
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -147729,7 +147745,7 @@ var require_resolveCommand = __commonJS({
147729
147745
  try {
147730
147746
  resolved = which.sync(parsed.command, {
147731
147747
  path: env[getPathKey({ env })],
147732
- pathExt: withoutPathExt ? path80.delimiter : void 0
147748
+ pathExt: withoutPathExt ? path81.delimiter : void 0
147733
147749
  });
147734
147750
  } catch (e) {
147735
147751
  } finally {
@@ -147738,7 +147754,7 @@ var require_resolveCommand = __commonJS({
147738
147754
  }
147739
147755
  }
147740
147756
  if (resolved) {
147741
- resolved = path80.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
147757
+ resolved = path81.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
147742
147758
  }
147743
147759
  return resolved;
147744
147760
  }
@@ -147792,8 +147808,8 @@ var require_shebang_command = __commonJS({
147792
147808
  if (!match4) {
147793
147809
  return null;
147794
147810
  }
147795
- const [path80, argument] = match4[0].replace(/#! ?/, "").split(" ");
147796
- const binary2 = path80.split("/").pop();
147811
+ const [path81, argument] = match4[0].replace(/#! ?/, "").split(" ");
147812
+ const binary2 = path81.split("/").pop();
147797
147813
  if (binary2 === "env") {
147798
147814
  return argument;
147799
147815
  }
@@ -147806,16 +147822,16 @@ var require_shebang_command = __commonJS({
147806
147822
  var require_readShebang = __commonJS({
147807
147823
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
147808
147824
  "use strict";
147809
- var fs71 = __require("fs");
147825
+ var fs72 = __require("fs");
147810
147826
  var shebangCommand = require_shebang_command();
147811
147827
  function readShebang(command) {
147812
147828
  const size = 150;
147813
147829
  const buffer = Buffer.alloc(size);
147814
147830
  let fd;
147815
147831
  try {
147816
- fd = fs71.openSync(command, "r");
147817
- fs71.readSync(fd, buffer, 0, size, 0);
147818
- fs71.closeSync(fd);
147832
+ fd = fs72.openSync(command, "r");
147833
+ fs72.readSync(fd, buffer, 0, size, 0);
147834
+ fs72.closeSync(fd);
147819
147835
  } catch (e) {
147820
147836
  }
147821
147837
  return shebangCommand(buffer.toString());
@@ -147828,7 +147844,7 @@ var require_readShebang = __commonJS({
147828
147844
  var require_parse = __commonJS({
147829
147845
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
147830
147846
  "use strict";
147831
- var path80 = __require("path");
147847
+ var path81 = __require("path");
147832
147848
  var resolveCommand = require_resolveCommand();
147833
147849
  var escape2 = require_escape();
147834
147850
  var readShebang = require_readShebang();
@@ -147853,7 +147869,7 @@ var require_parse = __commonJS({
147853
147869
  const needsShell = !isExecutableRegExp.test(commandFile);
147854
147870
  if (parsed.options.forceShell || needsShell) {
147855
147871
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
147856
- parsed.command = path80.normalize(parsed.command);
147872
+ parsed.command = path81.normalize(parsed.command);
147857
147873
  parsed.command = escape2.command(parsed.command);
147858
147874
  parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
147859
147875
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -148219,8 +148235,8 @@ var require_package = __commonJS({
148219
148235
  // node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js
148220
148236
  var require_main = __commonJS({
148221
148237
  "node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/lib/main.js"(exports, module) {
148222
- var fs71 = __require("fs");
148223
- var path80 = __require("path");
148238
+ var fs72 = __require("fs");
148239
+ var path81 = __require("path");
148224
148240
  var os15 = __require("os");
148225
148241
  var crypto6 = __require("crypto");
148226
148242
  var packageJson = require_package();
@@ -148328,7 +148344,7 @@ var require_main = __commonJS({
148328
148344
  if (options && options.path && options.path.length > 0) {
148329
148345
  if (Array.isArray(options.path)) {
148330
148346
  for (const filepath of options.path) {
148331
- if (fs71.existsSync(filepath)) {
148347
+ if (fs72.existsSync(filepath)) {
148332
148348
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
148333
148349
  }
148334
148350
  }
@@ -148336,15 +148352,15 @@ var require_main = __commonJS({
148336
148352
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
148337
148353
  }
148338
148354
  } else {
148339
- possibleVaultPath = path80.resolve(process.cwd(), ".env.vault");
148355
+ possibleVaultPath = path81.resolve(process.cwd(), ".env.vault");
148340
148356
  }
148341
- if (fs71.existsSync(possibleVaultPath)) {
148357
+ if (fs72.existsSync(possibleVaultPath)) {
148342
148358
  return possibleVaultPath;
148343
148359
  }
148344
148360
  return null;
148345
148361
  }
148346
148362
  function _resolveHome(envPath) {
148347
- return envPath[0] === "~" ? path80.join(os15.homedir(), envPath.slice(1)) : envPath;
148363
+ return envPath[0] === "~" ? path81.join(os15.homedir(), envPath.slice(1)) : envPath;
148348
148364
  }
148349
148365
  function _configVault(options) {
148350
148366
  const debug2 = Boolean(options && options.debug);
@@ -148361,7 +148377,7 @@ var require_main = __commonJS({
148361
148377
  return { parsed };
148362
148378
  }
148363
148379
  function configDotenv(options) {
148364
- const dotenvPath = path80.resolve(process.cwd(), ".env");
148380
+ const dotenvPath = path81.resolve(process.cwd(), ".env");
148365
148381
  let encoding = "utf8";
148366
148382
  const debug2 = Boolean(options && options.debug);
148367
148383
  const quiet = options && "quiet" in options ? options.quiet : true;
@@ -148385,13 +148401,13 @@ var require_main = __commonJS({
148385
148401
  }
148386
148402
  let lastError;
148387
148403
  const parsedAll = {};
148388
- for (const path81 of optionPaths) {
148404
+ for (const path82 of optionPaths) {
148389
148405
  try {
148390
- const parsed = DotenvModule.parse(fs71.readFileSync(path81, { encoding }));
148406
+ const parsed = DotenvModule.parse(fs72.readFileSync(path82, { encoding }));
148391
148407
  DotenvModule.populate(parsedAll, parsed, options);
148392
148408
  } catch (e) {
148393
148409
  if (debug2) {
148394
- _debug(`Failed to load ${path81} ${e.message}`);
148410
+ _debug(`Failed to load ${path82} ${e.message}`);
148395
148411
  }
148396
148412
  lastError = e;
148397
148413
  }
@@ -148406,7 +148422,7 @@ var require_main = __commonJS({
148406
148422
  const shortPaths = [];
148407
148423
  for (const filePath of optionPaths) {
148408
148424
  try {
148409
- const relative2 = path80.relative(process.cwd(), filePath);
148425
+ const relative2 = path81.relative(process.cwd(), filePath);
148410
148426
  shortPaths.push(relative2);
148411
148427
  } catch (e) {
148412
148428
  if (debug2) {
@@ -149265,8 +149281,8 @@ var init_cli_provider = __esm({
149265
149281
  this._repoId = repoId;
149266
149282
  }
149267
149283
  /** Set target repo path — used as cwd when spawning CLI so Read tool accesses the right files. */
149268
- setRepoPath(path80) {
149269
- this._repoPath = path80;
149284
+ setRepoPath(path81) {
149285
+ this._repoPath = path81;
149270
149286
  }
149271
149287
  flushUsage() {
149272
149288
  if (this._usageRecords.length === 0)
@@ -161397,11 +161413,11 @@ var require_mime_types = __commonJS({
161397
161413
  }
161398
161414
  return exts[0];
161399
161415
  }
161400
- function lookup(path80) {
161401
- if (!path80 || typeof path80 !== "string") {
161416
+ function lookup(path81) {
161417
+ if (!path81 || typeof path81 !== "string") {
161402
161418
  return false;
161403
161419
  }
161404
- var extension2 = extname("x." + path80).toLowerCase().substr(1);
161420
+ var extension2 = extname("x." + path81).toLowerCase().substr(1);
161405
161421
  if (!extension2) {
161406
161422
  return false;
161407
161423
  }
@@ -162506,11 +162522,11 @@ var require_form_data = __commonJS({
162506
162522
  "use strict";
162507
162523
  var CombinedStream = require_combined_stream();
162508
162524
  var util2 = __require("util");
162509
- var path80 = __require("path");
162525
+ var path81 = __require("path");
162510
162526
  var http = __require("http");
162511
162527
  var https = __require("https");
162512
162528
  var parseUrl = __require("url").parse;
162513
- var fs71 = __require("fs");
162529
+ var fs72 = __require("fs");
162514
162530
  var Stream = __require("stream").Stream;
162515
162531
  var crypto6 = __require("crypto");
162516
162532
  var mime = require_mime_types();
@@ -162577,7 +162593,7 @@ var require_form_data = __commonJS({
162577
162593
  if (value.end != void 0 && value.end != Infinity && value.start != void 0) {
162578
162594
  callback(null, value.end + 1 - (value.start ? value.start : 0));
162579
162595
  } else {
162580
- fs71.stat(value.path, function(err, stat) {
162596
+ fs72.stat(value.path, function(err, stat) {
162581
162597
  if (err) {
162582
162598
  callback(err);
162583
162599
  return;
@@ -162634,11 +162650,11 @@ var require_form_data = __commonJS({
162634
162650
  FormData2.prototype._getContentDisposition = function(value, options) {
162635
162651
  var filename;
162636
162652
  if (typeof options.filepath === "string") {
162637
- filename = path80.normalize(options.filepath).replace(/\\/g, "/");
162653
+ filename = path81.normalize(options.filepath).replace(/\\/g, "/");
162638
162654
  } else if (options.filename || value && (value.name || value.path)) {
162639
- filename = path80.basename(options.filename || value && (value.name || value.path));
162655
+ filename = path81.basename(options.filename || value && (value.name || value.path));
162640
162656
  } else if (value && value.readable && hasOwn(value, "httpVersion")) {
162641
- filename = path80.basename(value.client._httpMessage.path || "");
162657
+ filename = path81.basename(value.client._httpMessage.path || "");
162642
162658
  }
162643
162659
  if (filename) {
162644
162660
  return 'filename="' + filename + '"';
@@ -163195,8 +163211,8 @@ var require_node2 = __commonJS({
163195
163211
  }
163196
163212
  break;
163197
163213
  case "FILE":
163198
- var fs71 = __require("fs");
163199
- stream2 = new fs71.SyncWriteStream(fd2, { autoClose: false });
163214
+ var fs72 = __require("fs");
163215
+ stream2 = new fs72.SyncWriteStream(fd2, { autoClose: false });
163200
163216
  stream2._type = "fs";
163201
163217
  break;
163202
163218
  case "PIPE":
@@ -164292,9 +164308,9 @@ var require_axios = __commonJS({
164292
164308
  function removeBrackets(key4) {
164293
164309
  return utils$1.endsWith(key4, "[]") ? key4.slice(0, -2) : key4;
164294
164310
  }
164295
- function renderKey(path80, key4, dots) {
164296
- if (!path80) return key4;
164297
- return path80.concat(key4).map(function each(token, i) {
164311
+ function renderKey(path81, key4, dots) {
164312
+ if (!path81) return key4;
164313
+ return path81.concat(key4).map(function each(token, i) {
164298
164314
  token = removeBrackets(token);
164299
164315
  return !dots && i ? "[" + token + "]" : token;
164300
164316
  }).join(dots ? "." : "");
@@ -164342,13 +164358,13 @@ var require_axios = __commonJS({
164342
164358
  }
164343
164359
  return value;
164344
164360
  }
164345
- function defaultVisitor(value, key4, path80) {
164361
+ function defaultVisitor(value, key4, path81) {
164346
164362
  let arr = value;
164347
164363
  if (utils$1.isReactNative(formData) && utils$1.isReactNativeBlob(value)) {
164348
- formData.append(renderKey(path80, key4, dots), convertValue(value));
164364
+ formData.append(renderKey(path81, key4, dots), convertValue(value));
164349
164365
  return false;
164350
164366
  }
164351
- if (value && !path80 && typeof value === "object") {
164367
+ if (value && !path81 && typeof value === "object") {
164352
164368
  if (utils$1.endsWith(key4, "{}")) {
164353
164369
  key4 = metaTokens ? key4 : key4.slice(0, -2);
164354
164370
  value = JSON.stringify(value);
@@ -164367,7 +164383,7 @@ var require_axios = __commonJS({
164367
164383
  if (isVisitable(value)) {
164368
164384
  return true;
164369
164385
  }
164370
- formData.append(renderKey(path80, key4, dots), convertValue(value));
164386
+ formData.append(renderKey(path81, key4, dots), convertValue(value));
164371
164387
  return false;
164372
164388
  }
164373
164389
  const stack2 = [];
@@ -164376,16 +164392,16 @@ var require_axios = __commonJS({
164376
164392
  convertValue,
164377
164393
  isVisitable
164378
164394
  });
164379
- function build8(value, path80) {
164395
+ function build8(value, path81) {
164380
164396
  if (utils$1.isUndefined(value)) return;
164381
164397
  if (stack2.indexOf(value) !== -1) {
164382
- throw Error("Circular reference detected in " + path80.join("."));
164398
+ throw Error("Circular reference detected in " + path81.join("."));
164383
164399
  }
164384
164400
  stack2.push(value);
164385
164401
  utils$1.forEach(value, function each(el, key4) {
164386
- const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key4) ? key4.trim() : key4, path80, exposedHelpers);
164402
+ const result = !(utils$1.isUndefined(el) || el === null) && visitor.call(formData, el, utils$1.isString(key4) ? key4.trim() : key4, path81, exposedHelpers);
164387
164403
  if (result === true) {
164388
- build8(el, path80 ? path80.concat(key4) : [key4]);
164404
+ build8(el, path81 ? path81.concat(key4) : [key4]);
164389
164405
  }
164390
164406
  });
164391
164407
  stack2.pop();
@@ -164574,7 +164590,7 @@ var require_axios = __commonJS({
164574
164590
  };
164575
164591
  function toURLEncodedForm(data, options) {
164576
164592
  return toFormData(data, new platform.classes.URLSearchParams(), {
164577
- visitor: function(value, key4, path80, helpers) {
164593
+ visitor: function(value, key4, path81, helpers) {
164578
164594
  if (platform.isNode && utils$1.isBuffer(value)) {
164579
164595
  this.append(key4, value.toString("base64"));
164580
164596
  return false;
@@ -164602,11 +164618,11 @@ var require_axios = __commonJS({
164602
164618
  return obj;
164603
164619
  }
164604
164620
  function formDataToJSON(formData) {
164605
- function buildPath(path80, value, target, index) {
164606
- let name = path80[index++];
164621
+ function buildPath(path81, value, target, index) {
164622
+ let name = path81[index++];
164607
164623
  if (name === "__proto__") return true;
164608
164624
  const isNumericKey = Number.isFinite(+name);
164609
- const isLast = index >= path80.length;
164625
+ const isLast = index >= path81.length;
164610
164626
  name = !name && utils$1.isArray(target) ? target.length : name;
164611
164627
  if (isLast) {
164612
164628
  if (utils$1.hasOwnProp(target, name)) {
@@ -164619,7 +164635,7 @@ var require_axios = __commonJS({
164619
164635
  if (!target[name] || !utils$1.isObject(target[name])) {
164620
164636
  target[name] = [];
164621
164637
  }
164622
- const result = buildPath(path80, value, target[name], index);
164638
+ const result = buildPath(path81, value, target[name], index);
164623
164639
  if (result && utils$1.isArray(target[name])) {
164624
164640
  target[name] = arrayToObject(target[name]);
164625
164641
  }
@@ -165937,9 +165953,9 @@ var require_axios = __commonJS({
165937
165953
  auth = urlUsername + ":" + urlPassword;
165938
165954
  }
165939
165955
  auth && headers.delete("authorization");
165940
- let path80;
165956
+ let path81;
165941
165957
  try {
165942
- path80 = buildURL(parsed.pathname + parsed.search, config2.params, config2.paramsSerializer).replace(/^\?/, "");
165958
+ path81 = buildURL(parsed.pathname + parsed.search, config2.params, config2.paramsSerializer).replace(/^\?/, "");
165943
165959
  } catch (err) {
165944
165960
  const customErr = new Error(err.message);
165945
165961
  customErr.config = config2;
@@ -165949,7 +165965,7 @@ var require_axios = __commonJS({
165949
165965
  }
165950
165966
  headers.set("Accept-Encoding", "gzip, compress, deflate" + (isBrotliSupported ? ", br" : ""), false);
165951
165967
  const options = {
165952
- path: path80,
165968
+ path: path81,
165953
165969
  method,
165954
165970
  headers: headers.toJSON(),
165955
165971
  agents: {
@@ -166155,14 +166171,14 @@ var require_axios = __commonJS({
166155
166171
  var cookies = platform.hasStandardBrowserEnv ? (
166156
166172
  // Standard browser envs support document.cookie
166157
166173
  {
166158
- write(name, value, expires, path80, domain, secure, sameSite) {
166174
+ write(name, value, expires, path81, domain, secure, sameSite) {
166159
166175
  if (typeof document === "undefined") return;
166160
166176
  const cookie = [`${name}=${encodeURIComponent(value)}`];
166161
166177
  if (utils$1.isNumber(expires)) {
166162
166178
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
166163
166179
  }
166164
- if (utils$1.isString(path80)) {
166165
- cookie.push(`path=${path80}`);
166180
+ if (utils$1.isString(path81)) {
166181
+ cookie.push(`path=${path81}`);
166166
166182
  }
166167
166183
  if (utils$1.isString(domain)) {
166168
166184
  cookie.push(`domain=${domain}`);
@@ -167683,8 +167699,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname10(proc
167683
167699
  return decodedFile;
167684
167700
  };
167685
167701
  }
167686
- function normalizeWindowsPath(path80) {
167687
- return path80.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
167702
+ function normalizeWindowsPath(path81) {
167703
+ return path81.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
167688
167704
  }
167689
167705
  async function addSourceContext(frames) {
167690
167706
  const filesToLines = {};
@@ -167729,9 +167745,9 @@ async function addSourceContext(frames) {
167729
167745
  LRU_FILE_CONTENTS_CACHE.reduce();
167730
167746
  return frames;
167731
167747
  }
167732
- function getContextLinesFromFile(path80, ranges, output) {
167748
+ function getContextLinesFromFile(path81, ranges, output) {
167733
167749
  return new Promise((resolve12) => {
167734
- const stream = createReadStream(path80);
167750
+ const stream = createReadStream(path81);
167735
167751
  const lineReaded = createInterface2({
167736
167752
  input: stream
167737
167753
  });
@@ -167749,7 +167765,7 @@ function getContextLinesFromFile(path80, ranges, output) {
167749
167765
  let rangeStart = range2[0];
167750
167766
  let rangeEnd = range2[1];
167751
167767
  function onStreamError() {
167752
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path80, 1);
167768
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path81, 1);
167753
167769
  lineReaded.close();
167754
167770
  lineReaded.removeAllListeners();
167755
167771
  destroyStreamAndResolve();
@@ -167826,8 +167842,8 @@ function clearLineContext(frame) {
167826
167842
  delete frame.context_line;
167827
167843
  delete frame.post_context;
167828
167844
  }
167829
- function shouldSkipContextLinesForFile(path80) {
167830
- return path80.startsWith("node:") || path80.endsWith(".min.js") || path80.endsWith(".min.cjs") || path80.endsWith(".min.mjs") || path80.startsWith("data:");
167845
+ function shouldSkipContextLinesForFile(path81) {
167846
+ return path81.startsWith("node:") || path81.endsWith(".min.js") || path81.endsWith(".min.cjs") || path81.endsWith(".min.mjs") || path81.startsWith("data:");
167831
167847
  }
167832
167848
  function shouldSkipContextLinesForFrame(frame) {
167833
167849
  if (frame.lineno !== void 0 && frame.lineno > MAX_CONTEXTLINES_LINENO) {
@@ -171176,7 +171192,7 @@ function readToolVersion() {
171176
171192
  if (cachedVersion)
171177
171193
  return cachedVersion;
171178
171194
  if (true) {
171179
- cachedVersion = "0.7.0-next.8";
171195
+ cachedVersion = "0.7.0-next.9";
171180
171196
  return cachedVersion;
171181
171197
  }
171182
171198
  try {
@@ -173582,13 +173598,13 @@ var init_pexprs_toFailure = __esm({
173582
173598
  return new Failure(this, "a Unicode [" + this.categoryOrProp + "] character", "description");
173583
173599
  };
173584
173600
  Alt.prototype.toFailure = function(grammar2) {
173585
- const fs71 = this.terms.map((t2) => t2.toFailure(grammar2));
173586
- const description = "(" + fs71.join(" or ") + ")";
173601
+ const fs72 = this.terms.map((t2) => t2.toFailure(grammar2));
173602
+ const description = "(" + fs72.join(" or ") + ")";
173587
173603
  return new Failure(this, description, "description");
173588
173604
  };
173589
173605
  Seq.prototype.toFailure = function(grammar2) {
173590
- const fs71 = this.factors.map((f2) => f2.toFailure(grammar2));
173591
- const description = "(" + fs71.join(" ") + ")";
173606
+ const fs72 = this.factors.map((f2) => f2.toFailure(grammar2));
173607
+ const description = "(" + fs72.join(" ") + ")";
173592
173608
  return new Failure(this, description, "description");
173593
173609
  };
173594
173610
  Iter.prototype.toFailure = function(grammar2) {
@@ -175425,9 +175441,9 @@ function buildGrammar2(match4, namespace, optOhmGrammarForTesting, options) {
175425
175441
  decl.withSuperGrammar(namespace[superGrammarName]);
175426
175442
  }
175427
175443
  },
175428
- Rule_define(n, fs71, d3, _2, b) {
175444
+ Rule_define(n, fs72, d3, _2, b) {
175429
175445
  currentRuleName = n.visit();
175430
- currentRuleFormals = fs71.children.map((c2) => c2.visit())[0] || [];
175446
+ currentRuleFormals = fs72.children.map((c2) => c2.visit())[0] || [];
175431
175447
  if (!decl.defaultStartRule && decl.ensureSuperGrammar() !== Grammar.ProtoBuiltInRules) {
175432
175448
  decl.withDefaultStartRule(currentRuleName);
175433
175449
  }
@@ -175436,9 +175452,9 @@ function buildGrammar2(match4, namespace, optOhmGrammarForTesting, options) {
175436
175452
  const source = this.source.trimmed();
175437
175453
  return decl.define(currentRuleName, currentRuleFormals, body, description, source);
175438
175454
  },
175439
- Rule_override(n, fs71, _2, b) {
175455
+ Rule_override(n, fs72, _2, b) {
175440
175456
  currentRuleName = n.visit();
175441
- currentRuleFormals = fs71.children.map((c2) => c2.visit())[0] || [];
175457
+ currentRuleFormals = fs72.children.map((c2) => c2.visit())[0] || [];
175442
175458
  const source = this.source.trimmed();
175443
175459
  decl.ensureSuperGrammarRuleForOverriding(currentRuleName, source);
175444
175460
  overriding = true;
@@ -175446,9 +175462,9 @@ function buildGrammar2(match4, namespace, optOhmGrammarForTesting, options) {
175446
175462
  overriding = false;
175447
175463
  return decl.override(currentRuleName, currentRuleFormals, body, null, source);
175448
175464
  },
175449
- Rule_extend(n, fs71, _2, b) {
175465
+ Rule_extend(n, fs72, _2, b) {
175450
175466
  currentRuleName = n.visit();
175451
- currentRuleFormals = fs71.children.map((c2) => c2.visit())[0] || [];
175467
+ currentRuleFormals = fs72.children.map((c2) => c2.visit())[0] || [];
175452
175468
  const body = b.visit();
175453
175469
  const source = this.source.trimmed();
175454
175470
  return decl.extend(currentRuleName, currentRuleFormals, body, null, source);
@@ -175475,8 +175491,8 @@ function buildGrammar2(match4, namespace, optOhmGrammarForTesting, options) {
175475
175491
  return builder.alt(...args).withSource(this.source);
175476
175492
  }
175477
175493
  },
175478
- Formals(opointy, fs71, cpointy) {
175479
- return fs71.visit();
175494
+ Formals(opointy, fs72, cpointy) {
175495
+ return fs72.visit();
175480
175496
  },
175481
175497
  Params(opointy, ps, cpointy) {
175482
175498
  return ps.visit();
@@ -175638,8 +175654,8 @@ function initPrototypeParser(grammar2) {
175638
175654
  formals: optFormals.children.map((c2) => c2.parse())[0] || []
175639
175655
  };
175640
175656
  },
175641
- Formals(oparen, fs71, cparen) {
175642
- return fs71.asIteration().children.map((c2) => c2.parse());
175657
+ Formals(oparen, fs72, cparen) {
175658
+ return fs72.asIteration().children.map((c2) => c2.parse());
175643
175659
  },
175644
175660
  name(first2, rest) {
175645
175661
  return this.sourceString;
@@ -178960,8 +178976,8 @@ function parseAndResolve(files) {
178960
178976
  const parsed = files.map((f2) => parseOne(f2.path, f2.source));
178961
178977
  return resolve10(parsed);
178962
178978
  }
178963
- function parseTcFile(path80, source) {
178964
- return parseOne(path80, source);
178979
+ function parseTcFile(path81, source) {
178980
+ return parseOne(path81, source);
178965
178981
  }
178966
178982
  var LineMap, OP_VALUES;
178967
178983
  var init_parser_ohm = __esm({
@@ -180350,13 +180366,13 @@ function extractStarletteRoutesFromFile(filePath, source, tree) {
180350
180366
  const identities = starletteIdentitiesForPath(rawPath);
180351
180367
  const line = node2.startPosition.row + 1;
180352
180368
  for (const method of methods) {
180353
- for (const path80 of identities) {
180369
+ for (const path81 of identities) {
180354
180370
  out.push({
180355
- identity: `${method} ${path80}`,
180371
+ identity: `${method} ${path81}`,
180356
180372
  contract: {
180357
180373
  protocol: "http",
180358
180374
  method,
180359
- path: path80,
180375
+ path: path81,
180360
180376
  responses: [],
180361
180377
  tags: []
180362
180378
  },
@@ -180533,14 +180549,14 @@ function parseRouteDecorator(dec, source, stringVars) {
180533
180549
  const args = call.childForFieldName("arguments");
180534
180550
  if (!args)
180535
180551
  return null;
180536
- let path80 = null;
180552
+ let path81 = null;
180537
180553
  let successStatus = "200";
180538
180554
  for (let i = 0; i < args.namedChildCount; i++) {
180539
180555
  const a = args.namedChild(i);
180540
180556
  if (!a)
180541
180557
  continue;
180542
- if (path80 === null && a.type === "string")
180543
- path80 = pyStr(a, source);
180558
+ if (path81 === null && a.type === "string")
180559
+ path81 = pyStr(a, source);
180544
180560
  else if (a.type === "keyword_argument") {
180545
180561
  const name = a.childForFieldName("name");
180546
180562
  const value = a.childForFieldName("value");
@@ -180549,17 +180565,17 @@ function parseRouteDecorator(dec, source, stringVars) {
180549
180565
  }
180550
180566
  }
180551
180567
  }
180552
- if (path80 === null) {
180568
+ if (path81 === null) {
180553
180569
  const firstArg = args.namedChild(0);
180554
180570
  if (firstArg?.type === "identifier") {
180555
180571
  const resolved = stringVars.get(source.slice(firstArg.startIndex, firstArg.endIndex));
180556
180572
  if (resolved !== void 0)
180557
- path80 = resolved;
180573
+ path81 = resolved;
180558
180574
  }
180559
180575
  }
180560
- if (path80 === null)
180576
+ if (path81 === null)
180561
180577
  return null;
180562
- return { method, path: path80, routerVar, successStatus };
180578
+ return { method, path: path81, routerVar, successStatus };
180563
180579
  }
180564
180580
  function extractResponses2(body, source, successStatus) {
180565
180581
  const byStatus = /* @__PURE__ */ new Map();
@@ -180692,9 +180708,9 @@ function looksLikeModel(p2, source) {
180692
180708
  const text4 = source.slice(type2.startIndex, type2.endIndex);
180693
180709
  return /^[A-Z]/.test(text4);
180694
180710
  }
180695
- function joinPath(prefix, path80) {
180711
+ function joinPath(prefix, path81) {
180696
180712
  const a = prefix.replace(/\/$/, "");
180697
- const b = path80.startsWith("/") ? path80 : `/${path80}`;
180713
+ const b = path81.startsWith("/") ? path81 : `/${path81}`;
180698
180714
  return a + b || "/";
180699
180715
  }
180700
180716
  function callName(call, source) {
@@ -197012,8 +197028,8 @@ async function runRulesReset({ ruleKey }) {
197012
197028
 
197013
197029
  // tools/cli/src/commands/contracts.ts
197014
197030
  init_dist4();
197015
- import fs68 from "node:fs";
197016
- import path73 from "node:path";
197031
+ import fs69 from "node:fs";
197032
+ import path74 from "node:path";
197017
197033
 
197018
197034
  // packages/spec-consolidator/dist/types.js
197019
197035
  init_zod();
@@ -197051,6 +197067,26 @@ var RelationSchema = external_exports.object({
197051
197067
  /** Optional human-readable rationale. */
197052
197068
  note: external_exports.string().optional()
197053
197069
  });
197070
+ var ConflictResolutionSchema = external_exports.object({
197071
+ /** Repo-relative path / DocRef of the first doc in the dispute. */
197072
+ docA: external_exports.string(),
197073
+ /** docA's conflicting section heading, or `null` for its preamble/lead. */
197074
+ anchorA: external_exports.string().nullable(),
197075
+ /** docA's verbatim disputed sentence, when the detector captured one. */
197076
+ quoteA: external_exports.string().optional(),
197077
+ /** Repo-relative path / DocRef of the second doc in the dispute. */
197078
+ docB: external_exports.string(),
197079
+ /** docB's conflicting section heading, or `null` for its preamble/lead. */
197080
+ anchorB: external_exports.string().nullable(),
197081
+ /** docB's verbatim disputed sentence, when the detector captured one. */
197082
+ quoteB: external_exports.string().optional(),
197083
+ /** Which side wins, or `dismissed` (not a real conflict). */
197084
+ verdict: external_exports.enum(["a", "b", "dismissed"]),
197085
+ /** ISO timestamp the resolution was recorded. */
197086
+ resolvedAt: external_exports.string(),
197087
+ /** Optional human-readable rationale. */
197088
+ note: external_exports.string().optional()
197089
+ });
197054
197090
  var ManualAreaSchema = external_exports.object({
197055
197091
  /** Repo-relative path / DocRef of the doc. */
197056
197092
  doc: external_exports.string(),
@@ -197075,7 +197111,13 @@ var DecisionsFileSchema = external_exports.object({
197075
197111
  /** User-authored doc→doc relations (replace/precedence/keep-both). */
197076
197112
  relations: external_exports.array(RelationSchema).default([]),
197077
197113
  /** User overrides of a doc's auto-assigned area tags. */
197078
- manualAreas: external_exports.array(ManualAreaSchema).default([])
197114
+ manualAreas: external_exports.array(ManualAreaSchema).default([]),
197115
+ /**
197116
+ * SECTION-scoped conflict verdicts (plan item 31) — pick-a-side / dismissal on
197117
+ * one flagged disagreement, keyed by dispute identity. Optional with a `[]`
197118
+ * default so a decisions.json written before item 31 still parses.
197119
+ */
197120
+ conflictResolutions: external_exports.array(ConflictResolutionSchema).default([])
197079
197121
  });
197080
197122
 
197081
197123
  // packages/spec-consolidator/dist/corpus-types.js
@@ -198015,6 +198057,7 @@ init_transport();
198015
198057
  init_dist5();
198016
198058
 
198017
198059
  // packages/spec-consolidator/dist/pointer-verifier.js
198060
+ init_dist5();
198018
198061
  var MIN_MEANINGFUL_SCORE = 1.5;
198019
198062
  var NEGLIGIBLE_RATIO = 0.25;
198020
198063
  var STOPWORDS2 = /* @__PURE__ */ new Set([
@@ -198164,16 +198207,13 @@ function splitDocSections(body, drop) {
198164
198207
  function headingKey(h) {
198165
198208
  return h.replace(/[`*_~]/g, "").trim().toLowerCase();
198166
198209
  }
198167
- function normalizeForQuote(text4) {
198168
- return text4.replace(/[`*_~]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
198169
- }
198170
198210
  function locateQuote(sections, quote) {
198171
- const needle = normalizeForQuote(quote);
198211
+ const needle = normalizeQuote(quote);
198172
198212
  if (!needle)
198173
198213
  return [];
198174
198214
  const hits = [];
198175
198215
  for (let i = 0; i < sections.length; i++) {
198176
- if (normalizeForQuote(sections[i].text).includes(needle))
198216
+ if (normalizeQuote(sections[i].text).includes(needle))
198177
198217
  hits.push(i);
198178
198218
  }
198179
198219
  return hits;
@@ -198250,7 +198290,6 @@ async function flagOverlaps(repoRoot5, areas, docs, opts = {}) {
198250
198290
  if (opts.enabled === false)
198251
198291
  return result;
198252
198292
  const byPath = new Map(docs.map((d3) => [d3.path, d3]));
198253
- const resolved = resolvedPairKeys(opts.relations ?? []);
198254
198293
  const maxPairs = opts.maxPairsPerArea ?? DEFAULT_MAX_PAIRS_PER_AREA;
198255
198294
  const vocab = opts.vocab;
198256
198295
  const pairs2 = [];
@@ -198265,8 +198304,6 @@ async function flagOverlaps(repoRoot5, areas, docs, opts = {}) {
198265
198304
  const b = byPath.get(y);
198266
198305
  if (!a || !b)
198267
198306
  return;
198268
- if (isResolved(resolved, area.id, x, y))
198269
- return;
198270
198307
  const key4 = x < y ? `${x}\0${y}` : `${y}\0${x}`;
198271
198308
  if (seen.has(key4))
198272
198309
  return;
@@ -198369,22 +198406,6 @@ async function examineOne(repoRoot5, areaId, a, b, runner) {
198369
198406
  await writeCache3(repoRoot5, cacheKey, verdict);
198370
198407
  return verdict;
198371
198408
  }
198372
- function resolvedPairKeys(relations) {
198373
- const set2 = /* @__PURE__ */ new Set();
198374
- for (const r of relations) {
198375
- if (r.scope)
198376
- set2.add(scopedKey2(r.scope, r.older, r.newer));
198377
- else
198378
- set2.add(globalKey(r.older, r.newer));
198379
- }
198380
- return set2;
198381
- }
198382
- var sortedPair = (x, y) => [x, y].sort().join(" ");
198383
- var globalKey = (x, y) => `* ${sortedPair(x, y)}`;
198384
- var scopedKey2 = (scope, x, y) => `${scope} ${sortedPair(x, y)}`;
198385
- function isResolved(set2, areaId, x, y) {
198386
- return set2.has(globalKey(x, y)) || set2.has(scopedKey2(areaId, x, y));
198387
- }
198388
198409
  var OVERLAP_DETECTOR_SYSTEM_PROMPT = `You compare TWO documentation files that both cover the same AREA of a software system and decide whether they may DISAGREE.
198389
198410
 
198390
198411
  ${OUTPUT_ONLY_GUARDRAIL}
@@ -198697,12 +198718,12 @@ function prefilterDocs(docs, manualIncludes = []) {
198697
198718
  if (reason)
198698
198719
  reasons.set(doc.path, reason);
198699
198720
  }
198700
- for (const { path: path80, reason } of dedupeNearDuplicates(docs.filter((d3) => !manualSet.has(d3.path) && !reasons.has(d3.path)))) {
198701
- reasons.set(path80, reason);
198721
+ for (const { path: path81, reason } of dedupeNearDuplicates(docs.filter((d3) => !manualSet.has(d3.path) && !reasons.has(d3.path)))) {
198722
+ reasons.set(path81, reason);
198702
198723
  }
198703
198724
  return {
198704
198725
  toClassify: docs.filter((d3) => !reasons.has(d3.path)),
198705
- skipped: [...reasons].map(([path80, reason]) => ({ path: path80, reason }))
198726
+ skipped: [...reasons].map(([path81, reason]) => ({ path: path81, reason }))
198706
198727
  };
198707
198728
  }
198708
198729
  async function planRelevanceWork(repoRoot5, docs, manualIncludes = []) {
@@ -199020,7 +199041,6 @@ async function curate(repoRoot5, opts = {}) {
199020
199041
  const overlapsByArea = await flagOverlaps(repoRoot5, grouped.areas, docs, {
199021
199042
  runner: opts.overlapRunner,
199022
199043
  enabled: opts.disableOverlapDetection !== true,
199023
- relations,
199024
199044
  vocab,
199025
199045
  transport: opts.transport,
199026
199046
  model: models.overlap,
@@ -199066,7 +199086,8 @@ var EMPTY_DECISIONS = {
199066
199086
  manualIncludes: [],
199067
199087
  manualExcludes: [],
199068
199088
  relations: [],
199069
- manualAreas: []
199089
+ manualAreas: [],
199090
+ conflictResolutions: []
199070
199091
  };
199071
199092
  function readCorpusDecisions(repoRoot5) {
199072
199093
  const file = path31.join(repoRoot5, ".truecourse", "specs", "decisions.json");
@@ -199088,7 +199109,8 @@ var EMPTY_DECISIONS2 = {
199088
199109
  manualIncludes: [],
199089
199110
  manualExcludes: [],
199090
199111
  relations: [],
199091
- manualAreas: []
199112
+ manualAreas: [],
199113
+ conflictResolutions: []
199092
199114
  };
199093
199115
  function decisionsPath(repoRoot5) {
199094
199116
  return path32.join(repoRoot5, ".truecourse", "specs", "decisions.json");
@@ -199268,8 +199290,8 @@ function canonicalIdentity(_kind, identity) {
199268
199290
  let id = identity.trim().replace(/\s+/g, " ");
199269
199291
  const op = HTTP_METHOD.exec(id);
199270
199292
  if (op) {
199271
- const path80 = op[2].replace(/\/+$/, "").replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, "{$1}");
199272
- id = `${op[1].toUpperCase()} ${path80}`;
199293
+ const path81 = op[2].replace(/\/+$/, "").replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, "{$1}");
199294
+ id = `${op[1].toUpperCase()} ${path81}`;
199273
199295
  }
199274
199296
  return id;
199275
199297
  }
@@ -203166,6 +203188,7 @@ function describeStageResolutions(repoDir = resolveRepoDir(process.cwd())) {
203166
203188
  }
203167
203189
 
203168
203190
  // packages/core/dist/commands/spec-in-process.js
203191
+ init_dist5();
203169
203192
  init_transport();
203170
203193
 
203171
203194
  // packages/core/dist/lib/llm-call-log.js
@@ -207432,8 +207455,8 @@ init_dist5();
207432
207455
 
207433
207456
  // packages/guard-generator/dist/section-plan.js
207434
207457
  init_zod();
207435
- import fs59 from "node:fs";
207436
- import path63 from "node:path";
207458
+ import fs60 from "node:fs";
207459
+ import path64 from "node:path";
207437
207460
  import { createHash as createHash15 } from "node:crypto";
207438
207461
  init_dist5();
207439
207462
 
@@ -207575,6 +207598,11 @@ function buildExtractUserPrompt(ctx) {
207575
207598
  ctx.viewText,
207576
207599
  '"""'
207577
207600
  ];
207601
+ if (ctx.suppressed && ctx.suppressed.length > 0) {
207602
+ lines.push("", "RESOLVED \u2014 STALE, DO NOT EXTRACT. A conflict resolution judged the following", "sentence(s) in this document stale (another document is authoritative here).", "Extract NO claim that asserts what any of them says \u2014 treat them as if absent:");
207603
+ for (const q2 of ctx.suppressed)
207604
+ lines.push(`- "${q2}"`);
207605
+ }
207578
207606
  if (ctx.correction) {
207579
207607
  lines.push("", "CORRECTION \u2014 your previous response was NOT valid. You returned:", ctx.correction.invalidOutput, 'Return exactly ONE JSON object with "claims" and "untestable" arrays matching', 'the schema above, and NOTHING else. Every "driver" is one of cli|api|web|tui;', 'every "sectionAnchor" is an anchor copied verbatim from the outline.');
207580
207608
  }
@@ -207743,17 +207771,127 @@ function buildRecipeUserPrompt(input) {
207743
207771
  return lines.join("\n");
207744
207772
  }
207745
207773
 
207746
- // packages/guard-generator/dist/section-plan.js
207774
+ // packages/guard-generator/dist/suppression.js
207775
+ init_zod();
207776
+ init_dist5();
207777
+ import fs59 from "node:fs";
207778
+ import path63 from "node:path";
207779
+ var OverlapSectionShape = external_exports.object({ doc: external_exports.string(), heading: external_exports.string().nullable().optional(), quote: external_exports.string().optional() }).passthrough();
207780
+ var OverlapShape = external_exports.object({
207781
+ docs: external_exports.tuple([external_exports.string(), external_exports.string()]),
207782
+ note: external_exports.string().optional(),
207783
+ sections: external_exports.array(OverlapSectionShape).optional(),
207784
+ areas: external_exports.array(external_exports.string()).optional()
207785
+ }).passthrough();
207786
+ var RelationShape = external_exports.object({ older: external_exports.string(), newer: external_exports.string(), scope: external_exports.string().optional() }).passthrough();
207747
207787
  var CorpusShape2 = external_exports.object({
207788
+ areas: external_exports.array(external_exports.object({ id: external_exports.string(), overlaps: external_exports.array(OverlapShape).optional() }).passthrough()).optional(),
207789
+ relations: external_exports.array(RelationShape).optional()
207790
+ }).passthrough();
207791
+ var ConflictResolutionShape = external_exports.object({
207792
+ docA: external_exports.string(),
207793
+ anchorA: external_exports.string().nullable().optional(),
207794
+ quoteA: external_exports.string().optional(),
207795
+ docB: external_exports.string(),
207796
+ anchorB: external_exports.string().nullable().optional(),
207797
+ quoteB: external_exports.string().optional(),
207798
+ verdict: external_exports.enum(["a", "b", "dismissed"]),
207799
+ resolvedAt: external_exports.string().optional(),
207800
+ note: external_exports.string().optional()
207801
+ }).passthrough();
207802
+ var DecisionsShape = external_exports.object({
207803
+ relations: external_exports.array(RelationShape).optional(),
207804
+ manualExcludes: external_exports.array(external_exports.string()).optional(),
207805
+ conflictResolutions: external_exports.array(ConflictResolutionShape).optional()
207806
+ }).passthrough();
207807
+ function readJsonTolerant(file, schema2) {
207808
+ if (!fs59.existsSync(file))
207809
+ return void 0;
207810
+ try {
207811
+ const parsed = schema2.safeParse(JSON.parse(fs59.readFileSync(file, "utf-8")));
207812
+ return parsed.success ? parsed.data : void 0;
207813
+ } catch {
207814
+ return void 0;
207815
+ }
207816
+ }
207817
+ function readSuppressedClaims(repoRoot5) {
207818
+ const specDir = path63.join(repoRoot5, ".truecourse", "specs");
207819
+ const corpus = readJsonTolerant(path63.join(specDir, "corpus.json"), CorpusShape2);
207820
+ if (!corpus)
207821
+ return [];
207822
+ const decisions = readJsonTolerant(path63.join(specDir, "decisions.json"), DecisionsShape);
207823
+ const corpusLike = {
207824
+ areas: (corpus.areas ?? []).map((a) => ({
207825
+ id: a.id,
207826
+ overlaps: (a.overlaps ?? []).map((o) => ({
207827
+ docs: o.docs,
207828
+ note: o.note,
207829
+ sections: (o.sections ?? []).map((s) => ({ doc: s.doc, heading: s.heading ?? null, quote: s.quote })),
207830
+ areas: o.areas
207831
+ }))
207832
+ })),
207833
+ relations: corpus.relations ?? []
207834
+ };
207835
+ const decisionsLike = {
207836
+ relations: decisions?.relations ?? [],
207837
+ manualExcludes: decisions?.manualExcludes ?? [],
207838
+ conflictResolutions: (decisions?.conflictResolutions ?? []).map((r) => ({
207839
+ docA: r.docA,
207840
+ anchorA: r.anchorA ?? null,
207841
+ quoteA: r.quoteA,
207842
+ docB: r.docB,
207843
+ anchorB: r.anchorB ?? null,
207844
+ quoteB: r.quoteB,
207845
+ verdict: r.verdict,
207846
+ resolvedAt: r.resolvedAt,
207847
+ note: r.note
207848
+ }))
207849
+ };
207850
+ return suppressedClaims(corpusLike, decisionsLike);
207851
+ }
207852
+ function readSuppressionIndex(repoRoot5) {
207853
+ const map2 = /* @__PURE__ */ new Map();
207854
+ for (const claim of readSuppressedClaims(repoRoot5)) {
207855
+ const list = map2.get(claim.doc);
207856
+ if (list)
207857
+ list.push(claim.quote);
207858
+ else
207859
+ map2.set(claim.doc, [claim.quote]);
207860
+ }
207861
+ return map2;
207862
+ }
207863
+ function suppressedQuotesIn(text4, docQuotes) {
207864
+ if (docQuotes.length === 0)
207865
+ return [];
207866
+ const haystack = normalizeQuote(text4);
207867
+ const seen = /* @__PURE__ */ new Set();
207868
+ const hits = [];
207869
+ for (const q2 of docQuotes) {
207870
+ const needle = normalizeQuote(q2);
207871
+ if (!needle || seen.has(needle) || !haystack.includes(needle))
207872
+ continue;
207873
+ seen.add(needle);
207874
+ hits.push(q2);
207875
+ }
207876
+ return hits.sort((a, b) => normalizeQuote(a) < normalizeQuote(b) ? -1 : 1);
207877
+ }
207878
+ function suppressionKey(quotes) {
207879
+ if (quotes.length === 0)
207880
+ return "";
207881
+ return [...quotes].map(normalizeQuote).sort().join("\0");
207882
+ }
207883
+
207884
+ // packages/guard-generator/dist/section-plan.js
207885
+ var CorpusShape3 = external_exports.object({
207748
207886
  docs: external_exports.array(external_exports.object({ ref: external_exports.string(), areaTags: external_exports.array(external_exports.string()).optional() }).passthrough()).optional()
207749
207887
  }).passthrough();
207750
207888
  function readCorpusAreaTags(repoRoot5) {
207751
- const file = path63.join(repoRoot5, ".truecourse", "specs", "corpus.json");
207889
+ const file = path64.join(repoRoot5, ".truecourse", "specs", "corpus.json");
207752
207890
  const map2 = /* @__PURE__ */ new Map();
207753
- if (!fs59.existsSync(file))
207891
+ if (!fs60.existsSync(file))
207754
207892
  return map2;
207755
207893
  try {
207756
- const parsed = CorpusShape2.safeParse(JSON.parse(fs59.readFileSync(file, "utf-8")));
207894
+ const parsed = CorpusShape3.safeParse(JSON.parse(fs60.readFileSync(file, "utf-8")));
207757
207895
  if (!parsed.success)
207758
207896
  return map2;
207759
207897
  for (const d3 of parsed.data.docs ?? [])
@@ -207762,29 +207900,35 @@ function readCorpusAreaTags(repoRoot5) {
207762
207900
  }
207763
207901
  return map2;
207764
207902
  }
207765
- function generationInputsHash(fingerprint2, recipeFingerprint) {
207766
- return "sha256:" + createHash15("sha256").update([
207903
+ function generationInputsHash(fingerprint2, recipeFingerprint, suppressionFingerprint = "") {
207904
+ const parts = [
207767
207905
  fingerprint2,
207768
207906
  recipeFingerprint,
207769
207907
  String(GUARD_FORMAT_VERSION),
207770
207908
  EXTRACT_PROMPT_FINGERPRINT2,
207771
207909
  GENERATE_PROMPT_FINGERPRINT
207772
- ].join("\0")).digest("hex");
207910
+ ];
207911
+ if (suppressionFingerprint)
207912
+ parts.push(suppressionFingerprint);
207913
+ return "sha256:" + createHash15("sha256").update(parts.join("\0")).digest("hex");
207773
207914
  }
207774
207915
  function hasGuardUniverse(repoRoot5) {
207775
- return fs59.existsSync(path63.join(repoRoot5, ".truecourse", "specs", "corpus.json"));
207916
+ return fs60.existsSync(path64.join(repoRoot5, ".truecourse", "specs", "corpus.json"));
207776
207917
  }
207777
207918
  function planGuardWork(repoRoot5, recipeFingerprint) {
207778
207919
  const recipeFp = recipeFingerprint ?? computeRecipeFingerprint(repoRoot5);
207779
- const recipeMissing = !fs59.existsSync(recipePath(repoRoot5));
207920
+ const recipeMissing = !fs60.existsSync(recipePath(repoRoot5));
207780
207921
  const hasUniverse = hasGuardUniverse(repoRoot5);
207781
207922
  const { indexes } = indexRepoDocs(repoRoot5, []);
207782
207923
  const areaTags = readCorpusAreaTags(repoRoot5);
207924
+ const suppressionIndex = readSuppressionIndex(repoRoot5);
207783
207925
  const sections = [];
207784
207926
  for (const [doc, index] of indexes) {
207785
- const texts = extractSectionTexts(doc, fs59.readFileSync(path63.resolve(repoRoot5, doc), "utf-8"));
207927
+ const texts = extractSectionTexts(doc, fs60.readFileSync(path64.resolve(repoRoot5, doc), "utf-8"));
207928
+ const docQuotes = suppressionIndex.get(doc) ?? [];
207786
207929
  for (const s of index.sections) {
207787
207930
  const t2 = texts.get(s.anchor);
207931
+ const fullText = t2?.fullText ?? "";
207788
207932
  sections.push({
207789
207933
  doc,
207790
207934
  anchor: s.anchor,
@@ -207792,8 +207936,9 @@ function planGuardWork(repoRoot5, recipeFingerprint) {
207792
207936
  headingText: s.headingText,
207793
207937
  level: s.level,
207794
207938
  ownText: t2?.ownText ?? "",
207795
- fullText: t2?.fullText ?? "",
207796
- areaTags: areaTags.get(doc) ?? []
207939
+ fullText,
207940
+ areaTags: areaTags.get(doc) ?? [],
207941
+ suppressionFingerprint: suppressionKey(suppressedQuotesIn(fullText, docQuotes))
207797
207942
  });
207798
207943
  }
207799
207944
  }
@@ -207806,12 +207951,12 @@ function planGuardWork(repoRoot5, recipeFingerprint) {
207806
207951
  const key4 = `${s.doc}\0${s.anchor}`;
207807
207952
  seen.add(key4);
207808
207953
  const prior = byKey.get(key4);
207809
- const inputsHash = generationInputsHash(s.fingerprint, recipeFp);
207954
+ const inputsHash = generationInputsHash(s.fingerprint, recipeFp, s.suppressionFingerprint);
207810
207955
  if (!prior || prior.generationInputsHash !== inputsHash)
207811
207956
  work.push(s);
207812
207957
  }
207813
207958
  const orphaned = (manifest?.sections ?? []).filter((e) => !seen.has(`${e.doc}\0${e.anchor}`));
207814
- return { hasUniverse, sections, work, orphaned, recipeFingerprint: recipeFp, recipeMissing };
207959
+ return { hasUniverse, sections, work, orphaned, recipeFingerprint: recipeFp, recipeMissing, suppressionIndex };
207815
207960
  }
207816
207961
  function collectWorkDocs(repoRoot5, plan) {
207817
207962
  const workDocs = new Set(plan.work.map((s) => s.doc));
@@ -207827,8 +207972,9 @@ function collectWorkDocs(repoRoot5, plan) {
207827
207972
  }
207828
207973
  return [...byDoc].map(([doc, sections]) => ({
207829
207974
  doc,
207830
- content: fs59.readFileSync(path63.resolve(repoRoot5, doc), "utf-8"),
207831
- sections
207975
+ content: fs60.readFileSync(path64.resolve(repoRoot5, doc), "utf-8"),
207976
+ sections,
207977
+ suppressedQuotes: plan.suppressionIndex.get(doc) ?? []
207832
207978
  }));
207833
207979
  }
207834
207980
 
@@ -207911,8 +208057,13 @@ function flattenZodError(error) {
207911
208057
  // packages/guard-generator/dist/extract.js
207912
208058
  var EXTRACT_CACHE_NAME2 = "guard/extract";
207913
208059
  var EXTRACT_VIEW_BUDGET = 16e3;
207914
- function viewCacheKey(viewText) {
207915
- return createHash16("sha256").update(`${EXTRACT_PROMPT_FINGERPRINT2}::${sha(viewText)}`).digest("hex");
208060
+ function viewCacheKey(viewText, suppressed = []) {
208061
+ const base2 = `${EXTRACT_PROMPT_FINGERPRINT2}::${sha(viewText)}`;
208062
+ const suppression = suppressionKey(suppressed);
208063
+ return createHash16("sha256").update(suppression ? `${base2}::${suppression}` : base2).digest("hex");
208064
+ }
208065
+ function suppressedForView(doc, viewText) {
208066
+ return suppressedQuotesIn(viewText, doc.suppressedQuotes);
207916
208067
  }
207917
208068
  function sha(text4) {
207918
208069
  return createHash16("sha256").update(text4).digest("hex");
@@ -207958,7 +208109,7 @@ function countExtractViews(doc) {
207958
208109
  async function countUncachedExtractViews(repoRoot5, doc) {
207959
208110
  let n = 0;
207960
208111
  for (const v of planViews(doc)) {
207961
- if (!await getCacheEntry(repoRoot5, EXTRACT_CACHE_NAME2, viewCacheKey(v.text)))
208112
+ if (!await getCacheEntry(repoRoot5, EXTRACT_CACHE_NAME2, viewCacheKey(v.text, suppressedForView(doc, v.text))))
207962
208113
  n++;
207963
208114
  }
207964
208115
  return n;
@@ -207967,7 +208118,7 @@ async function extractDocClaims(repoRoot5, doc, runner, limit, onView) {
207967
208118
  const outline = outlineOf(doc.sections);
207968
208119
  const views = planViews(doc);
207969
208120
  const run = limit ?? ((fn) => fn());
207970
- const attempts = await Promise.all(views.map((v) => run(() => extractView(repoRoot5, doc.doc, outline, v, runner)).then((got) => {
208121
+ const attempts = await Promise.all(views.map((v) => run(() => extractView(repoRoot5, doc.doc, outline, v, suppressedForView(doc, v.text), runner)).then((got) => {
207971
208122
  onView?.();
207972
208123
  return got;
207973
208124
  })));
@@ -207988,15 +208139,21 @@ async function extractDocClaims(repoRoot5, doc, runner, limit, onView) {
207988
208139
  return { ok: false, reason: firstError || "all extraction views failed" };
207989
208140
  return { ok: true, data: snap(merged, doc.sections), complete: failedViews === 0, failedViews };
207990
208141
  }
207991
- async function extractView(repoRoot5, docPath, outline, view, runner) {
207992
- const cacheKey = viewCacheKey(view.text);
208142
+ async function extractView(repoRoot5, docPath, outline, view, suppressed, runner) {
208143
+ const cacheKey = viewCacheKey(view.text, suppressed);
207993
208144
  const cached = await getCacheEntry(repoRoot5, EXTRACT_CACHE_NAME2, cacheKey);
207994
208145
  if (cached) {
207995
208146
  const parsed = DocExtractionSchema.safeParse(cached);
207996
208147
  if (parsed.success)
207997
208148
  return { data: parsed.data };
207998
208149
  }
207999
- const ctx = { doc: docPath, outline, viewText: view.text, view: view.view };
208150
+ const ctx = {
208151
+ doc: docPath,
208152
+ outline,
208153
+ viewText: view.text,
208154
+ view: view.view,
208155
+ ...suppressed.length > 0 ? { suppressed } : {}
208156
+ };
208000
208157
  const attempt = await callExtractWithReask(ctx, runner);
208001
208158
  if ("data" in attempt)
208002
208159
  await setCacheEntry(repoRoot5, EXTRACT_CACHE_NAME2, cacheKey, attempt.data);
@@ -208075,7 +208232,7 @@ function snap(raw, sections) {
208075
208232
 
208076
208233
  // packages/guard-generator/dist/ground.js
208077
208234
  init_zod();
208078
- import path64 from "node:path";
208235
+ import path65 from "node:path";
208079
208236
  import { createHash as createHash17 } from "node:crypto";
208080
208237
  var GROUND_CACHE_NAME = "guard/ground";
208081
208238
  var PROBE_TIMEOUT_MS = 2e4;
@@ -208131,7 +208288,7 @@ function toProbeArgv(fragment, programNames) {
208131
208288
  const tokens = fragment.trim().split(/\s+/).filter(Boolean);
208132
208289
  if (tokens.length === 0)
208133
208290
  return null;
208134
- if (programNames.has(tokens[0]) || programNames.has(path64.basename(tokens[0])))
208291
+ if (programNames.has(tokens[0]) || programNames.has(path65.basename(tokens[0])))
208135
208292
  tokens.shift();
208136
208293
  if (tokens.length === 0)
208137
208294
  return [];
@@ -208152,7 +208309,7 @@ function programNamesOf(entry) {
208152
208309
  return names;
208153
208310
  }
208154
208311
  function addName(set2, arg) {
208155
- const base2 = path64.basename(arg);
208312
+ const base2 = path65.basename(arg);
208156
208313
  if (base2)
208157
208314
  set2.add(base2);
208158
208315
  const stem = base2.replace(/\.[^.]+$/, "");
@@ -208214,9 +208371,9 @@ function truncate3(text4) {
208214
208371
  }
208215
208372
 
208216
208373
  // packages/guard-generator/dist/recipe-discovery.js
208217
- import fs60 from "node:fs";
208374
+ import fs61 from "node:fs";
208218
208375
  import os13 from "node:os";
208219
- import path65 from "node:path";
208376
+ import path66 from "node:path";
208220
208377
  import { createHash as createHash18 } from "node:crypto";
208221
208378
  var RECIPE_CACHE_NAME = "guard/recipe";
208222
208379
  var DISCOVERY_INPUTS = ["package.json", "pnpm-lock.yaml", "package-lock.json", "yarn.lock", "turbo.json"];
@@ -208270,13 +208427,13 @@ async function discoverRecipe(repoRoot5, runner) {
208270
208427
  ...proposal.env ? { env: proposal.env } : {}
208271
208428
  };
208272
208429
  const target = recipePath(repoRoot5);
208273
- fs60.mkdirSync(path65.dirname(target), { recursive: true });
208274
- fs60.writeFileSync(target, JSON.stringify(recipe, null, 2) + "\n");
208430
+ fs61.mkdirSync(path66.dirname(target), { recursive: true });
208431
+ fs61.writeFileSync(target, JSON.stringify(recipe, null, 2) + "\n");
208275
208432
  return {
208276
208433
  status: "discovered",
208277
208434
  recipe,
208278
208435
  fingerprint: computeRecipeFingerprint(repoRoot5),
208279
- wrotePath: path65.relative(repoRoot5, target)
208436
+ wrotePath: path66.relative(repoRoot5, target)
208280
208437
  };
208281
208438
  }
208282
208439
  async function proposeRecipeWithReask(input, runner) {
@@ -208301,14 +208458,14 @@ async function proposeRecipeWithReask(input, runner) {
208301
208458
  return { error: `recipe proposal invalid after re-ask: ${flattenZodError(reParsed.error)}` };
208302
208459
  }
208303
208460
  function readDiscoveryInputs(repoRoot5) {
208304
- const pkgPath = path65.join(repoRoot5, "package.json");
208305
- const packageJson = fs60.existsSync(pkgPath) ? fs60.readFileSync(pkgPath, "utf-8") : "(no package.json)";
208306
- const presentInputs = DISCOVERY_INPUTS.filter((f2) => fs60.existsSync(path65.join(repoRoot5, f2)));
208461
+ const pkgPath = path66.join(repoRoot5, "package.json");
208462
+ const packageJson = fs61.existsSync(pkgPath) ? fs61.readFileSync(pkgPath, "utf-8") : "(no package.json)";
208463
+ const presentInputs = DISCOVERY_INPUTS.filter((f2) => fs61.existsSync(path66.join(repoRoot5, f2)));
208307
208464
  return { packageJson, presentInputs };
208308
208465
  }
208309
208466
  async function probeEntry(repoRoot5, entry) {
208310
208467
  const resolved = resolveEntry(repoRoot5, entry);
208311
- const cwd = fs60.mkdtempSync(path65.join(os13.tmpdir(), "tc-guard-probe-"));
208468
+ const cwd = fs61.mkdtempSync(path66.join(os13.tmpdir(), "tc-guard-probe-"));
208312
208469
  try {
208313
208470
  for (const args of [["--help"], []]) {
208314
208471
  const capture = await executeStep({
@@ -208325,7 +208482,7 @@ async function probeEntry(repoRoot5, entry) {
208325
208482
  reason: `entrypoint ${JSON.stringify(entry)} did not answer to \`--help\` or a bare invocation`
208326
208483
  };
208327
208484
  } finally {
208328
- fs60.rmSync(cwd, { recursive: true, force: true });
208485
+ fs61.rmSync(cwd, { recursive: true, force: true });
208329
208486
  }
208330
208487
  }
208331
208488
 
@@ -208372,8 +208529,8 @@ async function birthValidate(repoRoot5, candidates, opts = {}) {
208372
208529
  }
208373
208530
 
208374
208531
  // packages/guard-generator/dist/serialize.js
208375
- import fs61 from "node:fs";
208376
- import path66 from "node:path";
208532
+ import fs62 from "node:fs";
208533
+ import path67 from "node:path";
208377
208534
  init_dist5();
208378
208535
  function anchorLeaf(anchor) {
208379
208536
  const segs = anchor.split("/").filter(Boolean);
@@ -208392,7 +208549,7 @@ function assignScenarioId(anchor, used) {
208392
208549
  function areaOrDocSlug(section) {
208393
208550
  if (section.areaTags.length > 0)
208394
208551
  return slugifyHeading(section.areaTags[0]) || "area";
208395
- const base2 = path66.basename(section.doc).replace(/\.[^.]+$/, "");
208552
+ const base2 = path67.basename(section.doc).replace(/\.[^.]+$/, "");
208396
208553
  return slugifyHeading(base2) || "doc";
208397
208554
  }
208398
208555
  function buildScenario(section, raw, id) {
@@ -208415,15 +208572,15 @@ function scenarioFileIndex(repoRoot5) {
208415
208572
  const root2 = scenariosDir(repoRoot5);
208416
208573
  const map2 = /* @__PURE__ */ new Map();
208417
208574
  const walk20 = (dir) => {
208418
- if (!fs61.existsSync(dir))
208575
+ if (!fs62.existsSync(dir))
208419
208576
  return;
208420
- for (const entry of fs61.readdirSync(dir, { withFileTypes: true })) {
208421
- const full = path66.join(dir, entry.name);
208577
+ for (const entry of fs62.readdirSync(dir, { withFileTypes: true })) {
208578
+ const full = path67.join(dir, entry.name);
208422
208579
  if (entry.isDirectory())
208423
208580
  walk20(full);
208424
208581
  else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) {
208425
208582
  try {
208426
- const doc = jsYaml.load(fs61.readFileSync(full, "utf-8"));
208583
+ const doc = jsYaml.load(fs62.readFileSync(full, "utf-8"));
208427
208584
  if (doc && typeof doc.id === "string")
208428
208585
  map2.set(doc.id, full);
208429
208586
  } catch {
@@ -208441,18 +208598,18 @@ function serializeScenarioYaml(scenario) {
208441
208598
  return jsYaml.dump(scenario, { lineWidth: -1, noRefs: true });
208442
208599
  }
208443
208600
  function writeScenarioFile(repoRoot5, slug2, scenario) {
208444
- const dir = path66.join(scenariosDir(repoRoot5), slug2);
208445
- fs61.mkdirSync(dir, { recursive: true });
208446
- const file = path66.join(dir, `${scenario.id}.yaml`);
208447
- fs61.writeFileSync(file, serializeScenarioYaml(scenario));
208448
- return path66.relative(repoRoot5, file);
208601
+ const dir = path67.join(scenariosDir(repoRoot5), slug2);
208602
+ fs62.mkdirSync(dir, { recursive: true });
208603
+ const file = path67.join(dir, `${scenario.id}.yaml`);
208604
+ fs62.writeFileSync(file, serializeScenarioYaml(scenario));
208605
+ return path67.relative(repoRoot5, file);
208449
208606
  }
208450
208607
  function deleteScenarioFiles(repoRoot5, ids) {
208451
208608
  const index = scenarioFileIndex(repoRoot5);
208452
208609
  for (const id of ids) {
208453
208610
  const file = index.get(id);
208454
- if (file && fs61.existsSync(file))
208455
- fs61.rmSync(file);
208611
+ if (file && fs62.existsSync(file))
208612
+ fs62.rmSync(file);
208456
208613
  }
208457
208614
  }
208458
208615
 
@@ -208672,7 +208829,7 @@ async function generateGuards(options) {
208672
208829
  anchor: section.anchor,
208673
208830
  fingerprint: section.fingerprint,
208674
208831
  scenarioIds: scenarioIds.slice().sort(),
208675
- generationInputsHash: generationInputsHash(section.fingerprint, recipeFingerprint),
208832
+ generationInputsHash: generationInputsHash(section.fingerprint, recipeFingerprint, section.suppressionFingerprint),
208676
208833
  ...classification ? { classification } : {}
208677
208834
  });
208678
208835
  settledKeys.add(k);
@@ -209157,8 +209314,8 @@ init_context_router();
209157
209314
 
209158
209315
  // packages/core/dist/services/llm/model-prices.js
209159
209316
  init_paths();
209160
- import fs62 from "node:fs";
209161
- import path67 from "node:path";
209317
+ import fs63 from "node:fs";
209318
+ import path68 from "node:path";
209162
209319
  var OPENROUTER_URL = "https://openrouter.ai/api/v1/models";
209163
209320
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
209164
209321
  var FETCH_TIMEOUT_MS = 8e3;
@@ -209174,11 +209331,11 @@ function tierOf(id) {
209174
209331
  return s.includes("opus") ? "opus" : s.includes("sonnet") ? "sonnet" : s.includes("haiku") ? "haiku" : null;
209175
209332
  }
209176
209333
  function cacheFilePath() {
209177
- return path67.join(getGlobalDir(), "cache", CACHE_FILE);
209334
+ return path68.join(getGlobalDir(), "cache", CACHE_FILE);
209178
209335
  }
209179
209336
  function readCache7() {
209180
209337
  try {
209181
- const t2 = JSON.parse(fs62.readFileSync(cacheFilePath(), "utf-8"));
209338
+ const t2 = JSON.parse(fs63.readFileSync(cacheFilePath(), "utf-8"));
209182
209339
  if (t2 && t2.tiers && t2.byId && typeof t2.fetchedAt === "number")
209183
209340
  return t2;
209184
209341
  } catch {
@@ -209187,8 +209344,8 @@ function readCache7() {
209187
209344
  }
209188
209345
  function writeCache7(t2) {
209189
209346
  try {
209190
- fs62.mkdirSync(path67.dirname(cacheFilePath()), { recursive: true });
209191
- fs62.writeFileSync(cacheFilePath(), JSON.stringify(t2));
209347
+ fs63.mkdirSync(path68.dirname(cacheFilePath()), { recursive: true });
209348
+ fs63.writeFileSync(cacheFilePath(), JSON.stringify(t2));
209192
209349
  } catch {
209193
209350
  }
209194
209351
  }
@@ -209567,16 +209724,16 @@ function changedSubject(total, changed, noun) {
209567
209724
 
209568
209725
  // packages/core/dist/commands/spec-in-process.js
209569
209726
  init_dist8();
209570
- import fs67 from "node:fs";
209571
- import path72 from "node:path";
209727
+ import fs68 from "node:fs";
209728
+ import path73 from "node:path";
209572
209729
  init_git();
209573
209730
  import { createHash as createHash20, randomUUID as randomUUID27 } from "node:crypto";
209574
209731
 
209575
209732
  // packages/core/dist/lib/verify-store.js
209576
209733
  init_atomic_write();
209577
209734
  init_analysis_store();
209578
- import fs63 from "node:fs";
209579
- import path68 from "node:path";
209735
+ import fs64 from "node:fs";
209736
+ import path69 from "node:path";
209580
209737
 
209581
209738
  // packages/core/dist/types/verify-snapshot.js
209582
209739
  function driftKey(d3) {
@@ -209624,23 +209781,23 @@ var LATEST_FILE3 = "LATEST.json";
209624
209781
  var HISTORY_FILE3 = "history.json";
209625
209782
  var DIFF_FILE2 = "diff.json";
209626
209783
  function verifierDir(repoPath) {
209627
- return path68.join(repoPath, TRUECOURSE_DIR4, VERIFIER_DIR);
209784
+ return path69.join(repoPath, TRUECOURSE_DIR4, VERIFIER_DIR);
209628
209785
  }
209629
209786
  function runsDir(repoPath) {
209630
- return path68.join(verifierDir(repoPath), RUNS_DIR2);
209787
+ return path69.join(verifierDir(repoPath), RUNS_DIR2);
209631
209788
  }
209632
209789
  function verifyRunPath(repoPath, filename) {
209633
- return path68.join(runsDir(repoPath), filename);
209790
+ return path69.join(runsDir(repoPath), filename);
209634
209791
  }
209635
209792
  function verifyLatestPath(repoPath) {
209636
- return path68.join(verifierDir(repoPath), LATEST_FILE3);
209793
+ return path69.join(verifierDir(repoPath), LATEST_FILE3);
209637
209794
  }
209638
209795
  function verifyHistoryPath(repoPath) {
209639
- return path68.join(verifierDir(repoPath), HISTORY_FILE3);
209796
+ return path69.join(verifierDir(repoPath), HISTORY_FILE3);
209640
209797
  }
209641
209798
  function verifyDiffPath(repoPath, scope) {
209642
209799
  const file = scope ? `diff-${sanitizeScope(scope)}.json` : DIFF_FILE2;
209643
- return path68.join(verifierDir(repoPath), file);
209800
+ return path69.join(verifierDir(repoPath), file);
209644
209801
  }
209645
209802
  function sanitizeScope(scope) {
209646
209803
  return scope.replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -209674,7 +209831,7 @@ var FileVerifyStore = class {
209674
209831
  const file = verifyLatestPath(repoPath);
209675
209832
  let mtime;
209676
209833
  try {
209677
- mtime = fs63.statSync(file).mtimeMs;
209834
+ mtime = fs64.statSync(file).mtimeMs;
209678
209835
  } catch (err) {
209679
209836
  if (err.code === "ENOENT") {
209680
209837
  latestCache2.delete(repoPath);
@@ -209685,7 +209842,7 @@ var FileVerifyStore = class {
209685
209842
  const cached = latestCache2.get(repoPath);
209686
209843
  if (cached && cached.mtime === mtime)
209687
209844
  return cached.data;
209688
- const data = JSON.parse(fs63.readFileSync(file, "utf-8"));
209845
+ const data = JSON.parse(fs64.readFileSync(file, "utf-8"));
209689
209846
  latestCache2.set(repoPath, { mtime, data });
209690
209847
  return data;
209691
209848
  }
@@ -209695,7 +209852,7 @@ var FileVerifyStore = class {
209695
209852
  }
209696
209853
  async deleteVerifyLatest(repoPath) {
209697
209854
  try {
209698
- fs63.unlinkSync(verifyLatestPath(repoPath));
209855
+ fs64.unlinkSync(verifyLatestPath(repoPath));
209699
209856
  } catch (err) {
209700
209857
  if (err.code !== "ENOENT")
209701
209858
  throw err;
@@ -209709,21 +209866,21 @@ var FileVerifyStore = class {
209709
209866
  }
209710
209867
  async readVerifyRun(repoPath, filename) {
209711
209868
  const file = verifyRunPath(repoPath, filename);
209712
- if (!fs63.existsSync(file))
209869
+ if (!fs64.existsSync(file))
209713
209870
  return null;
209714
- return JSON.parse(fs63.readFileSync(file, "utf-8"));
209871
+ return JSON.parse(fs64.readFileSync(file, "utf-8"));
209715
209872
  }
209716
209873
  async listVerifyRuns(repoPath) {
209717
209874
  const dir = runsDir(repoPath);
209718
- if (!fs63.existsSync(dir))
209875
+ if (!fs64.existsSync(dir))
209719
209876
  return [];
209720
- return fs63.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
209877
+ return fs64.readdirSync(dir).filter((n) => n.endsWith(".json")).sort();
209721
209878
  }
209722
209879
  async readVerifyHistory(repoPath) {
209723
209880
  const file = verifyHistoryPath(repoPath);
209724
- if (!fs63.existsSync(file))
209881
+ if (!fs64.existsSync(file))
209725
209882
  return { runs: [] };
209726
- return JSON.parse(fs63.readFileSync(file, "utf-8"));
209883
+ return JSON.parse(fs64.readFileSync(file, "utf-8"));
209727
209884
  }
209728
209885
  async appendVerifyHistory(repoPath, entry) {
209729
209886
  const history = await this.readVerifyHistory(repoPath);
@@ -209736,7 +209893,7 @@ var FileVerifyStore = class {
209736
209893
  if (!entry)
209737
209894
  return false;
209738
209895
  try {
209739
- fs63.unlinkSync(verifyRunPath(repoPath, entry.filename));
209896
+ fs64.unlinkSync(verifyRunPath(repoPath, entry.filename));
209740
209897
  } catch (err) {
209741
209898
  if (err.code !== "ENOENT")
209742
209899
  throw err;
@@ -209758,16 +209915,16 @@ var FileVerifyStore = class {
209758
209915
  }
209759
209916
  async readVerifyDiff(repoPath, scope) {
209760
209917
  const file = verifyDiffPath(repoPath, scope);
209761
- if (!fs63.existsSync(file))
209918
+ if (!fs64.existsSync(file))
209762
209919
  return null;
209763
- return JSON.parse(fs63.readFileSync(file, "utf-8"));
209920
+ return JSON.parse(fs64.readFileSync(file, "utf-8"));
209764
209921
  }
209765
209922
  async writeVerifyDiff(repoPath, diff, scope) {
209766
209923
  atomicWriteJson(verifyDiffPath(repoPath, scope), diff);
209767
209924
  }
209768
209925
  async deleteVerifyDiff(repoPath, scope) {
209769
209926
  try {
209770
- fs63.unlinkSync(verifyDiffPath(repoPath, scope));
209927
+ fs64.unlinkSync(verifyDiffPath(repoPath, scope));
209771
209928
  } catch (err) {
209772
209929
  if (err.code !== "ENOENT")
209773
209930
  throw err;
@@ -209801,8 +209958,8 @@ async function repoRef(repoRoot5, commitOverride) {
209801
209958
  }
209802
209959
 
209803
209960
  // packages/core/dist/lib/contract-store.js
209804
- import fs64 from "node:fs";
209805
- import path69 from "node:path";
209961
+ import fs65 from "node:fs";
209962
+ import path70 from "node:path";
209806
209963
  var KIND_REL = {
209807
209964
  contracts: [".truecourse", "contracts"],
209808
209965
  // The inferred tree lives at contracts/_inferred (matches `writeInferred`).
@@ -209812,13 +209969,13 @@ function countTcFiles(dir) {
209812
209969
  let n = 0;
209813
209970
  let entries;
209814
209971
  try {
209815
- entries = fs64.readdirSync(dir, { withFileTypes: true });
209972
+ entries = fs65.readdirSync(dir, { withFileTypes: true });
209816
209973
  } catch {
209817
209974
  return 0;
209818
209975
  }
209819
209976
  for (const e of entries) {
209820
209977
  if (e.isDirectory())
209821
- n += countTcFiles(path69.join(dir, e.name));
209978
+ n += countTcFiles(path70.join(dir, e.name));
209822
209979
  else if (e.isFile() && e.name.endsWith(".tc"))
209823
209980
  n += 1;
209824
209981
  }
@@ -209829,7 +209986,7 @@ function walkTcRel(dir, excludeInferred) {
209829
209986
  const walk20 = (rel) => {
209830
209987
  let entries;
209831
209988
  try {
209832
- entries = fs64.readdirSync(path69.join(dir, rel), { withFileTypes: true });
209989
+ entries = fs65.readdirSync(path70.join(dir, rel), { withFileTypes: true });
209833
209990
  } catch {
209834
209991
  return;
209835
209992
  }
@@ -209853,50 +210010,50 @@ function safeResolve(root2, rel) {
209853
210010
  return null;
209854
210011
  if (norm.split("/").some((s) => s === ".." || s === "." || s === ""))
209855
210012
  return null;
209856
- const base2 = path69.resolve(root2);
209857
- const dest = path69.resolve(base2, norm);
209858
- if (dest !== base2 && !dest.startsWith(base2 + path69.sep))
210013
+ const base2 = path70.resolve(root2);
210014
+ const dest = path70.resolve(base2, norm);
210015
+ if (dest !== base2 && !dest.startsWith(base2 + path70.sep))
209859
210016
  return null;
209860
210017
  return dest;
209861
210018
  }
209862
210019
  var FileContractStore = class {
209863
210020
  materializesInPlace = true;
209864
210021
  async saveContracts(ref, kind, _sourceDir) {
209865
- const dir = path69.join(ref.repoKey, ...KIND_REL[kind]);
210022
+ const dir = path70.join(ref.repoKey, ...KIND_REL[kind]);
209866
210023
  return { manifest: {}, fileCount: countTcFiles(dir), objectsWritten: 0, manifestHash: "" };
209867
210024
  }
209868
210025
  async loadContracts(ref, kind) {
209869
- const dir = path69.join(ref.repoKey, ...KIND_REL[kind]);
209870
- if (!fs64.existsSync(dir))
210026
+ const dir = path70.join(ref.repoKey, ...KIND_REL[kind]);
210027
+ if (!fs65.existsSync(dir))
209871
210028
  return null;
209872
210029
  return { dir, cleanup: async () => {
209873
210030
  } };
209874
210031
  }
209875
210032
  async hasContracts(ref, kind) {
209876
- return fs64.existsSync(path69.join(ref.repoKey, ...KIND_REL[kind]));
210033
+ return fs65.existsSync(path70.join(ref.repoKey, ...KIND_REL[kind]));
209877
210034
  }
209878
210035
  // The file impl reads the live repo tree, which is whatever is checked out —
209879
210036
  // there is no per-commit history, so `commitSha` is ignored (OSS is latest).
209880
210037
  async listContractFiles(repoKey, kind, _commitSha) {
209881
- return walkTcRel(path69.join(repoKey, ...KIND_REL[kind]), kind === "contracts");
210038
+ return walkTcRel(path70.join(repoKey, ...KIND_REL[kind]), kind === "contracts");
209882
210039
  }
209883
210040
  async readContractFile(repoKey, kind, relPath, _commitSha) {
209884
- const dest = safeResolve(path69.join(repoKey, ...KIND_REL[kind]), relPath);
209885
- if (!dest || !fs64.existsSync(dest) || !fs64.statSync(dest).isFile())
210041
+ const dest = safeResolve(path70.join(repoKey, ...KIND_REL[kind]), relPath);
210042
+ if (!dest || !fs65.existsSync(dest) || !fs65.statSync(dest).isFile())
209886
210043
  return null;
209887
- return fs64.readFileSync(dest, "utf-8");
210044
+ return fs65.readFileSync(dest, "utf-8");
209888
210045
  }
209889
210046
  async putContractFile(ref, kind, relPath, content) {
209890
- const dest = safeResolve(path69.join(ref.repoKey, ...KIND_REL[kind]), relPath);
210047
+ const dest = safeResolve(path70.join(ref.repoKey, ...KIND_REL[kind]), relPath);
209891
210048
  if (!dest)
209892
210049
  throw new Error(`[contract-store] unsafe contract path: ${relPath}`);
209893
- fs64.mkdirSync(path69.dirname(dest), { recursive: true });
209894
- fs64.writeFileSync(dest, content);
210050
+ fs65.mkdirSync(path70.dirname(dest), { recursive: true });
210051
+ fs65.writeFileSync(dest, content);
209895
210052
  }
209896
210053
  async deleteContractFile(ref, kind, relPath) {
209897
- const dest = safeResolve(path69.join(ref.repoKey, ...KIND_REL[kind]), relPath);
210054
+ const dest = safeResolve(path70.join(ref.repoKey, ...KIND_REL[kind]), relPath);
209898
210055
  if (dest)
209899
- fs64.rmSync(dest, { force: true });
210056
+ fs65.rmSync(dest, { force: true });
209900
210057
  }
209901
210058
  // OSS/local has no workspace concept (mirrors the spec store). Writing throws
209902
210059
  // (fail loud — a caller that reached here is mis-wired); reads are empty so an
@@ -209923,10 +210080,10 @@ var loadWorkspaceContracts = (ref, kind) => active8.loadWorkspaceContracts(ref,
209923
210080
  var contractsMaterializeInPlace = () => active8.materializesInPlace;
209924
210081
 
209925
210082
  // packages/core/dist/lib/spec-store.js
209926
- import fs65 from "node:fs";
209927
- import path70 from "node:path";
210083
+ import fs66 from "node:fs";
210084
+ import path71 from "node:path";
209928
210085
  function specPath(repoKey, artifact) {
209929
- return path70.join(repoKey, ".truecourse", "specs", `${artifact}.json`);
210086
+ return path71.join(repoKey, ".truecourse", "specs", `${artifact}.json`);
209930
210087
  }
209931
210088
  function isPrDecisionsRef(commitSha) {
209932
210089
  return /^_pr\/\d+$/.test(commitSha ?? "");
@@ -209939,18 +210096,18 @@ var FileSpecStore = class {
209939
210096
  throw new Error(PR_DECISIONS_FILE_ERROR);
209940
210097
  }
209941
210098
  const file = specPath(ref.repoKey, artifact);
209942
- fs65.mkdirSync(path70.dirname(file), { recursive: true });
209943
- fs65.writeFileSync(file, JSON.stringify(json2, null, 2) + "\n", "utf-8");
210099
+ fs66.mkdirSync(path71.dirname(file), { recursive: true });
210100
+ fs66.writeFileSync(file, JSON.stringify(json2, null, 2) + "\n", "utf-8");
209944
210101
  }
209945
210102
  async loadSpec(ref, artifact) {
209946
210103
  if (artifact === "decisions" && isPrDecisionsRef(ref.commitSha)) {
209947
210104
  throw new Error(PR_DECISIONS_FILE_ERROR);
209948
210105
  }
209949
210106
  const file = specPath(ref.repoKey, artifact);
209950
- if (!fs65.existsSync(file))
210107
+ if (!fs66.existsSync(file))
209951
210108
  return null;
209952
210109
  try {
209953
- return JSON.parse(fs65.readFileSync(file, "utf-8"));
210110
+ return JSON.parse(fs66.readFileSync(file, "utf-8"));
209954
210111
  } catch {
209955
210112
  return null;
209956
210113
  }
@@ -209960,8 +210117,8 @@ var FileSpecStore = class {
209960
210117
  throw new Error(PR_DECISIONS_FILE_ERROR);
209961
210118
  }
209962
210119
  const file = specPath(ref.repoKey, artifact);
209963
- if (fs65.existsSync(file))
209964
- fs65.rmSync(file);
210120
+ if (fs66.existsSync(file))
210121
+ fs66.rmSync(file);
209965
210122
  }
209966
210123
  // The file impl is single-document-per-repo, so "latest" === read the file.
209967
210124
  async loadLatest(repoKey, artifact) {
@@ -209988,23 +210145,23 @@ var loadLatestSpec = (repoKey, artifact) => active9.loadLatest(repoKey, artifact
209988
210145
  var specsMaterializeInPlace = () => active9.materializesInPlace;
209989
210146
 
209990
210147
  // packages/core/dist/lib/inferred-action-store.js
209991
- import fs66 from "node:fs";
209992
- import path71 from "node:path";
210148
+ import fs67 from "node:fs";
210149
+ import path72 from "node:path";
209993
210150
  function actionsFile(repoKey) {
209994
- return path71.join(repoKey, ".truecourse", "specs", "inferred-actions.json");
210151
+ return path72.join(repoKey, ".truecourse", "specs", "inferred-actions.json");
209995
210152
  }
209996
210153
  var FileInferredActionStore = class {
209997
210154
  read(repoKey) {
209998
210155
  try {
209999
- return JSON.parse(fs66.readFileSync(actionsFile(repoKey), "utf-8"));
210156
+ return JSON.parse(fs67.readFileSync(actionsFile(repoKey), "utf-8"));
210000
210157
  } catch {
210001
210158
  return [];
210002
210159
  }
210003
210160
  }
210004
210161
  write(repoKey, actions) {
210005
210162
  const file = actionsFile(repoKey);
210006
- fs66.mkdirSync(path71.dirname(file), { recursive: true });
210007
- fs66.writeFileSync(file, JSON.stringify(actions, null, 2) + "\n", "utf-8");
210163
+ fs67.mkdirSync(path72.dirname(file), { recursive: true });
210164
+ fs67.writeFileSync(file, JSON.stringify(actions, null, 2) + "\n", "utf-8");
210008
210165
  }
210009
210166
  async setAction(repoKey, action) {
210010
210167
  const next = this.read(repoKey).filter((a) => !(a.kind === action.kind && a.identity === action.identity));
@@ -210133,13 +210290,13 @@ function resolveTransport(options) {
210133
210290
  }
210134
210291
  return getDefaultTransport();
210135
210292
  }
210136
- var GENERATED_MARKER_REL = path72.join(".truecourse", "contracts", "result.json");
210293
+ var GENERATED_MARKER_REL = path73.join(".truecourse", "contracts", "result.json");
210137
210294
  function generatedMarkerPath(repoRoot5) {
210138
- return path72.join(repoRoot5, GENERATED_MARKER_REL);
210295
+ return path73.join(repoRoot5, GENERATED_MARKER_REL);
210139
210296
  }
210140
210297
  function stampGeneratedMarker(repoRoot5, summary) {
210141
210298
  const file = generatedMarkerPath(repoRoot5);
210142
- fs67.mkdirSync(path72.dirname(file), { recursive: true });
210299
+ fs68.mkdirSync(path73.dirname(file), { recursive: true });
210143
210300
  const body = {
210144
210301
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
210145
210302
  written: summary?.written ?? 0,
@@ -210147,7 +210304,7 @@ function stampGeneratedMarker(repoRoot5, summary) {
210147
210304
  validationIssues: summary?.validationIssues ?? [],
210148
210305
  enumerateFailures: summary?.enumerateFailures ?? []
210149
210306
  };
210150
- fs67.writeFileSync(file, JSON.stringify(body, null, 2) + "\n");
210307
+ fs68.writeFileSync(file, JSON.stringify(body, null, 2) + "\n");
210151
210308
  }
210152
210309
  function resolveCurateModels(repoRoot5) {
210153
210310
  return {
@@ -210271,22 +210428,22 @@ async function curateInProcess(repoRoot5, options = {}) {
210271
210428
  }
210272
210429
  }
210273
210430
  function buildPriorContracts(repoRoot5) {
210274
- const dir = path72.join(repoRoot5, ".truecourse", "contracts");
210275
- if (!fs67.existsSync(dir))
210431
+ const dir = path73.join(repoRoot5, ".truecourse", "contracts");
210432
+ if (!fs68.existsSync(dir))
210276
210433
  return void 0;
210277
210434
  const targets = [];
210278
210435
  const bodyByKey = /* @__PURE__ */ new Map();
210279
210436
  const walk20 = (d3) => {
210280
- for (const e of fs67.readdirSync(d3, { withFileTypes: true })) {
210437
+ for (const e of fs68.readdirSync(d3, { withFileTypes: true })) {
210281
210438
  if (e.isDirectory()) {
210282
210439
  if (e.name === "_inferred")
210283
210440
  continue;
210284
- walk20(path72.join(d3, e.name));
210441
+ walk20(path73.join(d3, e.name));
210285
210442
  } else if (e.name.endsWith(".tc")) {
210286
- const abs = path72.join(d3, e.name);
210287
- const src = fs67.readFileSync(abs, "utf-8");
210443
+ const abs = path73.join(d3, e.name);
210444
+ const src = fs68.readFileSync(abs, "utf-8");
210288
210445
  try {
210289
- const file = parser_ohm_exports.parseTcFile(path72.relative(dir, abs), src);
210446
+ const file = parser_ohm_exports.parseTcFile(path73.relative(dir, abs), src);
210290
210447
  for (const key4 of resolver_exports.resolve([file]).index.keys()) {
210291
210448
  const colon = key4.indexOf(":");
210292
210449
  if (colon < 0)
@@ -210446,18 +210603,18 @@ function resolverHardError(result) {
210446
210603
  const detail = reasons.length ? reasons.slice(0, 3).join("; ") : "duplicate or conflicting artifact identities";
210447
210604
  return new Error(`Contract corpus failed to resolve \u2014 ${detail}`);
210448
210605
  }
210449
- var LEGACY_VERIFY_STATE_REL = path72.join(".truecourse", ".cache", "verifier", "verify-state.json");
210606
+ var LEGACY_VERIFY_STATE_REL = path73.join(".truecourse", ".cache", "verifier", "verify-state.json");
210450
210607
  function legacyVerifyStatePath(repoRoot5) {
210451
- return path72.join(repoRoot5, LEGACY_VERIFY_STATE_REL);
210608
+ return path73.join(repoRoot5, LEGACY_VERIFY_STATE_REL);
210452
210609
  }
210453
210610
  async function withContracts(repoRoot5, options, tracker, fn) {
210454
- const fallbackPath = path72.join(repoRoot5, ".truecourse", "contracts");
210611
+ const fallbackPath = path73.join(repoRoot5, ".truecourse", "contracts");
210455
210612
  const wsMat = options.workspaceOrgId ? await loadWorkspaceContracts({ workspaceOrgId: options.workspaceOrgId }, "contracts") : null;
210456
210613
  let repoMat = null;
210457
210614
  try {
210458
210615
  let recorded;
210459
210616
  if (options.contractsDir) {
210460
- if (!fs67.existsSync(options.contractsDir)) {
210617
+ if (!fs68.existsSync(options.contractsDir)) {
210461
210618
  const err = new Error(`Contracts directory not found at ${options.contractsDir}. Run \`truecourse contracts generate\` first.`);
210462
210619
  tracker?.error("load", err.message);
210463
210620
  throw err;
@@ -210502,7 +210659,7 @@ async function verifyInProcess(repoRoot5, options = {}) {
210502
210659
  tracker?.start("compare");
210503
210660
  tracker?.done("compare", `${result.drifts.length} drift${result.drifts.length === 1 ? "" : "s"}`);
210504
210661
  if (options.ref) {
210505
- result.drifts = result.drifts.map((d3) => d3.filePath && path72.isAbsolute(d3.filePath) ? { ...d3, filePath: path72.relative(repoRoot5, d3.filePath).split(path72.sep).join("/") } : d3);
210662
+ result.drifts = result.drifts.map((d3) => d3.filePath && path73.isAbsolute(d3.filePath) ? { ...d3, filePath: path73.relative(repoRoot5, d3.filePath).split(path73.sep).join("/") } : d3);
210506
210663
  }
210507
210664
  const verifiedAt = (/* @__PURE__ */ new Date()).toISOString();
210508
210665
  const { branch, commitHash } = await gitMeta(repoRoot5);
@@ -210546,7 +210703,7 @@ async function verifyInProcess(repoRoot5, options = {}) {
210546
210703
  bySeverity: summary.bySeverity
210547
210704
  });
210548
210705
  await deleteVerifyDiff(storeKey);
210549
- fs67.rmSync(legacyVerifyStatePath(repoRoot5), { force: true });
210706
+ fs68.rmSync(legacyVerifyStatePath(repoRoot5), { force: true });
210550
210707
  }
210551
210708
  const state = {
210552
210709
  verifiedAt,
@@ -210594,7 +210751,7 @@ async function runWithStash(repoRoot5, skipStash, tracker, fn) {
210594
210751
  const status = await stashGit.status();
210595
210752
  if (!status.isClean()) {
210596
210753
  const gitRoot = (await stashGit.revparse(["--show-toplevel"])).trim();
210597
- if (path72.resolve(repoRoot5) === path72.resolve(gitRoot)) {
210754
+ if (path73.resolve(repoRoot5) === path73.resolve(gitRoot)) {
210598
210755
  tracker?.detail?.("load", "Stashing pending changes...");
210599
210756
  const res = await stashGit.stash(["push", "--include-untracked", "-m", "truecourse-verify-stash"]);
210600
210757
  didStash = !res.includes("No local changes");
@@ -210696,7 +210853,7 @@ async function verifyDiffInProcess(repoRoot5, options = {}) {
210696
210853
  async function inferInProcess(repoRoot5, options = {}) {
210697
210854
  const startedAt = Date.now();
210698
210855
  const codeDir = options.codeDir ?? autodetectCodeDir(repoRoot5);
210699
- let contractsDir = options.contractsDir ?? path72.join(repoRoot5, ".truecourse", "contracts");
210856
+ let contractsDir = options.contractsDir ?? path73.join(repoRoot5, ".truecourse", "contracts");
210700
210857
  let releaseContracts = async () => {
210701
210858
  };
210702
210859
  if (!options.contractsDir && options.ref) {
@@ -210740,7 +210897,7 @@ async function persistInferred(repoRoot5, options, contractsDir, codeDir, starte
210740
210897
  });
210741
210898
  }
210742
210899
  if (!options.dryRun && options.ref) {
210743
- await saveContracts(options.ref, "contracts_inferred", path72.join(contractsDir, "_inferred"));
210900
+ await saveContracts(options.ref, "contracts_inferred", path73.join(contractsDir, "_inferred"));
210744
210901
  }
210745
210902
  const rendered = result.decisions.map((d3) => renderDecision(d3));
210746
210903
  const decisionPaths = rendered.map((r) => r.relPath);
@@ -210763,8 +210920,8 @@ async function persistInferred(repoRoot5, options, contractsDir, codeDir, starte
210763
210920
  return { infer: result, written, proposed, decisionPaths, summaries };
210764
210921
  }
210765
210922
  function autodetectCodeDir(repoRoot5) {
210766
- const codeSubdir = path72.join(repoRoot5, "code");
210767
- if (fs67.existsSync(codeSubdir) && fs67.statSync(codeSubdir).isDirectory()) {
210923
+ const codeSubdir = path73.join(repoRoot5, "code");
210924
+ if (fs68.existsSync(codeSubdir) && fs68.statSync(codeSubdir).isDirectory()) {
210768
210925
  return codeSubdir;
210769
210926
  }
210770
210927
  return repoRoot5;
@@ -210774,7 +210931,8 @@ var EMPTY_DECISIONS3 = {
210774
210931
  manualIncludes: [],
210775
210932
  manualExcludes: [],
210776
210933
  relations: [],
210777
- manualAreas: []
210934
+ manualAreas: [],
210935
+ conflictResolutions: []
210778
210936
  };
210779
210937
  var DECISIONS_REF = "_repo";
210780
210938
  var prDecisionsRef = (pr) => `_pr/${pr}`;
@@ -210828,7 +210986,12 @@ function mergeDecisions(base2, overlay) {
210828
210986
  ...(base2.manualAreas ?? []).filter((a) => !overlayAreaDocs.has(a.doc)),
210829
210987
  ...overlay.manualAreas ?? []
210830
210988
  ];
210831
- return { version: 1, manualIncludes, manualExcludes, relations, manualAreas };
210989
+ const overlayResKeys = new Set((overlay.conflictResolutions ?? []).map(conflictResolutionKey));
210990
+ const conflictResolutions = [
210991
+ ...(base2.conflictResolutions ?? []).filter((r) => !overlayResKeys.has(conflictResolutionKey(r))),
210992
+ ...overlay.conflictResolutions ?? []
210993
+ ];
210994
+ return { version: 1, manualIncludes, manualExcludes, relations, manualAreas, conflictResolutions };
210832
210995
  }
210833
210996
  function uniqueStrings(items) {
210834
210997
  return [...new Set(items)];
@@ -210837,6 +211000,13 @@ function getCorpus(repoKey) {
210837
211000
  return loadLatestSpec(repoKey, "corpus");
210838
211001
  }
210839
211002
  var relationKey = (r) => `${[r.older, r.newer].sort().join(" ")} ${r.scope ?? ""}`;
211003
+ var conflictResolutionKey = (r) => {
211004
+ const sides = [
211005
+ `${r.docA}#${r.anchorA ?? ""}`,
211006
+ `${r.docB}#${r.anchorB ?? ""}`
211007
+ ].sort();
211008
+ return sides.join(" \0 ");
211009
+ };
210840
211010
  function applyAddRelation(existing, input) {
210841
211011
  if (input.older === input.newer) {
210842
211012
  throw new Error("addRelation: older and newer must be different docs");
@@ -210849,20 +211019,22 @@ function applyAddRelation(existing, input) {
210849
211019
  manualIncludes: existing.manualIncludes ?? [],
210850
211020
  manualExcludes: existing.manualExcludes ?? [],
210851
211021
  relations: [...dedup, relation],
210852
- manualAreas: existing.manualAreas ?? []
211022
+ manualAreas: existing.manualAreas ?? [],
211023
+ conflictResolutions: existing.conflictResolutions ?? []
210853
211024
  };
210854
211025
  }
210855
211026
  function applyRemoveRelation(existing, input) {
210856
211027
  const matches = (r) => {
210857
- const samePair = r.older === input.older && r.newer === input.newer || r.older === input.newer && r.newer === input.older;
210858
- return samePair && (input.scope === void 0 || r.scope === input.scope);
211028
+ const samePair2 = r.older === input.older && r.newer === input.newer || r.older === input.newer && r.newer === input.older;
211029
+ return samePair2 && (input.scope === void 0 || r.scope === input.scope);
210859
211030
  };
210860
211031
  return {
210861
211032
  version: 1,
210862
211033
  manualIncludes: existing.manualIncludes ?? [],
210863
211034
  manualExcludes: existing.manualExcludes ?? [],
210864
211035
  relations: (existing.relations ?? []).filter((r) => !matches(r)),
210865
- manualAreas: existing.manualAreas ?? []
211036
+ manualAreas: existing.manualAreas ?? [],
211037
+ conflictResolutions: existing.conflictResolutions ?? []
210866
211038
  };
210867
211039
  }
210868
211040
  function applyAddManualInclude(existing, docPath) {
@@ -210875,7 +211047,8 @@ function applyAddManualInclude(existing, docPath) {
210875
211047
  manualIncludes: includes.includes(docPath) ? includes : [...includes, docPath],
210876
211048
  manualExcludes: excludes.filter((p2) => p2 !== docPath),
210877
211049
  relations: existing.relations ?? [],
210878
- manualAreas: existing.manualAreas ?? []
211050
+ manualAreas: existing.manualAreas ?? [],
211051
+ conflictResolutions: existing.conflictResolutions ?? []
210879
211052
  };
210880
211053
  }
210881
211054
  function applyRemoveManualInclude(existing, docPath) {
@@ -210884,7 +211057,8 @@ function applyRemoveManualInclude(existing, docPath) {
210884
211057
  manualIncludes: (existing.manualIncludes ?? []).filter((p2) => p2 !== docPath),
210885
211058
  manualExcludes: existing.manualExcludes ?? [],
210886
211059
  relations: existing.relations ?? [],
210887
- manualAreas: existing.manualAreas ?? []
211060
+ manualAreas: existing.manualAreas ?? [],
211061
+ conflictResolutions: existing.conflictResolutions ?? []
210888
211062
  };
210889
211063
  }
210890
211064
  function applyAddManualExclude(existing, docPath) {
@@ -210897,7 +211071,8 @@ function applyAddManualExclude(existing, docPath) {
210897
211071
  manualIncludes: includes.filter((p2) => p2 !== docPath),
210898
211072
  manualExcludes: excludes.includes(docPath) ? excludes : [...excludes, docPath],
210899
211073
  relations: existing.relations ?? [],
210900
- manualAreas: existing.manualAreas ?? []
211074
+ manualAreas: existing.manualAreas ?? [],
211075
+ conflictResolutions: existing.conflictResolutions ?? []
210901
211076
  };
210902
211077
  }
210903
211078
  function applyRemoveManualExclude(existing, docPath) {
@@ -210906,7 +211081,23 @@ function applyRemoveManualExclude(existing, docPath) {
210906
211081
  manualIncludes: existing.manualIncludes ?? [],
210907
211082
  manualExcludes: (existing.manualExcludes ?? []).filter((p2) => p2 !== docPath),
210908
211083
  relations: existing.relations ?? [],
210909
- manualAreas: existing.manualAreas ?? []
211084
+ manualAreas: existing.manualAreas ?? [],
211085
+ conflictResolutions: existing.conflictResolutions ?? []
211086
+ };
211087
+ }
211088
+ function applyAddConflictResolution(existing, input) {
211089
+ if (input.docA === input.docB) {
211090
+ throw new Error("addConflictResolution: docA and docB must be different docs");
211091
+ }
211092
+ const key4 = conflictResolutionKey(input);
211093
+ const dedup = (existing.conflictResolutions ?? []).filter((r) => conflictResolutionKey(r) !== key4);
211094
+ return {
211095
+ version: 1,
211096
+ manualIncludes: existing.manualIncludes ?? [],
211097
+ manualExcludes: existing.manualExcludes ?? [],
211098
+ relations: existing.relations ?? [],
211099
+ manualAreas: existing.manualAreas ?? [],
211100
+ conflictResolutions: [...dedup, input]
210910
211101
  };
210911
211102
  }
210912
211103
  async function addRelation(repoRoot5, input, opts) {
@@ -210943,6 +211134,11 @@ async function removeManualExclude(repoRoot5, docPath, opts) {
210943
211134
  await storeDecisions(repoRoot5, next, opts);
210944
211135
  return next;
210945
211136
  }
211137
+ async function addConflictResolution(repoRoot5, input, opts) {
211138
+ const next = applyAddConflictResolution(await loadDecisions(repoRoot5, opts), input);
211139
+ await storeDecisions(repoRoot5, next, opts);
211140
+ return next;
211141
+ }
210946
211142
 
210947
211143
  // tools/cli/src/commands/contracts.ts
210948
211144
  init_progress();
@@ -211119,8 +211315,8 @@ async function runContractsGenerate(options = {}) {
211119
211315
  }
211120
211316
  async function runContractsList(options = {}) {
211121
211317
  const repoRoot5 = options.cwd ?? process.cwd();
211122
- const contractsDir = path73.join(repoRoot5, ".truecourse", "contracts");
211123
- if (!fs68.existsSync(contractsDir)) {
211318
+ const contractsDir = path74.join(repoRoot5, ".truecourse", "contracts");
211319
+ if (!fs69.existsSync(contractsDir)) {
211124
211320
  O2.info("No contracts found. Run `truecourse contracts generate` first.");
211125
211321
  return;
211126
211322
  }
@@ -211128,12 +211324,12 @@ async function runContractsList(options = {}) {
211128
211324
  const fileNodes = [];
211129
211325
  let parseErrors = 0;
211130
211326
  const visit = (dir) => {
211131
- for (const entry of fs68.readdirSync(dir, { withFileTypes: true })) {
211132
- const full = path73.join(dir, entry.name);
211327
+ for (const entry of fs69.readdirSync(dir, { withFileTypes: true })) {
211328
+ const full = path74.join(dir, entry.name);
211133
211329
  if (entry.isDirectory()) visit(full);
211134
211330
  else if (entry.isFile() && entry.name.endsWith(".tc")) {
211135
211331
  try {
211136
- fileNodes.push(parserOhm.parseTcFile(full, fs68.readFileSync(full, "utf-8")));
211332
+ fileNodes.push(parserOhm.parseTcFile(full, fs69.readFileSync(full, "utf-8")));
211137
211333
  } catch {
211138
211334
  parseErrors += 1;
211139
211335
  }
@@ -211160,7 +211356,7 @@ async function runContractsList(options = {}) {
211160
211356
  mt(`Contracts \u2014 ${artifacts.length} ${scope}artifact${artifacts.length === 1 ? "" : "s"}`);
211161
211357
  for (const a of artifacts) {
211162
211358
  const conf = a.confidence ? `[${a.confidence}] ` : "";
211163
- const loc = a.origin ? a.origin.lines[0] >= 0 ? `${a.origin.source}:${a.origin.lines[0]}` : a.origin.source : `${path73.relative(repoRoot5, a.declarationLoc.filePath)}:${a.declarationLoc.lineStart}`;
211359
+ const loc = a.origin ? a.origin.lines[0] >= 0 ? `${a.origin.source}:${a.origin.lines[0]}` : a.origin.source : `${path74.relative(repoRoot5, a.declarationLoc.filePath)}:${a.declarationLoc.lineStart}`;
211164
211360
  console.log(` ${conf}${a.ref.type}:${a.ref.identity} ${loc}`);
211165
211361
  }
211166
211362
  if (parseErrors > 0) {
@@ -211172,8 +211368,8 @@ async function runContractsList(options = {}) {
211172
211368
  }
211173
211369
  async function runContractsValidate(options = {}) {
211174
211370
  const repoRoot5 = options.cwd ?? process.cwd();
211175
- const contractsDir = path73.join(repoRoot5, ".truecourse", "contracts");
211176
- if (!fs68.existsSync(contractsDir)) {
211371
+ const contractsDir = path74.join(repoRoot5, ".truecourse", "contracts");
211372
+ if (!fs69.existsSync(contractsDir)) {
211177
211373
  O2.error("No .truecourse/contracts/ directory found.");
211178
211374
  process.exit(1);
211179
211375
  }
@@ -211181,14 +211377,14 @@ async function runContractsValidate(options = {}) {
211181
211377
  const fileNodes = [];
211182
211378
  const issues = [];
211183
211379
  const visit = (dir) => {
211184
- for (const entry of fs68.readdirSync(dir, { withFileTypes: true })) {
211185
- const full = path73.join(dir, entry.name);
211380
+ for (const entry of fs69.readdirSync(dir, { withFileTypes: true })) {
211381
+ const full = path74.join(dir, entry.name);
211186
211382
  if (entry.isDirectory()) visit(full);
211187
211383
  else if (entry.isFile() && entry.name.endsWith(".tc")) {
211188
211384
  try {
211189
- fileNodes.push(parserOhm.parseTcFile(full, fs68.readFileSync(full, "utf-8")));
211385
+ fileNodes.push(parserOhm.parseTcFile(full, fs69.readFileSync(full, "utf-8")));
211190
211386
  } catch (e) {
211191
- issues.push(`${path73.relative(repoRoot5, full)}: parse error: ${e instanceof Error ? e.message : e}`);
211387
+ issues.push(`${path74.relative(repoRoot5, full)}: parse error: ${e instanceof Error ? e.message : e}`);
211192
211388
  }
211193
211389
  }
211194
211390
  }
@@ -211196,11 +211392,11 @@ async function runContractsValidate(options = {}) {
211196
211392
  visit(contractsDir);
211197
211393
  const resolution = resolver.resolve(fileNodes);
211198
211394
  for (const err of resolution.errors) {
211199
- issues.push(`${path73.relative(repoRoot5, err.filePath)}:${err.line} ${err.message}`);
211395
+ issues.push(`${path74.relative(repoRoot5, err.filePath)}:${err.line} ${err.message}`);
211200
211396
  }
211201
211397
  const trulyUnresolved = resolution.unresolvedRefs.filter((u2) => u2.ref.type !== "Unknown");
211202
211398
  for (const u2 of trulyUnresolved) {
211203
- issues.push(`${path73.relative(repoRoot5, u2.usedAt.filePath)}:${u2.usedAt.lineStart} unresolved ${u2.ref.type}:${u2.ref.identity}`);
211399
+ issues.push(`${path74.relative(repoRoot5, u2.usedAt.filePath)}:${u2.usedAt.lineStart} unresolved ${u2.ref.type}:${u2.ref.identity}`);
211204
211400
  }
211205
211401
  if (issues.length === 0) {
211206
211402
  O2.success(`Validated ${resolution.index.size} artifact${resolution.index.size === 1 ? "" : "s"} \u2014 no issues.`);
@@ -211214,7 +211410,7 @@ async function runContractsValidate(options = {}) {
211214
211410
 
211215
211411
  // tools/cli/src/commands/spec.ts
211216
211412
  init_dist4();
211217
- import path74 from "node:path";
211413
+ import path75 from "node:path";
211218
211414
  init_dist5();
211219
211415
  init_progress();
211220
211416
  init_registry();
@@ -211265,17 +211461,18 @@ async function runSpecScan(opts = {}) {
211265
211461
  O2.warn("Manual includes outside spec.include (never discovered \u2014 widen the scope to pick them up):");
211266
211462
  for (const inc of s.outOfScopeManualIncludes) O2.message(` \u2022 ${inc}`);
211267
211463
  }
211268
- if (s.openOverlaps.length > 0) {
211464
+ const open = openConflicts(curate2.corpus, curate2.decisions);
211465
+ if (open.length > 0) {
211269
211466
  O2.message("");
211270
- O2.message("Open overlaps (areas where two docs may disagree \u2014 resolve with a relation):");
211271
- for (const o of s.openOverlaps.slice(0, 10)) {
211467
+ O2.message("Open overlaps (two docs may disagree \u2014 pick a side or dismiss with `spec conflicts resolve`):");
211468
+ for (const o of open.slice(0, 10)) {
211272
211469
  O2.message(` \u2022 ${o.area}: ${o.a} \u2194 ${o.b}`);
211273
211470
  }
211274
- if (s.openOverlaps.length > 10) {
211275
- O2.message(` \u2026 (+${s.openOverlaps.length - 10} more)`);
211471
+ if (open.length > 10) {
211472
+ O2.message(` \u2026 (+${open.length - 10} more)`);
211276
211473
  }
211277
211474
  }
211278
- const openCount = s.openOverlaps.length;
211475
+ const openCount = open.length;
211279
211476
  gt(
211280
211477
  openCount === 0 ? "Corpus written to .truecourse/specs/corpus.json. Run `truecourse guard generate`." : `Corpus written to .truecourse/specs/corpus.json. ${openCount} conflict${openCount === 1 ? "" : "s"} to resolve (\`truecourse spec conflicts list\`), then \`truecourse guard generate\`.`
211281
211478
  );
@@ -211307,6 +211504,14 @@ async function runSpecStatus(opts = {}) {
211307
211504
  const ov = area.overlaps.length ? ` \xB7 ${area.overlaps.length} overlap${area.overlaps.length === 1 ? "" : "s"}` : "";
211308
211505
  O2.message(` ${area.id.padEnd(30)} ${area.docRefs.length} doc${area.docRefs.length === 1 ? "" : "s"}${ov}`);
211309
211506
  }
211507
+ const orphaned = orphanedConflictResolutions(corpus, decisions);
211508
+ if (orphaned.length > 0) {
211509
+ O2.message("");
211510
+ O2.warn(
211511
+ `${orphaned.length} orphaned conflict resolution${orphaned.length === 1 ? "" : "s"} (no longer match a flagged dispute \u2014 review with \`spec conflicts list\`):`
211512
+ );
211513
+ for (const o of orphaned.slice(0, 10)) O2.message(` \u2022 ${o.docA} \u2194 ${o.docB} (${o.verdict})`);
211514
+ }
211310
211515
  gt(
211311
211516
  open === 0 ? "No open overlaps \u2014 run `truecourse guard generate`." : "Open overlaps \u2014 see `truecourse spec conflicts list`."
211312
211517
  );
@@ -211334,7 +211539,7 @@ async function runVerify(opts = {}) {
211334
211539
  O2.message("");
211335
211540
  O2.message("Drifts:");
211336
211541
  for (const d3 of verify2.drifts.slice(0, 20)) {
211337
- const loc = d3.filePath ? ` ${path74.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211542
+ const loc = d3.filePath ? ` ${path75.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211338
211543
  O2.message(` [${d3.severity}] ${d3.obligationKey}${loc}`);
211339
211544
  O2.message(` \u2192 ${d3.message}`);
211340
211545
  }
@@ -211368,7 +211573,7 @@ async function runVerifyDiff(opts) {
211368
211573
  O2.message("");
211369
211574
  O2.message(`${label}:`);
211370
211575
  for (const d3 of drifts.slice(0, 20)) {
211371
- const loc = d3.filePath ? ` ${path74.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211576
+ const loc = d3.filePath ? ` ${path75.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211372
211577
  O2.message(` [${d3.severity}] ${d3.obligationKey}${loc}`);
211373
211578
  }
211374
211579
  if (drifts.length > 20) O2.message(` \u2026 (+${drifts.length - 20} more)`);
@@ -211423,8 +211628,8 @@ async function runInfer(opts = {}) {
211423
211628
 
211424
211629
  // tools/cli/src/commands/spec-conflicts.ts
211425
211630
  init_dist4();
211426
- import fs69 from "node:fs";
211427
- import path75 from "node:path";
211631
+ import fs70 from "node:fs";
211632
+ import path76 from "node:path";
211428
211633
  init_dist5();
211429
211634
  var root = (opts) => opts.cwd ?? process.cwd();
211430
211635
  var base = (ref) => ref.split("/").pop() ?? ref;
@@ -211436,25 +211641,47 @@ function loadCorpusOrExit(repoRoot5) {
211436
211641
  }
211437
211642
  return corpus;
211438
211643
  }
211644
+ function resolvedLabel(c2) {
211645
+ if (c2.resolution) {
211646
+ if (c2.resolution.verdict === "dismissed") return "dismissed (not a real conflict)";
211647
+ const winner = c2.resolution.verdict === "a" ? c2.resolution.docA : c2.resolution.docB;
211648
+ return `${base(winner)} is right (loser\u2019s claim suppressed at generate)`;
211649
+ }
211650
+ if (c2.excludedRef) return `${base(c2.excludedRef)} excluded`;
211651
+ return "resolved";
211652
+ }
211439
211653
  async function runSpecConflictsList(opts = {}) {
211440
211654
  const repoRoot5 = root(opts);
211441
211655
  const corpus = loadCorpusOrExit(repoRoot5);
211442
- const conflicts2 = buildCorpusConflicts(corpus, readCorpusDecisions(repoRoot5));
211656
+ const decisions = readCorpusDecisions(repoRoot5);
211657
+ const conflicts2 = buildCorpusConflicts(corpus, decisions);
211443
211658
  const open = conflicts2.filter((c2) => !c2.resolved);
211444
- const resolved = conflicts2.length - open.length;
211445
- mt("Overlaps (areas where docs may disagree)");
211446
- for (const c2 of open) {
211447
- O2.warn(`${c2.area}`);
211448
- O2.message(` ${base(c2.a)} \u2194 ${base(c2.b)}${c2.note ? ` \xB7 ${c2.note}` : ""}`);
211449
- O2.message(` resolve: truecourse spec conflicts resolve ${c2.area} --older ${c2.a} --newer ${c2.b} --precedence`);
211659
+ const orphaned = orphanedConflictResolutions(corpus, decisions);
211660
+ mt("Overlaps (where two docs\u2019 sections may disagree)");
211661
+ conflicts2.forEach((c2, i) => {
211662
+ const n = i + 1;
211663
+ if (c2.resolved) {
211664
+ O2.step(`${n}. ${c2.area} \xB7 ${base(c2.a)} \u2194 ${base(c2.b)} \u2014 resolved: ${resolvedLabel(c2)}`);
211665
+ } else {
211666
+ O2.warn(`${n}. ${c2.area} \xB7 ${base(c2.a)} \u2194 ${base(c2.b)}${c2.note ? ` \xB7 ${c2.note}` : ""}`);
211667
+ O2.message(` pick a side: truecourse spec conflicts resolve ${n} --right ${c2.a} (or --right ${c2.b}, or --dismiss)`);
211668
+ }
211669
+ });
211670
+ if (conflicts2.length === 0) O2.step("No overlaps flagged.");
211671
+ if (orphaned.length > 0) {
211672
+ O2.warn(
211673
+ `${orphaned.length} orphaned resolution${orphaned.length === 1 ? "" : "s"} \u2014 recorded but no longer match a flagged conflict (the docs changed):`
211674
+ );
211675
+ for (const o of orphaned) O2.message(` ${base(o.docA)} \u2194 ${base(o.docB)} (${o.verdict})`);
211450
211676
  }
211451
- if (open.length === 0) O2.step("No open overlaps.");
211452
- gt(`${open.length} open \xB7 ${resolved} resolved. Inspect with \`spec conflicts show <area>\`.`);
211677
+ gt(
211678
+ `${open.length} open \xB7 ${conflicts2.length - open.length} resolved${orphaned.length ? ` \xB7 ${orphaned.length} orphaned` : ""}. Inspect with \`spec conflicts show <area>\`.`
211679
+ );
211453
211680
  }
211454
211681
  function excerpt(repoRoot5, ref, note, max = 20) {
211455
211682
  let text4;
211456
211683
  try {
211457
- text4 = fs69.readFileSync(path75.join(repoRoot5, ref), "utf-8");
211684
+ text4 = fs70.readFileSync(path76.join(repoRoot5, ref), "utf-8");
211458
211685
  } catch {
211459
211686
  return ` (could not read ${ref})`;
211460
211687
  }
@@ -211478,47 +211705,76 @@ async function runSpecConflictsShow(area, opts = {}) {
211478
211705
  for (const ov of a.overlaps) {
211479
211706
  const [da, db] = ov.docs;
211480
211707
  const c2 = conflicts2.find(
211481
- (x) => x.area === area && (x.a === da && x.b === db || x.a === db && x.b === da)
211708
+ (x) => (x.areas.includes(area) || x.area === area) && (x.a === da && x.b === db || x.a === db && x.b === da)
211482
211709
  );
211483
211710
  O2.warn(`${base(da)} \u2194 ${base(db)}${ov.note ? ` \xB7 ${ov.note}` : ""}`);
211484
- if (c2?.relation) O2.message(` resolved \u2192 ${c2.relation.type} (${c2.relation.older} \u21D2 ${c2.relation.newer})`);
211485
- else if (c2?.excludedRef) O2.message(` resolved \u2192 ${c2.excludedRef} excluded`);
211486
- else O2.message(" open");
211711
+ O2.message(c2 && c2.resolved ? ` resolved \u2192 ${resolvedLabel(c2)}` : " open");
211487
211712
  O2.message(` ${da}:`);
211488
211713
  O2.message(excerpt(repoRoot5, da, ov.note));
211489
211714
  O2.message(` ${db}:`);
211490
211715
  O2.message(excerpt(repoRoot5, db, ov.note));
211491
211716
  }
211492
- gt("resolve with `spec conflicts resolve <area> --older P --newer P --replace|--precedence|--keep-both`.");
211717
+ gt("resolve with `spec conflicts resolve <n|area> --right <docPath>` (pick a side) or `--dismiss`.");
211493
211718
  }
211494
- async function runSpecConflictsResolve(area, opts) {
211719
+ function pickConflict(target, conflicts2, right) {
211720
+ if (/^\d+$/.test(target)) {
211721
+ const idx = Number(target) - 1;
211722
+ if (idx < 0 || idx >= conflicts2.length) {
211723
+ return { error: `No conflict #${target}. Run \`spec conflicts list\` (${conflicts2.length} listed).` };
211724
+ }
211725
+ return conflicts2[idx];
211726
+ }
211727
+ let inArea = conflicts2.filter((c2) => c2.areas.includes(target) || c2.area === target);
211728
+ if (inArea.length === 0) return { error: `No conflicts in area ${target}. List them with \`spec conflicts list\`.` };
211729
+ if (right) inArea = inArea.filter((c2) => c2.a === right || c2.b === right);
211730
+ if (inArea.length === 0) return { error: `No conflict in ${target} involves ${right}.` };
211731
+ if (inArea.length > 1) {
211732
+ return { error: `Area ${target} has ${inArea.length} conflicts \u2014 address one by its number (\`spec conflicts list\`).` };
211733
+ }
211734
+ return inArea[0];
211735
+ }
211736
+ function buildResolution(c2, verdict, note) {
211737
+ const secOf = (doc) => (c2.sections ?? []).find((s) => s.doc === doc);
211738
+ return {
211739
+ docA: c2.a,
211740
+ anchorA: secOf(c2.a)?.heading ?? null,
211741
+ quoteA: secOf(c2.a)?.quote,
211742
+ docB: c2.b,
211743
+ anchorB: secOf(c2.b)?.heading ?? null,
211744
+ quoteB: secOf(c2.b)?.quote,
211745
+ verdict,
211746
+ resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
211747
+ note
211748
+ };
211749
+ }
211750
+ async function runSpecConflictsResolve(target, opts) {
211495
211751
  const repoRoot5 = root(opts);
211496
- if (!opts.older || !opts.newer) return fail("resolve needs --older <path> and --newer <path>");
211497
- if (opts.older === opts.newer) return fail("--older and --newer must be different docs");
211498
211752
  const corpus = loadCorpusOrExit(repoRoot5);
211499
- const a = corpus.areas.find((x) => x.id === area);
211500
- if (!a) return fail(`No such area: ${area}.`);
211501
- const known = new Set(a.docRefs);
211502
- for (const ref of [opts.older, opts.newer]) {
211503
- if (!known.has(ref)) return fail(`${ref} is not a doc in area ${area}. Docs: ${a.docRefs.join(", ")}`);
211753
+ const decisions = readCorpusDecisions(repoRoot5);
211754
+ if (!opts.right && !opts.dismiss) {
211755
+ return fail("Pass --right <docPath> (pick a side) or --dismiss. Doc-level relations live in `spec chains add` and never resolve a conflict.");
211756
+ }
211757
+ if (opts.right && opts.dismiss) return fail("Pass either --right <docPath> or --dismiss, not both.");
211758
+ const conflicts2 = buildCorpusConflicts(corpus, decisions);
211759
+ const picked = pickConflict(target, conflicts2, opts.right);
211760
+ if ("error" in picked) return fail(picked.error);
211761
+ let verdict;
211762
+ if (opts.dismiss) {
211763
+ verdict = "dismissed";
211764
+ } else {
211765
+ if (opts.right !== picked.a && opts.right !== picked.b) {
211766
+ return fail(`--right must be one of the disputing docs: ${picked.a} or ${picked.b}.`);
211767
+ }
211768
+ verdict = opts.right === picked.a ? "a" : "b";
211769
+ }
211770
+ await addConflictResolution(repoRoot5, buildResolution(picked, verdict, opts.note));
211771
+ if (verdict === "dismissed") {
211772
+ gt(`Dismissed: ${base(picked.a)} \u2194 ${base(picked.b)} is not a real conflict.`);
211773
+ } else {
211774
+ const winner = verdict === "a" ? picked.a : picked.b;
211775
+ const loser = verdict === "a" ? picked.b : picked.a;
211776
+ gt(`Recorded: ${base(winner)} is right. ${base(loser)}\u2019s disputed claim is suppressed at \`truecourse guard generate\`.`);
211504
211777
  }
211505
- const conflict = buildCorpusConflicts(corpus, readCorpusDecisions(repoRoot5)).find(
211506
- (c2) => c2.a === opts.older && c2.b === opts.newer || c2.a === opts.newer && c2.b === opts.older
211507
- );
211508
- const scope = conflict && conflict.areas.length > 1 ? void 0 : area;
211509
- await addRelation(repoRoot5, {
211510
- type: opts.type,
211511
- older: opts.older,
211512
- newer: opts.newer,
211513
- scope,
211514
- detectedFrom: "manual",
211515
- note: opts.note
211516
- });
211517
- const s = fe();
211518
- s.start("Re-scanning to apply the relation");
211519
- await curateInProcess(repoRoot5, {});
211520
- s.stop("Re-scanned");
211521
- gt(`Recorded ${opts.type}: ${opts.older} \u21D2 ${opts.newer} (scope ${scope ?? "all areas"}).`);
211522
211778
  }
211523
211779
  function fail(msg) {
211524
211780
  pt(msg);
@@ -211687,7 +211943,7 @@ function fail3(msg) {
211687
211943
 
211688
211944
  // tools/cli/src/commands/drifts.ts
211689
211945
  init_dist4();
211690
- import path76 from "node:path";
211946
+ import path77 from "node:path";
211691
211947
  var DRIFT_SEVERITIES = [
211692
211948
  "critical",
211693
211949
  "high",
@@ -211724,7 +211980,7 @@ async function runDriftsList(opts = {}) {
211724
211980
  O2.message("");
211725
211981
  O2.message("Drifts:");
211726
211982
  for (const d3 of page) {
211727
- const loc = d3.filePath ? ` ${path76.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211983
+ const loc = d3.filePath ? ` ${path77.relative(root2, d3.filePath)}:${d3.lineStart ?? "?"}` : "";
211728
211984
  O2.message(` [${d3.severity}] ${d3.obligationKey}${loc}`);
211729
211985
  O2.message(` \u2192 ${d3.message}`);
211730
211986
  }
@@ -211755,7 +212011,7 @@ function parseDriftSeverityFlag(raw) {
211755
212011
 
211756
212012
  // tools/cli/src/commands/guard.ts
211757
212013
  init_dist4();
211758
- import path77 from "node:path";
212014
+ import path78 from "node:path";
211759
212015
  init_progress();
211760
212016
 
211761
212017
  // packages/core/dist/commands/guard-in-process.js
@@ -212200,7 +212456,7 @@ async function runGuardGenerate(opts = {}) {
212200
212456
  return;
212201
212457
  }
212202
212458
  const report4 = readGuardResult(repoRoot5) ?? { ...guard, generatedAt: (/* @__PURE__ */ new Date()).toISOString() };
212203
- printGuardGenerateSummary(report4, path77.relative(repoRoot5, guardResultPath(repoRoot5)));
212459
+ printGuardGenerateSummary(report4, path78.relative(repoRoot5, guardResultPath(repoRoot5)));
212204
212460
  if (guard.written.length === 0 && guard.birthFindings.length === 0 && guard.errors.length === 0) {
212205
212461
  gt("No scenarios written.");
212206
212462
  return;
@@ -212408,7 +212664,7 @@ function printLoadErrors(loadErrors) {
212408
212664
 
212409
212665
  // tools/cli/src/commands/config.ts
212410
212666
  init_dist4();
212411
- import path78 from "node:path";
212667
+ import path79 from "node:path";
212412
212668
  var STAGE_LABEL = {
212413
212669
  "spec.relevance": "Spec \xB7 doc relevance",
212414
212670
  "spec.areaTag": "Spec \xB7 area tag",
@@ -212439,7 +212695,7 @@ async function runConfigLlmShow(options = {}) {
212439
212695
  const repoRoot5 = options.cwd ?? process.cwd();
212440
212696
  const { stages, fallbackModel } = describeStageResolutions(repoRoot5);
212441
212697
  mt("LLM model resolution");
212442
- O2.info(`repoRoot ${path78.relative(process.cwd(), repoRoot5) || "."}`);
212698
+ O2.info(`repoRoot ${path79.relative(process.cwd(), repoRoot5) || "."}`);
212443
212699
  O2.info(`fallback ${fallbackModel ?? "(not configured)"}`);
212444
212700
  for (const stage of stages) {
212445
212701
  const label = STAGE_LABEL[stage.stageId];
@@ -212455,8 +212711,8 @@ async function runConfigLlmShow(options = {}) {
212455
212711
 
212456
212712
  // tools/cli/src/commands/hooks.ts
212457
212713
  import { execSync as execSync4 } from "node:child_process";
212458
- import fs70 from "node:fs";
212459
- import path79 from "node:path";
212714
+ import fs71 from "node:fs";
212715
+ import path80 from "node:path";
212460
212716
  init_dist4();
212461
212717
  init_paths();
212462
212718
  init_registry();
@@ -212490,17 +212746,17 @@ pre-commit:
212490
212746
  function findGitDir(from) {
212491
212747
  let dir = from;
212492
212748
  while (true) {
212493
- const gitPath = path79.join(dir, ".git");
212494
- if (fs70.existsSync(gitPath)) {
212495
- const stat = fs70.statSync(gitPath);
212749
+ const gitPath = path80.join(dir, ".git");
212750
+ if (fs71.existsSync(gitPath)) {
212751
+ const stat = fs71.statSync(gitPath);
212496
212752
  if (stat.isDirectory()) return gitPath;
212497
212753
  if (stat.isFile()) {
212498
- const content = fs70.readFileSync(gitPath, "utf-8").trim();
212754
+ const content = fs71.readFileSync(gitPath, "utf-8").trim();
212499
212755
  const match4 = content.match(/^gitdir:\s*(.+)$/);
212500
- if (match4) return path79.resolve(dir, match4[1]);
212756
+ if (match4) return path80.resolve(dir, match4[1]);
212501
212757
  }
212502
212758
  }
212503
- const parent = path79.dirname(dir);
212759
+ const parent = path80.dirname(dir);
212504
212760
  if (parent === dir) return null;
212505
212761
  dir = parent;
212506
212762
  }
@@ -212508,18 +212764,18 @@ function findGitDir(from) {
212508
212764
  function findProjectRoot(from) {
212509
212765
  let dir = from;
212510
212766
  while (true) {
212511
- if (fs70.existsSync(path79.join(dir, ".git"))) return dir;
212512
- const parent = path79.dirname(dir);
212767
+ if (fs71.existsSync(path80.join(dir, ".git"))) return dir;
212768
+ const parent = path80.dirname(dir);
212513
212769
  if (parent === dir) return null;
212514
212770
  dir = parent;
212515
212771
  }
212516
212772
  }
212517
212773
  function loadConfig(projectRoot) {
212518
- const configPath = path79.join(projectRoot, ".truecourse", "hooks.yaml");
212519
- if (!fs70.existsSync(configPath)) return null;
212774
+ const configPath = path80.join(projectRoot, ".truecourse", "hooks.yaml");
212775
+ if (!fs71.existsSync(configPath)) return null;
212520
212776
  let parsed;
212521
212777
  try {
212522
- const raw = fs70.readFileSync(configPath, "utf-8");
212778
+ const raw = fs71.readFileSync(configPath, "utf-8");
212523
212779
  parsed = jsYaml.load(raw) || {};
212524
212780
  } catch (err) {
212525
212781
  console.error(`Error parsing ${configPath}: ${err.message}`);
@@ -212570,11 +212826,11 @@ async function runHooksInstall() {
212570
212826
  } else {
212571
212827
  console.log(INSTALL_WARNING);
212572
212828
  }
212573
- const hooksDir = path79.join(gitDir, "hooks");
212574
- fs70.mkdirSync(hooksDir, { recursive: true });
212575
- const hookPath = path79.join(hooksDir, "pre-commit");
212576
- if (fs70.existsSync(hookPath)) {
212577
- const existing = fs70.readFileSync(hookPath, "utf-8");
212829
+ const hooksDir = path80.join(gitDir, "hooks");
212830
+ fs71.mkdirSync(hooksDir, { recursive: true });
212831
+ const hookPath = path80.join(hooksDir, "pre-commit");
212832
+ if (fs71.existsSync(hookPath)) {
212833
+ const existing = fs71.readFileSync(hookPath, "utf-8");
212578
212834
  if (!existing.includes(HOOK_IDENTIFIER)) {
212579
212835
  console.error(
212580
212836
  "Error: A pre-commit hook already exists and was not installed by TrueCourse."
@@ -212584,16 +212840,16 @@ async function runHooksInstall() {
212584
212840
  process.exit(1);
212585
212841
  }
212586
212842
  }
212587
- fs70.writeFileSync(hookPath, HOOK_SCRIPT, { mode: 493 });
212843
+ fs71.writeFileSync(hookPath, HOOK_SCRIPT, { mode: 493 });
212588
212844
  console.log("TrueCourse pre-commit hook installed.");
212589
212845
  console.log(` ${hookPath}`);
212590
212846
  const projectRoot = findProjectRoot(process.cwd());
212591
212847
  if (projectRoot) {
212592
- const cfgDir = path79.join(projectRoot, ".truecourse");
212593
- const cfgPath = path79.join(cfgDir, "hooks.yaml");
212594
- if (!fs70.existsSync(cfgPath)) {
212595
- fs70.mkdirSync(cfgDir, { recursive: true });
212596
- fs70.writeFileSync(cfgPath, HOOKS_YAML_TEMPLATE);
212848
+ const cfgDir = path80.join(projectRoot, ".truecourse");
212849
+ const cfgPath = path80.join(cfgDir, "hooks.yaml");
212850
+ if (!fs71.existsSync(cfgPath)) {
212851
+ fs71.mkdirSync(cfgDir, { recursive: true });
212852
+ fs71.writeFileSync(cfgPath, HOOKS_YAML_TEMPLATE);
212597
212853
  console.log(` ${cfgPath} (starter config \u2014 edit to customize, commit to share with the team)`);
212598
212854
  }
212599
212855
  }
@@ -212604,17 +212860,17 @@ function runHooksUninstall() {
212604
212860
  console.error("Error: Not a git repository.");
212605
212861
  process.exit(1);
212606
212862
  }
212607
- const hookPath = path79.join(gitDir, "hooks", "pre-commit");
212608
- if (!fs70.existsSync(hookPath)) {
212863
+ const hookPath = path80.join(gitDir, "hooks", "pre-commit");
212864
+ if (!fs71.existsSync(hookPath)) {
212609
212865
  console.log("No pre-commit hook installed.");
212610
212866
  return;
212611
212867
  }
212612
- const content = fs70.readFileSync(hookPath, "utf-8");
212868
+ const content = fs71.readFileSync(hookPath, "utf-8");
212613
212869
  if (!content.includes(HOOK_IDENTIFIER)) {
212614
212870
  console.error("Error: The pre-commit hook was not installed by TrueCourse. Leaving it in place.");
212615
212871
  process.exit(1);
212616
212872
  }
212617
- fs70.unlinkSync(hookPath);
212873
+ fs71.unlinkSync(hookPath);
212618
212874
  console.log("TrueCourse pre-commit hook removed.");
212619
212875
  }
212620
212876
  function runHooksStatus() {
@@ -212623,8 +212879,8 @@ function runHooksStatus() {
212623
212879
  console.error("Error: Not a git repository.");
212624
212880
  process.exit(1);
212625
212881
  }
212626
- const hookPath = path79.join(gitDir, "hooks", "pre-commit");
212627
- const installed = fs70.existsSync(hookPath) && fs70.readFileSync(hookPath, "utf-8").includes(HOOK_IDENTIFIER);
212882
+ const hookPath = path80.join(gitDir, "hooks", "pre-commit");
212883
+ const installed = fs71.existsSync(hookPath) && fs71.readFileSync(hookPath, "utf-8").includes(HOOK_IDENTIFIER);
212628
212884
  if (installed) {
212629
212885
  console.log("TrueCourse pre-commit hook: installed");
212630
212886
  console.log(` ${hookPath}`);
@@ -212733,7 +212989,7 @@ async function runHooksRun() {
212733
212989
 
212734
212990
  // tools/cli/src/index.ts
212735
212991
  var program2 = new Command();
212736
- program2.name("truecourse").version("0.7.0-next.8").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
212992
+ program2.name("truecourse").version("0.7.0-next.9").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
212737
212993
  function warnDiscontinued(command) {
212738
212994
  process.stderr.write(
212739
212995
  `\u26A0 \`${command}\` is discontinued in favor of \`truecourse guard\` \u2014 see the README. Planned removal: 0.8.
@@ -212814,19 +213070,18 @@ specCmd.command("status").description("Summary of docs, areas, relations, and op
212814
213070
  await runSpecStatus();
212815
213071
  });
212816
213072
  var conflictsCmd = specCmd.command("conflicts").description("Inspect and resolve flagged within-area doc overlaps (agent-friendly)");
212817
- conflictsCmd.command("list").description("List flagged overlaps still awaiting a relation").action(async () => {
213073
+ conflictsCmd.command("list").description("List flagged overlaps still awaiting a verdict").action(async () => {
212818
213074
  await runSpecConflictsList();
212819
213075
  });
212820
213076
  conflictsCmd.command("show <area>").description("Show an area's overlapping docs with prose excerpts").action(async (area) => {
212821
213077
  await runSpecConflictsShow(area);
212822
213078
  });
212823
- conflictsCmd.command("resolve <area>").description("Resolve an overlap by recording a doc\u2192doc relation").requiredOption("--older <path>", "Repo-relative path of the older / superseded doc").requiredOption("--newer <path>", "Repo-relative path of the newer / authoritative doc").option("--replace", "`newer` fully supersedes `older` (excluded from generate)").option("--precedence", "Both feed generate; `newer` wins where they overlap").option("--keep-both", "Both are current peers (combine)").option("--note <text>", "Optional rationale").action(async (area, opts) => {
212824
- const type2 = opts.replace ? "replace" : opts.precedence ? "precedence" : opts.keepBoth ? "keep-both" : void 0;
212825
- if (!type2) {
212826
- console.error("Pass one of --replace | --precedence | --keep-both");
212827
- process.exit(1);
212828
- }
212829
- await runSpecConflictsResolve(area, { older: opts.older, newer: opts.newer, type: type2, note: opts.note });
213079
+ conflictsCmd.command("resolve <n|area>").description("Resolve a flagged overlap: pick a side (--right) or dismiss it (--dismiss)").option("--right <path>", "Pick a side: this doc is right; the other side's disputed claim is suppressed at generate").option("--dismiss", "Not a real conflict \u2014 dismiss the detector false-positive").option("--note <text>", "Optional rationale").action(async (target, opts) => {
213080
+ await runSpecConflictsResolve(target, {
213081
+ right: opts.right,
213082
+ dismiss: opts.dismiss,
213083
+ note: opts.note
213084
+ });
212830
213085
  });
212831
213086
  var chainsCmd = specCmd.command("chains").description("Manage doc\u2192doc relations (supersession / precedence overrides)");
212832
213087
  chainsCmd.command("list").description("List effective relations (auto-detected + user-authored)").action(async () => {