@hawkeyexl/manni 2.5.1 → 2.6.0

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.
@@ -71,7 +71,7 @@ import {
71
71
  withValueAt,
72
72
  writeEncryptionKey,
73
73
  writeFileAtomic
74
- } from "./chunk-22WVCFP4.js";
74
+ } from "./chunk-5RJVKWFZ.js";
75
75
 
76
76
  // src/meta/core/reencrypt.ts
77
77
  import { extname } from "node:path";
@@ -185,10 +185,12 @@ __export(cite_exports, {
185
185
  GIT_UNAVAILABLE_HISTORY: () => GIT_UNAVAILABLE_HISTORY,
186
186
  MARKER_JSON: () => MARKER_JSON,
187
187
  MAX_MARKERS_PER_PAGE: () => MAX_MARKERS_PER_PAGE,
188
+ MAX_PAGE_COMMITS: () => MAX_PAGE_COMMITS,
188
189
  MAX_RANGE_LINES: () => MAX_RANGE_LINES,
189
190
  MOVE_BUDGET_BYTES: () => MOVE_BUDGET_BYTES,
190
191
  MOVE_WINDOW_LINES: () => MOVE_WINDOW_LINES,
191
192
  ManifestSet: () => ManifestSet,
193
+ PAGE_HISTORY_UNAVAILABLE: () => PAGE_HISTORY_UNAVAILABLE,
192
194
  RULE_ID_PREFIX: () => RULE_ID_PREFIX,
193
195
  SRC_PATTERN: () => SRC_PATTERN,
194
196
  anchoredLines: () => anchoredLines,
@@ -198,9 +200,12 @@ __export(cite_exports, {
198
200
  buildSourceIndex: () => buildSourceIndex,
199
201
  checkCitations: () => checkCitations,
200
202
  citationInputs: () => citationInputs,
203
+ claimDiff: () => claimDiff,
201
204
  claimEnd: () => claimEnd,
205
+ claimHistory: () => claimHistory,
202
206
  claimLine: () => claimLine,
203
207
  claimMessageFor: () => claimMessageFor,
208
+ claimWords: () => claimWords,
204
209
  classifyCitation: () => classifyCitation,
205
210
  detectEol: () => detectEol,
206
211
  duplicateJoinRefusal: () => duplicateJoinRefusal,
@@ -218,6 +223,7 @@ __export(cite_exports, {
218
223
  hashLines: () => hashLines,
219
224
  hashRange: () => hashRange2,
220
225
  historyOf: () => historyOf,
226
+ holdsWords: () => holdsWords,
221
227
  insertStatementBefore: () => insertStatementBefore,
222
228
  insideFence: () => insideFence,
223
229
  isBoundLine: () => isBoundLine,
@@ -258,6 +264,8 @@ __export(cite_exports, {
258
264
  readSource: () => readSource,
259
265
  reencryptCitationEntries: () => reencryptCitationEntries,
260
266
  reencryptCitations: () => reencryptCitations,
267
+ refineClaim: () => refineClaim,
268
+ refusalLine: () => refusalLine,
261
269
  removalLine: () => removalLine,
262
270
  removeFrontmatterCitations: () => removeFrontmatterCitations,
263
271
  removeLine: () => removeLine,
@@ -276,6 +284,9 @@ __export(cite_exports, {
276
284
  runCheck: () => runCheck,
277
285
  runRemove: () => runRemove,
278
286
  runUpdate: () => runUpdate,
287
+ runsHolding: () => runsHolding,
288
+ sentencesOf: () => sentencesOf,
289
+ sharesSentence: () => sharesSentence,
279
290
  shiftedEntries: () => shiftedEntries,
280
291
  shortCommit: () => shortCommit,
281
292
  shortLine: () => shortLine,
@@ -292,6 +303,7 @@ __export(cite_exports, {
292
303
  splitLines: () => splitLines,
293
304
  splitUnit: () => splitUnit,
294
305
  statementForms: () => statementForms,
306
+ stripMarkers: () => stripMarkers,
295
307
  toBodyLines: () => toBodyLines,
296
308
  toFileLines: () => toFileLines,
297
309
  toValidationResult: () => toValidationResult,
@@ -313,6 +325,7 @@ var CITE_RULES = [
313
325
  "source-missing",
314
326
  "claim-moved",
315
327
  "claim-moved-ambiguous",
328
+ "claim-reanchored",
316
329
  "claim-changed",
317
330
  "marker-orphan",
318
331
  "marker-invalid",
@@ -348,6 +361,7 @@ var DEFAULT_SEVERITY = {
348
361
  "source-missing": "error",
349
362
  "claim-moved": "notice",
350
363
  "claim-moved-ambiguous": "warning",
364
+ "claim-reanchored": "notice",
351
365
  "claim-changed": "warning",
352
366
  "marker-orphan": "error",
353
367
  "marker-invalid": "error",
@@ -1734,6 +1748,10 @@ function gitClient(root) {
1734
1748
  };
1735
1749
  const available = () => once("available", async () => (await run2(root, ["rev-parse", "--show-toplevel"])).ok);
1736
1750
  const failed = (verb, outcome) => new CiteError(`git ${verb} failed: ${outcome.stderr.trim() || outcome.message}`);
1751
+ const shallow = () => once("shallow", async () => {
1752
+ const out = await run2(root, ["rev-parse", "--is-shallow-repository"]);
1753
+ return out.ok && out.stdout.trim() === "true";
1754
+ });
1737
1755
  const hasCommit = (commit) => once(`has\0${commit}`, async () => {
1738
1756
  const out = await run2(root, ["rev-parse", "--verify", "--quiet", "--end-of-options", `${commit}^{commit}`]);
1739
1757
  if (out.ok) return true;
@@ -1771,10 +1789,34 @@ function gitClient(root) {
1771
1789
  const out = await run2(root, ["diff", "--end-of-options", commit, "--", path]);
1772
1790
  if (!out.ok) throw failed("diff", out);
1773
1791
  return out.stdout;
1792
+ }),
1793
+ pageCommits: (path, cap) => once(`commits\0${String(cap)}\0${path}`, async () => {
1794
+ if (!await available()) return { commits: [], shallow: false, truncated: false };
1795
+ const out = await run2(root, [
1796
+ "log",
1797
+ `--format=%H${UNIT}%s`,
1798
+ "--topo-order",
1799
+ `-n${String(cap + 1)}`,
1800
+ "HEAD",
1801
+ "--",
1802
+ path
1803
+ ]);
1804
+ if (!out.ok) throw failed("log", out);
1805
+ const commits = [];
1806
+ for (const line of out.stdout.split(/\r?\n/)) {
1807
+ if (line === "") continue;
1808
+ const at2 = line.indexOf(UNIT);
1809
+ if (at2 === -1) continue;
1810
+ commits.push({ sha: line.slice(0, at2), subject: line.slice(at2 + 1) });
1811
+ }
1812
+ const truncated = commits.length > cap;
1813
+ return { commits: commits.slice(0, cap), shallow: await shallow(), truncated };
1774
1814
  })
1775
1815
  };
1776
1816
  }
1777
- var GIT_UNAVAILABLE_HISTORY = "git is not available here, so citations are checked without history: no never-true, no diffs, no commit subjects.";
1817
+ var UNIT = "";
1818
+ var GIT_UNAVAILABLE_HISTORY = "git is not available here, so citations are checked without history: no never-true, no reanchored claims, no diffs, no commit subjects.";
1819
+ var PAGE_HISTORY_UNAVAILABLE = "the page history ends before the pin held; use fetch-depth: 0 to tell reanchored claims from changed ones";
1778
1820
  var GIT_UNAVAILABLE_COMMIT = "git is not available here, so the citation records no commit.";
1779
1821
  function noGit() {
1780
1822
  return {
@@ -1783,10 +1825,293 @@ function noGit() {
1783
1825
  lsFiles: () => Promise.resolve([]),
1784
1826
  showFile: () => Promise.resolve({ missing: "commit" }),
1785
1827
  subjectsSince: () => Promise.resolve([]),
1786
- diffSince: () => Promise.resolve("")
1828
+ diffSince: () => Promise.resolve(""),
1829
+ pageCommits: () => Promise.resolve({ commits: [], shallow: false, truncated: false })
1787
1830
  };
1788
1831
  }
1789
1832
 
1833
+ // src/cite/core/history.ts
1834
+ var MAX_PAGE_COMMITS = 256;
1835
+ function stripMarkers(lines, format) {
1836
+ return lines.filter((line) => !isMarkerLine(line, format));
1837
+ }
1838
+ function claimWords(lines, format) {
1839
+ return stripMarkers(lines, format).join(" ").replace(/\s+/g, " ").trim();
1840
+ }
1841
+ function sentencesOf(text) {
1842
+ return text.split(/(?<=[.!?])\s+/).map((sentence) => sentence.replace(/\s+/g, " ").trim().toLowerCase()).filter((sentence) => sentence !== "");
1843
+ }
1844
+ function sharesSentence(a, b) {
1845
+ const left = new Set(sentencesOf(a));
1846
+ return sentencesOf(b).some((sentence) => left.has(sentence));
1847
+ }
1848
+ function holdsWords(outer, inner) {
1849
+ if (inner === "") return true;
1850
+ if (outer === inner) return true;
1851
+ if (outer.startsWith(`${inner} `)) return true;
1852
+ if (outer.endsWith(` ${inner}`)) return true;
1853
+ return outer.includes(` ${inner} `);
1854
+ }
1855
+ function runsHolding(lines, format, bodyLine, inner) {
1856
+ if (inner === "") return [];
1857
+ let text = "";
1858
+ const at2 = [];
1859
+ for (let n = Math.max(bodyLine, 1); n <= lines.length; n++) {
1860
+ const line = lines[n - 1] ?? "";
1861
+ if (isMarkerLine(line, format)) continue;
1862
+ const words = line.replace(/\s+/g, " ").trim();
1863
+ if (words === "") continue;
1864
+ if (text !== "") {
1865
+ text += " ";
1866
+ at2.push(n);
1867
+ }
1868
+ for (let i = 0; i < words.length; i++) at2.push(n);
1869
+ text += words;
1870
+ }
1871
+ const out = [];
1872
+ let from = 0;
1873
+ for (; ; ) {
1874
+ const found = text.indexOf(inner, from);
1875
+ if (found === -1) break;
1876
+ from = found + 1;
1877
+ const before = found === 0 ? " " : text[found - 1];
1878
+ const afterAt = found + inner.length;
1879
+ const after = afterAt === text.length ? " " : text[afterAt];
1880
+ if (before !== " " || after !== " ") continue;
1881
+ const start = at2[found];
1882
+ const end = at2[afterAt - 1];
1883
+ if (start === void 0 || end === void 0) continue;
1884
+ if (!out.some((span) => span.start === start && span.end === end)) out.push({ start, end });
1885
+ }
1886
+ return out.filter(
1887
+ (span) => !out.some(
1888
+ (other) => (other.start !== span.start || other.end !== span.end) && other.start >= span.start && other.end <= span.end
1889
+ )
1890
+ );
1891
+ }
1892
+ function bounds(line) {
1893
+ return line === void 0 || line.trim() === "" || ANY_FENCE.test(line);
1894
+ }
1895
+ function pinOf2(lines, span) {
1896
+ if (span.start < 1 || span.end > lines.length || span.end < span.start) return void 0;
1897
+ return hashLines(lines.slice(span.start - 1, span.end).join("\n"));
1898
+ }
1899
+ function readThen(input, text) {
1900
+ const then = readPage(input.page.file, text, { format: input.page.format });
1901
+ const lines = splitLines(then.content);
1902
+ if (input.entry.citation.claim?.lines !== void 0) return { page: then, lines };
1903
+ const id = input.entry.citation.id;
1904
+ if (id === void 0) return void 0;
1905
+ const marker = then.statements.find(
1906
+ (statement) => statement.payload.kind === "ref" && statement.payload.id === id
1907
+ );
1908
+ if (marker === void 0) return void 0;
1909
+ return { page: then, lines, marker };
1910
+ }
1911
+ function anchorHeldAt(input, then) {
1912
+ const pin = input.entry.citation.claim?.integrity;
1913
+ if (pin === void 0) return { kind: "absent" };
1914
+ const was = {
1915
+ citation: input.entry.citation,
1916
+ origin: input.entry.origin,
1917
+ ...then.marker === void 0 ? {} : { marker: then.marker }
1918
+ };
1919
+ const split = then.marker === void 0 ? void 0 : misplacedMarkerAt(then.page, then.lines, then.marker.line, was);
1920
+ const end = claimEnd(then.page, was, then.lines, split);
1921
+ if (end === null || end.status !== "current" && end.status !== "moved") {
1922
+ return { kind: "absent" };
1923
+ }
1924
+ for (const spec of [end.fileLines, end.newFileLines]) {
1925
+ const span = spec === void 0 ? void 0 : parseLines(spec);
1926
+ if (span !== void 0 && pinOf2(then.lines, span) === pin) {
1927
+ return { kind: "found", span, lines: then.lines.slice(span.start - 1, span.end) };
1928
+ }
1929
+ }
1930
+ if (split !== void 0) {
1931
+ const text = unitText(then.lines, split);
1932
+ if (hashLines(text.join("\n")) === pin) {
1933
+ return { kind: "found", span: movedUnit(split), lines: text };
1934
+ }
1935
+ }
1936
+ return { kind: "absent" };
1937
+ }
1938
+ function windowHeldAt(input, then) {
1939
+ const pin = input.entry.citation.claim?.integrity;
1940
+ const marker = then.marker;
1941
+ if (pin === void 0 || marker === void 0) return { kind: "absent" };
1942
+ if (input.entry.citation.quote === true) return { kind: "absent" };
1943
+ const lines = then.lines;
1944
+ let stop = marker.line;
1945
+ for (let n = marker.line + 1; n <= lines.length; n++) {
1946
+ if (bounds(lines[n - 1])) break;
1947
+ stop = n;
1948
+ }
1949
+ const starts = [marker.line];
1950
+ for (let n = marker.line + 1; n <= stop; n++) {
1951
+ const line = lines[n - 1] ?? "";
1952
+ if (line.trim() === "" || isMarkerLine(line, then.page.format)) continue;
1953
+ starts.push(n);
1954
+ }
1955
+ for (const start of starts) {
1956
+ for (let end = start; end <= stop; end++) {
1957
+ if (pinOf2(lines, { start, end }) === pin) {
1958
+ return { kind: "found", span: { start, end }, lines: lines.slice(start - 1, end) };
1959
+ }
1960
+ }
1961
+ }
1962
+ return { kind: "absent" };
1963
+ }
1964
+ async function stillWritten(input, commit, pageText) {
1965
+ const pin = input.entry.citation.claim?.integrity;
1966
+ if (pin === void 0) return { stop: true, born: true };
1967
+ const manifest = input.manifest;
1968
+ if (manifest !== void 0) {
1969
+ const shown = await input.git.showFile(commit, manifest);
1970
+ const held2 = "text" in shown && shown.text.includes(pin);
1971
+ return { stop: !held2, born: !held2 };
1972
+ }
1973
+ const held = pageText.includes(pin);
1974
+ return { stop: false, born: !held };
1975
+ }
1976
+ async function claimHistory(input) {
1977
+ const { git, path } = input;
1978
+ if (git.pageCommits === void 0) return { kind: "none" };
1979
+ if (!await git.available()) return { kind: "none" };
1980
+ const cap = input.cap ?? MAX_PAGE_COMMITS;
1981
+ const history = await git.pageCommits(path, cap);
1982
+ const { commits } = history;
1983
+ if (commits.length === 0) return { kind: "none" };
1984
+ const format = input.page.format;
1985
+ const baselineAt = (index, then, found) => {
1986
+ if (found.kind !== "found") return { kind: "none" };
1987
+ const commit = commits[index];
1988
+ if (commit === void 0) return { kind: "none" };
1989
+ return {
1990
+ kind: "baseline",
1991
+ commit: commit.sha,
1992
+ commitsSince: commits.slice(0, index).map((c) => c.subject),
1993
+ words: claimWords(found.lines, format),
1994
+ pageWords: claimWords(then.lines.slice(then.page.bodyLine - 1), format),
1995
+ lines: found.lines,
1996
+ at: spellLines(found.span)
1997
+ };
1998
+ };
1999
+ const examined = [];
2000
+ let ended = "cap";
2001
+ let born = false;
2002
+ for (let i = 0; i < commits.length; i++) {
2003
+ const commit = commits[i];
2004
+ if (commit === void 0) continue;
2005
+ const shown = await git.showFile(commit.sha, path);
2006
+ if (!("text" in shown)) {
2007
+ ended = shown.missing === "commit" ? "unavailable" : "birth";
2008
+ break;
2009
+ }
2010
+ const then = readThen(input, shown.text);
2011
+ if (then === void 0) {
2012
+ ended = "birth";
2013
+ break;
2014
+ }
2015
+ examined.push(then);
2016
+ const found = anchorHeldAt(input, then);
2017
+ if (found.kind === "found") return baselineAt(i, then, found);
2018
+ const written = await stillWritten(input, commit.sha, shown.text);
2019
+ if (written.born) born = true;
2020
+ if (written.stop) {
2021
+ ended = "birth";
2022
+ break;
2023
+ }
2024
+ }
2025
+ for (const [i, then] of examined.entries()) {
2026
+ const found = windowHeldAt(input, then);
2027
+ if (found.kind === "found") return baselineAt(i, then, found);
2028
+ }
2029
+ if (ended === "birth" || born) return { kind: "none" };
2030
+ if (ended === "unavailable") return { kind: "unavailable" };
2031
+ return history.truncated || history.shallow ? { kind: "unavailable" } : { kind: "none" };
2032
+ }
2033
+ function claimDiff(input) {
2034
+ const a = input.was.lines;
2035
+ const b = input.now.lines;
2036
+ let head = 0;
2037
+ while (head < a.length && head < b.length && a[head] === b[head]) head++;
2038
+ let tail = 0;
2039
+ while (tail < a.length - head && tail < b.length - head && a[a.length - 1 - tail] === b[b.length - 1 - tail]) {
2040
+ tail++;
2041
+ }
2042
+ const out = [
2043
+ `--- ${input.file}@${shortCommit(input.commit)}:${input.was.at}`,
2044
+ `+++ ${input.file}:${input.now.at}`
2045
+ ];
2046
+ for (const line of a.slice(0, head)) out.push(` ${line}`);
2047
+ for (const line of a.slice(head, a.length - tail)) out.push(`-${line}`);
2048
+ for (const line of b.slice(head, b.length - tail)) out.push(`+${line}`);
2049
+ for (const line of a.slice(a.length - tail)) out.push(` ${line}`);
2050
+ return out.join("\n");
2051
+ }
2052
+ function refineClaim(input) {
2053
+ const { claim, history, entry, page, lines } = input;
2054
+ if (history.kind === "unavailable") return { ...claim, historyAvailable: false };
2055
+ if (history.kind === "none") return claim;
2056
+ const format = page.format;
2057
+ const base = {
2058
+ ...claim,
2059
+ commitSha: history.commit,
2060
+ historyAvailable: true,
2061
+ commitsSince: history.commitsSince,
2062
+ baselineText: history.lines
2063
+ };
2064
+ const withDiff = (end, now2) => {
2065
+ const diff = claimDiff({
2066
+ file: page.file,
2067
+ commit: history.commit,
2068
+ was: { at: history.at, lines: history.lines },
2069
+ now: now2
2070
+ });
2071
+ return { ...end, diff };
2072
+ };
2073
+ if (entry.citation.quote === true) {
2074
+ const now2 = claim.text ?? [];
2075
+ const same = stripMarkers(now2, format).join("\n") === stripMarkers(history.lines, format).join("\n");
2076
+ const at2 = claim.fileLines ?? history.at;
2077
+ return withDiff(same ? { ...base, status: "reanchored" } : base, { at: at2, lines: now2 });
2078
+ }
2079
+ if (entry.citation.claim?.lines === void 0) {
2080
+ const now2 = claim.text ?? [];
2081
+ const w12 = claimWords(now2, format);
2082
+ const at2 = claim.fileLines ?? history.at;
2083
+ const held = holdsWords(w12, history.words) && holdsWords(history.pageWords, w12);
2084
+ return withDiff(held ? { ...base, status: "reanchored" } : base, { at: at2, lines: now2 });
2085
+ }
2086
+ const runs = runsHolding(lines, format, page.bodyLine, history.words);
2087
+ const [only] = runs;
2088
+ if (runs.length > 1) {
2089
+ return {
2090
+ ...claim,
2091
+ status: "moved-ambiguous",
2092
+ candidates: runs.map((span) => spellLines(toBodyLines(span, page.bodyLine))),
2093
+ candidateFileLines: runs.map(spellLines)
2094
+ };
2095
+ }
2096
+ if (only === void 0) {
2097
+ return withDiff(base, { at: claim.fileLines ?? history.at, lines: claim.text ?? [] });
2098
+ }
2099
+ const now = lines.slice(only.start - 1, only.end);
2100
+ const w1 = claimWords(now, format);
2101
+ if (!holdsWords(history.pageWords, w1)) {
2102
+ return withDiff(base, { at: claim.fileLines ?? history.at, lines: claim.text ?? [] });
2103
+ }
2104
+ return withDiff(
2105
+ {
2106
+ ...base,
2107
+ status: "reanchored",
2108
+ newLines: spellLines(toBodyLines(only, page.bodyLine)),
2109
+ newFileLines: spellLines(only)
2110
+ },
2111
+ { at: spellLines(only), lines: now }
2112
+ );
2113
+ }
2114
+
1790
2115
  // src/cite/core/classify.ts
1791
2116
  async function historyOf(git, commit, path, range, pin, key, budget) {
1792
2117
  const shown = await git.showFile(commit, path);
@@ -2437,13 +2762,37 @@ function claimMessageFor(result) {
2437
2762
  id,
2438
2763
  `the claim at ${at(where ?? "?")} now appears at lines ${listOf(claim.candidateFileLines ?? [])}.`
2439
2764
  );
2765
+ case "reanchored": {
2766
+ const since = claim.commitSha === void 0 ? "" : ` since ${short(claim.commitSha)}`;
2767
+ const to = claim.newFileLines === void 0 ? "" : `, to ${at(claim.newFileLines)}`;
2768
+ return named2(
2769
+ id,
2770
+ `the claim at ${at(where ?? "?")} was reanchored${since}${to}. Its words are unchanged.`
2771
+ );
2772
+ }
2440
2773
  case "changed":
2441
- return where === void 0 ? named2(id, "the claim has no lines and no marker names the entry, so its pin anchors nothing.") : named2(id, `the claim at ${at(where)} has changed since it was pinned.`);
2774
+ if (where === void 0) {
2775
+ return named2(
2776
+ id,
2777
+ "the claim has no lines and no marker names the entry, so its pin anchors nothing."
2778
+ );
2779
+ }
2780
+ return named2(id, `the claim at ${at(where)} has ${claimChange(claim)}`);
2442
2781
  case "current":
2443
2782
  case "skipped":
2444
2783
  return "";
2445
2784
  }
2446
2785
  }
2786
+ function claimChange(claim) {
2787
+ if (claim.historyAvailable === false) {
2788
+ return "changed since it was pinned (history unavailable; fetch-depth: 0).";
2789
+ }
2790
+ if (claim.commitSha === void 0) return "changed since it was pinned.";
2791
+ const at2 = short(claim.commitSha);
2792
+ const since = claim.commitsSince ?? [];
2793
+ const count = since.length === 0 ? "uncommitted" : plural(since.length, "commit");
2794
+ return `changed since ${at2}, ${count}.`;
2795
+ }
2447
2796
  function misplacedMessageFor(id, marker) {
2448
2797
  const place = marker.block ? `above the block at line ${String(marker.place)}` : `above line ${String(marker.place)}`;
2449
2798
  return named2(
@@ -2656,6 +3005,7 @@ async function checkCitations(page, opts) {
2656
3005
  const read = readPage(page.file, page.content, readOptions);
2657
3006
  const severity = resolveSeverity(opts.severity);
2658
3007
  const client = opts.gitClient ?? gitClient(opts.root);
3008
+ const pageGit = opts.pageGitClient ?? (opts.pageRoot === void 0 || opts.pageRoot === opts.root ? client : gitClient(opts.pageRoot));
2659
3009
  const checkSources = opts.checkSources !== false;
2660
3010
  const lines = splitLines(read.content);
2661
3011
  const results = [];
@@ -2679,7 +3029,10 @@ async function checkCitations(page, opts) {
2679
3029
  const misplacedAt = new Map(misplaced.map((found) => [found.line, found]));
2680
3030
  for (const entry of read.citations) {
2681
3031
  const split = entry.marker === void 0 ? void 0 : misplacedAt.get(entry.marker.line);
2682
- const claim = claimEnd(read, entry, lines, split);
3032
+ const claim = await withClaimHistory(
3033
+ { page: read, entry, claim: claimEnd(read, entry, lines, split), lines },
3034
+ { path: read.file, git: pageGit, ...opts.pageCommitCap === void 0 ? {} : { cap: opts.pageCommitCap }, ...opts.owned === void 0 ? {} : { manifest: opts.owned.file } }
3035
+ );
2683
3036
  const source = classifyOpts === void 0 ? skippedSource(entry) : await classifyCitation(entry, classifyOpts);
2684
3037
  const result = {
2685
3038
  citation: entry.citation,
@@ -2731,8 +3084,15 @@ async function checkCitations(page, opts) {
2731
3084
  }
2732
3085
  }
2733
3086
  findings.push(...findingsFor(results, severity));
2734
- const wantsHistory = checkSources && read.citations.some(({ citation }) => citation.source["commit-sha"] !== void 0);
2735
- if (wantsHistory && !await client.available()) notices.push(GIT_UNAVAILABLE_HISTORY);
3087
+ const wantsSourceHistory = checkSources && read.citations.some(({ citation }) => citation.source["commit-sha"] !== void 0);
3088
+ const wantsClaimHistory = results.some((r) => r.claim?.status === "changed");
3089
+ if (wantsSourceHistory && !await client.available()) notices.push(GIT_UNAVAILABLE_HISTORY);
3090
+ else if (wantsClaimHistory && !await pageGit.available()) {
3091
+ notices.push(GIT_UNAVAILABLE_HISTORY);
3092
+ }
3093
+ if (results.some((r) => r.claim?.historyAvailable === false)) {
3094
+ notices.push(PAGE_HISTORY_UNAVAILABLE);
3095
+ }
2736
3096
  const unavailable = results.find((r) => r.source.historyAvailable === false);
2737
3097
  if (unavailable?.source.commitSha !== void 0) {
2738
3098
  notices.push(
@@ -2752,6 +3112,14 @@ async function checkCitations(page, opts) {
2752
3112
  notices
2753
3113
  };
2754
3114
  }
3115
+ async function withClaimHistory(now, read) {
3116
+ const { claim } = now;
3117
+ if (claim === null || claim.status !== "changed") return claim;
3118
+ if (read.path === STDIN_LABEL) return claim;
3119
+ const input = { page: now.page, entry: now.entry, claim, ...read };
3120
+ const history = await claimHistory(input);
3121
+ return refineClaim({ ...input, lines: now.lines, history });
3122
+ }
2755
3123
  function skippedSource(entry) {
2756
3124
  const { source } = entry.citation;
2757
3125
  const out = { src: spellSource(source), status: "skipped" };
@@ -3090,12 +3458,15 @@ async function prepareRun(opts, action, verb, sources = {}) {
3090
3458
  });
3091
3459
  assertNonEmpty({ files, inputs: fileInputs, usingStdin, allowEmpty, exclude, exts, gitignoreSkipped, action });
3092
3460
  const git = opts.gitClient ?? gitClient(run3.root);
3461
+ const pageGit = opts.pageGitClient ?? (run3.base === run3.root ? git : gitClient(run3.base));
3093
3462
  const pageOptions = {
3094
3463
  root: run3.root,
3095
3464
  checkSources,
3096
3465
  key: run3.key,
3097
3466
  severity: config?.severity,
3098
- gitClient: git
3467
+ gitClient: git,
3468
+ pageRoot: run3.base,
3469
+ pageGitClient: pageGit
3099
3470
  };
3100
3471
  if (checkSources) pageOptions.sourceIndex = await sourceIndexFor(run3.root, git);
3101
3472
  const sidecars2 = await sidecarsFor(run3);
@@ -3721,6 +4092,12 @@ function settles(plan) {
3721
4092
  return "marker-misplaced";
3722
4093
  case "claim-reanchored":
3723
4094
  return "claim-moved";
4095
+ case "claim-words-held":
4096
+ return "claim-reanchored";
4097
+ // A refused claim leaves nothing written, but its finding is the row the
4098
+ // refusal prints, so it is not also reported as skipped.
4099
+ case "claim-replaced":
4100
+ return "claim-changed";
3724
4101
  // A shifted entry was `current`, so it had no finding to settle.
3725
4102
  case "claim-shifted":
3726
4103
  return "";
@@ -3734,6 +4111,15 @@ function apply(content, format, plan) {
3734
4111
  return spliceEntryField(content, format, index, ["claim", "lines"], plan.lines);
3735
4112
  case "claim-reanchored":
3736
4113
  return spliceEntryField(content, format, index, ["claim", "integrity"], plan.pin);
4114
+ case "claim-words-held": {
4115
+ let out = spliceEntryField(content, format, index, ["claim", "integrity"], plan.pin);
4116
+ if (plan.lines !== void 0) {
4117
+ out = spliceEntryField(out, format, index, ["claim", "lines"], plan.lines);
4118
+ }
4119
+ return out;
4120
+ }
4121
+ // Nothing is written for a refused claim; the report is the whole of it.
4122
+ case "claim-replaced":
3737
4123
  // The move is a page rewrite, applied to the whole page before any splice.
3738
4124
  case "marker-moved":
3739
4125
  return content;
@@ -3782,6 +4168,15 @@ function applyToEntry(entry, plan) {
3782
4168
  claim.integrity = plan.pin;
3783
4169
  return true;
3784
4170
  }
4171
+ case "claim-words-held": {
4172
+ const claim = end("claim");
4173
+ if (claim === void 0) return false;
4174
+ claim.integrity = plan.pin;
4175
+ if (plan.lines !== void 0) claim.lines = plan.lines;
4176
+ return true;
4177
+ }
4178
+ // Nothing is written for a refused claim.
4179
+ case "claim-replaced":
3785
4180
  // The page holds the marker, so the manifest has nothing to change.
3786
4181
  case "marker-moved":
3787
4182
  return true;
@@ -3854,6 +4249,37 @@ function rewriteOf(plan) {
3854
4249
  newLines: plan.now
3855
4250
  };
3856
4251
  }
4252
+ case "claim-words-held": {
4253
+ const was = citation.claim?.integrity ?? "";
4254
+ const out = {
4255
+ ...base,
4256
+ end: "claim",
4257
+ reason: "re-anchored",
4258
+ status: "reanchored",
4259
+ from: was,
4260
+ to: plan.pin,
4261
+ fromPin: was,
4262
+ toPin: plan.pin,
4263
+ fromLines: plan.fromLines,
4264
+ toLines: plan.toLines,
4265
+ at: plan.at
4266
+ };
4267
+ if (plan.commitSha !== void 0) out.commitSha = plan.commitSha;
4268
+ return out;
4269
+ }
4270
+ case "claim-replaced":
4271
+ return {
4272
+ ...base,
4273
+ end: "claim",
4274
+ reason: "replaced",
4275
+ status: "changed",
4276
+ from: plan.pin,
4277
+ to: plan.would,
4278
+ fromPin: plan.pin,
4279
+ toPin: plan.would,
4280
+ at: plan.at,
4281
+ commitSha: plan.commitSha
4282
+ };
3857
4283
  case "claim-shifted":
3858
4284
  return {
3859
4285
  ...base,
@@ -3880,14 +4306,22 @@ function rewriteOf(plan) {
3880
4306
  ...base,
3881
4307
  end: "claim",
3882
4308
  reason: "accepted",
3883
- status: "changed",
4309
+ // A bypassed guard reads `replaced`, so the log shows that the line
4310
+ // held other text and a named accept took it anyway.
4311
+ status: plan.replaced === true ? "replaced" : "changed",
3884
4312
  from: was,
3885
4313
  to: plan.pin,
3886
4314
  fromPin: was,
3887
4315
  toPin: plan.pin,
3888
4316
  at: plan.unit.lines.start,
3889
- text: normalizeWhitespace(plan.unit.text.join("\n"))
4317
+ text: quoted(plan.unit.text)
3890
4318
  };
4319
+ const stored = plan.result.claim?.fileLines;
4320
+ const now = spellLines(plan.unit.lines);
4321
+ if (stored !== void 0 && stored !== now) {
4322
+ out.fromLines = stored;
4323
+ out.toLines = now;
4324
+ }
3891
4325
  const markerLine = plan.markerLine ?? (plan.result.anchor === "marker" ? plan.result.markerLine : void 0);
3892
4326
  if (markerLine !== void 0) out.markerLine = markerLine;
3893
4327
  return out;
@@ -3910,6 +4344,18 @@ function rewriteOf(plan) {
3910
4344
  }
3911
4345
  }
3912
4346
  }
4347
+ function replacementAt(claim, text, format) {
4348
+ const was = claim.baselineText;
4349
+ const commit = claim.commitSha;
4350
+ if (was === void 0 || commit === void 0) return void 0;
4351
+ if (sharesSentence(claimWords(was, format), claimWords(text, format))) return void 0;
4352
+ return commit;
4353
+ }
4354
+ var QUOTE_CAP = 200;
4355
+ function quoted(text) {
4356
+ const all = normalizeWhitespace(text.join("\n"));
4357
+ return all.length <= QUOTE_CAP ? all : `${all.slice(0, QUOTE_CAP)}\u2026`;
4358
+ }
3913
4359
  function named3(id, text) {
3914
4360
  return id === void 0 ? text : `${id}: ${text}`;
3915
4361
  }
@@ -4064,6 +4510,25 @@ async function runUpdate(opts) {
4064
4510
  });
4065
4511
  }
4066
4512
  }
4513
+ if (result.anchor !== "marker" && claim !== null && claim.status === "reanchored" && claim.newLines !== void 0) {
4514
+ const at2 = parseLines(claim.newLines);
4515
+ const file = at2 === void 0 ? void 0 : toFileLines(at2, page.bodyLine);
4516
+ const pin = file === void 0 ? void 0 : pinOfLines(lines, file);
4517
+ const to = file === void 0 ? void 0 : { start: lineNow(file.start), end: lineNow(file.end) };
4518
+ if (file !== void 0 && to !== void 0 && pin !== void 0 && to.end - to.start === file.end - file.start) {
4519
+ const plan = {
4520
+ kind: "claim-words-held",
4521
+ result,
4522
+ pin,
4523
+ at: to.start,
4524
+ fromLines: claim.fileLines ?? "",
4525
+ toLines: spellLines(to),
4526
+ lines: lineSpec(toBodyLines(to, page.bodyLine))
4527
+ };
4528
+ if (claim.commitSha !== void 0) plan.commitSha = claim.commitSha;
4529
+ out.push(plan);
4530
+ }
4531
+ }
4067
4532
  if (result.source.status === "moved" && result.source.newLines !== void 0) {
4068
4533
  const at2 = parseLines(result.source.newLines);
4069
4534
  if (at2 !== void 0 && result.source.newSrc !== void 0) {
@@ -4085,15 +4550,28 @@ async function runUpdate(opts) {
4085
4550
  why: `Not re-pinned: the ${unit.kind} ${wide}.`
4086
4551
  });
4087
4552
  } else if (unit !== void 0 && pin !== void 0 && (!wantsBlock || unit.kind === "block")) {
4088
- const plan = { kind: "claim-accepted", result, unit, pin };
4089
- if (entry.citation.claim?.lines !== void 0) {
4090
- const body = toBodyLines(unit.lines, page.bodyLine);
4091
- const recorded = parseLines(entry.citation.claim.lines);
4092
- if (recorded === void 0 || recorded.start !== body.start || recorded.end !== body.end) {
4093
- plan.lines = lineSpec(body);
4553
+ const replaced = replacementAt(claim, unit.text, page.format);
4554
+ if (replaced !== void 0 && only === void 0) {
4555
+ out.push({
4556
+ kind: "claim-replaced",
4557
+ result,
4558
+ at: unit.lines.start,
4559
+ commitSha: replaced,
4560
+ pin: entry.citation.claim?.integrity ?? "",
4561
+ would: pin
4562
+ });
4563
+ } else {
4564
+ const plan = { kind: "claim-accepted", result, unit, pin };
4565
+ if (replaced !== void 0) plan.replaced = true;
4566
+ if (entry.citation.claim?.lines !== void 0) {
4567
+ const body = toBodyLines(unit.lines, page.bodyLine);
4568
+ const recorded = parseLines(entry.citation.claim.lines);
4569
+ if (recorded === void 0 || recorded.start !== body.start || recorded.end !== body.end) {
4570
+ plan.lines = lineSpec(body);
4571
+ }
4094
4572
  }
4573
+ out.push(plan);
4095
4574
  }
4096
- out.push(plan);
4097
4575
  }
4098
4576
  }
4099
4577
  if (result.source.status === "changed" || result.source.status === "never-true") {
@@ -4127,6 +4605,7 @@ async function runUpdate(opts) {
4127
4605
  });
4128
4606
  const lines = splitLines(content);
4129
4607
  const rewritten2 = [];
4608
+ const refused = [];
4130
4609
  const settled = /* @__PURE__ */ new Set();
4131
4610
  const declined = /* @__PURE__ */ new Map();
4132
4611
  const markers = decideMarkers({ page, report, lines, accept, only });
@@ -4165,6 +4644,7 @@ async function runUpdate(opts) {
4165
4644
  const now = anchoredNow(after, format, afterLines, lineNow(marker.line), quote);
4166
4645
  const status = result.claim.status;
4167
4646
  if (now !== void 0 && now.pin !== recorded) {
4647
+ const unitText2 = afterLines.slice(now.span.start - 1, now.span.end);
4168
4648
  if (status === "moved" || status === "current" && move !== void 0) {
4169
4649
  plans.push({
4170
4650
  kind: "claim-reanchored",
@@ -4173,6 +4653,17 @@ async function runUpdate(opts) {
4173
4653
  held: result.claim.fileLines ?? "",
4174
4654
  now: spellLines(now.span)
4175
4655
  });
4656
+ } else if (status === "reanchored") {
4657
+ const held = {
4658
+ kind: "claim-words-held",
4659
+ result,
4660
+ pin: now.pin,
4661
+ at: now.span.start,
4662
+ fromLines: result.claim.fileLines ?? "",
4663
+ toLines: spellLines(now.span)
4664
+ };
4665
+ if (result.claim.commitSha !== void 0) held.commitSha = result.claim.commitSha;
4666
+ plans.push(held);
4176
4667
  } else if (status === "changed" && accept) {
4177
4668
  const kind = quote ? "block" : "paragraph";
4178
4669
  const wide = tooWide(now.span);
@@ -4182,17 +4673,24 @@ async function runUpdate(opts) {
4182
4673
  why: `Not re-pinned: the ${kind} ${wide}.`
4183
4674
  });
4184
4675
  } else {
4185
- plans.push({
4186
- kind: "claim-accepted",
4187
- result,
4188
- pin: now.pin,
4189
- markerLine: lineNow(marker.line),
4190
- unit: {
4191
- lines: now.span,
4192
- kind,
4193
- text: afterLines.slice(now.span.start - 1, now.span.end)
4676
+ const replaced = replacementAt(result.claim, unitText2, format);
4677
+ plans.push(
4678
+ replaced === void 0 || only !== void 0 ? {
4679
+ kind: "claim-accepted",
4680
+ result,
4681
+ pin: now.pin,
4682
+ markerLine: lineNow(marker.line),
4683
+ unit: { lines: now.span, kind, text: unitText2 },
4684
+ ...replaced === void 0 ? {} : { replaced: true }
4685
+ } : {
4686
+ kind: "claim-replaced",
4687
+ result,
4688
+ at: now.span.start,
4689
+ commitSha: replaced,
4690
+ pin: recorded,
4691
+ would: now.pin
4194
4692
  }
4195
- });
4693
+ );
4196
4694
  }
4197
4695
  }
4198
4696
  }
@@ -4217,6 +4715,11 @@ async function runUpdate(opts) {
4217
4715
  }
4218
4716
  }
4219
4717
  for (const plan of plans) {
4718
+ if (plan.kind === "claim-replaced") {
4719
+ refused.push(rewriteOf(plan));
4720
+ settled.add(`${String(result.origin.index)}\0${settles(plan)}`);
4721
+ continue;
4722
+ }
4220
4723
  if (plan.kind === "marker-moved") {
4221
4724
  } else if (result.origin.kind === "manifest") {
4222
4725
  const held = entries?.[result.origin.index];
@@ -4273,7 +4776,7 @@ async function runUpdate(opts) {
4273
4776
  }
4274
4777
  writes.record(path, label, content);
4275
4778
  }
4276
- const out = { file: label, rewritten: rewritten2, skipped: skipped2, diff, written };
4779
+ const out = { file: label, rewritten: rewritten2, refused, skipped: skipped2, diff, written };
4277
4780
  if (path === void 0) out.content = after;
4278
4781
  pages.push(out);
4279
4782
  return report;
@@ -4303,8 +4806,10 @@ async function runUpdate(opts) {
4303
4806
  );
4304
4807
  sayNotices(reports, opts.onNotice, reminted && !await git.available() ? [GIT_UNAVAILABLE_COMMIT] : []);
4305
4808
  const rewritten = pages.reduce((n, page) => n + citationsIn(page.rewritten), 0);
4306
- const skipped = pages.reduce((n, page) => n + page.skipped.length, 0);
4307
- const undone = pages.some((page) => page.skipped.some((finding2) => finding2.severity === "error"));
4809
+ const skipped = pages.reduce((n, page) => n + page.skipped.length + page.refused.length, 0);
4810
+ const undone = pages.some(
4811
+ (page) => page.refused.length > 0 || page.skipped.some((finding2) => finding2.severity === "error")
4812
+ );
4308
4813
  return {
4309
4814
  pages,
4310
4815
  rewritten,
@@ -4505,11 +5010,27 @@ function claimColumn(result) {
4505
5010
  status = `moved, ${plural2(at2.length, "candidate")} (${at2.join(", ")})`;
4506
5011
  break;
4507
5012
  }
5013
+ case "reanchored": {
5014
+ const since = claim.commitSha === void 0 ? "" : ` since ${shortCommit(claim.commitSha)}`;
5015
+ const to = claim.newFileLines === void 0 ? "" : ` -> :${claim.newFileLines}`;
5016
+ status = `reanchored${since}${to}`;
5017
+ break;
5018
+ }
5019
+ case "changed":
5020
+ status = changedText(claim);
5021
+ break;
4508
5022
  default:
4509
5023
  status = claim.status;
4510
5024
  }
4511
5025
  return where === "" ? status : `${where} ${status}`;
4512
5026
  }
5027
+ function changedText(claim) {
5028
+ if (claim.historyAvailable === false) return "changed (history unavailable; fetch-depth: 0)";
5029
+ if (claim.commitSha === void 0) return "changed";
5030
+ const since = claim.commitsSince ?? [];
5031
+ const count = since.length === 0 ? "uncommitted" : plural2(since.length, "commit");
5032
+ return `changed since ${shortCommit(claim.commitSha)}, ${count}`;
5033
+ }
4513
5034
  function sourceColumn(result, opts, dim) {
4514
5035
  const { source } = result;
4515
5036
  const src = shortSrc(source.src);
@@ -4530,10 +5051,19 @@ function diffLines(result, dim) {
4530
5051
  return out;
4531
5052
  }
4532
5053
  function claimLines(result, dim) {
4533
- const text = result.claim?.text ?? [];
4534
- const shown = text.slice(0, DIFF_LINE_CAP);
5054
+ const claim = result.claim;
5055
+ const diff = claim?.diff;
5056
+ if (claim === null || diff === void 0 || diff === "") {
5057
+ return capped(claim?.text ?? [], dim);
5058
+ }
5059
+ const out = [];
5060
+ for (const subject of claim.commitsSince ?? []) out.push(dim(` ${subject}`));
5061
+ return [...out, ...capped(diff.split(/\r?\n/), dim)];
5062
+ }
5063
+ function capped(lines, dim) {
5064
+ const shown = lines.slice(0, DIFF_LINE_CAP);
4535
5065
  const out = shown.map((line) => dim(` ${line}`));
4536
- const more = text.length - shown.length;
5066
+ const more = lines.length - shown.length;
4537
5067
  if (more > 0) out.push(dim(` \u2026 (${plural2(more, "more line")})`));
4538
5068
  return out;
4539
5069
  }
@@ -4598,7 +5128,9 @@ function renderCheckPretty(run3, opts) {
4598
5128
  }
4599
5129
  if (opts.showDiff) {
4600
5130
  if (own.some((f) => f.rule === "source-changed")) under.push(...diffLines(result, c.dim));
4601
- if (own.some((f) => f.rule === "claim-changed")) under.push(...claimLines(result, c.dim));
5131
+ if (own.some((f) => f.rule === "claim-changed" || f.rule === "claim-reanchored")) {
5132
+ under.push(...claimLines(result, c.dim));
5133
+ }
4602
5134
  }
4603
5135
  const forgivenEnd = own.length > 0 && live.length === 0 ? c.dim(" (baselined)") : "";
4604
5136
  rows.push({
@@ -4672,6 +5204,18 @@ function widening(held, now) {
4672
5204
  if (parts.length === 0) return ", which held a marker line";
4673
5205
  return `, ${parts.join(" and ")} newly pinned`;
4674
5206
  }
5207
+ function widened(rewrite) {
5208
+ return rewrite.fromLines !== void 0 && rewrite.toLines !== void 0 && rewrite.fromLines !== rewrite.toLines;
5209
+ }
5210
+ function movedSpan(rewrite) {
5211
+ if (widened(rewrite)) return `lines ${rewrite.fromLines ?? ""} -> ${rewrite.toLines ?? ""}`;
5212
+ const at2 = rewrite.toLines ?? rewrite.fromLines ?? String(rewrite.at ?? 0);
5213
+ return `at ${spellAtSpec(at2)}`;
5214
+ }
5215
+ function refusalLine(rewrite) {
5216
+ const at2 = shortCommit(rewrite.commitSha ?? "");
5217
+ return `claim at ${spellAtSpec(String(rewrite.at ?? 0))} skipped: that line now holds different text than the claim at ${at2}. Re-add it with cite add.`;
5218
+ }
4675
5219
  function rewriteLine(rewrite) {
4676
5220
  const word = rewrite.from.includes("-") ? "lines" : "line";
4677
5221
  const status = rewrite.status === "never-true" ? "never true" : rewrite.status;
@@ -4681,6 +5225,10 @@ function rewriteLine(rewrite) {
4681
5225
  if (rewrite.reason === "shifted") {
4682
5226
  return `claim ${word} ${rewrite.from} -> ${rewrite.to} (shifted by a marker)`;
4683
5227
  }
5228
+ if (rewrite.reason === "re-anchored" && rewrite.status === "reanchored") {
5229
+ const since = rewrite.commitSha === void 0 ? "" : ` since ${shortCommit(rewrite.commitSha)}`;
5230
+ return `claim ${movedSpan(rewrite)} re-pinned (reanchored; words unchanged${since})`;
5231
+ }
4684
5232
  if (rewrite.reason === "re-anchored") {
4685
5233
  const held = rewrite.lines ?? "";
4686
5234
  const now = rewrite.newLines ?? "";
@@ -4690,6 +5238,9 @@ function rewriteLine(rewrite) {
4690
5238
  return rewrite.end === "claim" ? `claim ${word} ${rewrite.from} -> ${rewrite.to} (moved)` : `source ${shortSrc(rewrite.from)} -> ${shortSrc(rewrite.to)} (moved)`;
4691
5239
  }
4692
5240
  if (rewrite.end === "claim") {
5241
+ if (widened(rewrite)) {
5242
+ return `claim ${movedSpan(rewrite)} re-pinned (${status}; now "${rewrite.text ?? ""}")`;
5243
+ }
4693
5244
  const where = rewrite.markerLine === void 0 ? `line ${String(rewrite.at ?? 0)}` : `marker line ${String(rewrite.markerLine)}`;
4694
5245
  return `claim at ${where} re-pinned (${status}; now "${rewrite.text ?? ""}")`;
4695
5246
  }
@@ -4711,6 +5262,10 @@ function renderUpdatePretty(run3, opts) {
4711
5262
  const label = rewrite.id ?? `#${String(rewrite.index)}`;
4712
5263
  lines.push(`${page.file}: ${c.cyan(label)} ${rewriteLine(rewrite)}`);
4713
5264
  }
5265
+ for (const rewrite of page.refused) {
5266
+ const label = rewrite.id ?? `#${String(rewrite.index)}`;
5267
+ lines.push(`${page.file}: ${c.cyan(label)} ${refusalLine(rewrite)}`);
5268
+ }
4714
5269
  for (const finding2 of page.skipped) {
4715
5270
  const mark = severityMark(finding2.severity, c);
4716
5271
  lines.push(
@@ -4799,6 +5354,10 @@ function publicCitation(result) {
4799
5354
  if (result.claim.fileLines !== void 0) claim.fileLines = result.claim.fileLines;
4800
5355
  if (result.claim.newLines !== void 0) claim.newLines = result.claim.newLines;
4801
5356
  if (result.claim.candidates !== void 0) claim.candidates = result.claim.candidates;
5357
+ if (result.claim.commitSha !== void 0) claim.commitSha = result.claim.commitSha;
5358
+ if (result.claim.historyAvailable !== void 0) {
5359
+ claim.historyAvailable = result.claim.historyAvailable;
5360
+ }
4802
5361
  }
4803
5362
  return {
4804
5363
  ...result.citation.id === void 0 ? {} : { id: result.citation.id },
@@ -4819,9 +5378,11 @@ function renderRemoveJson(run3) {
4819
5378
  return JSON.stringify(run3, null, 2);
4820
5379
  }
4821
5380
  function renderUpdateJson(run3) {
5381
+ const strip = (rows) => rows.map(({ markerLine: _pretty, ...rewrite }) => rewrite);
4822
5382
  const pages = run3.pages.map((page) => ({
4823
5383
  ...page,
4824
- rewritten: page.rewritten.map(({ markerLine: _pretty, ...rewrite }) => rewrite)
5384
+ rewritten: strip(page.rewritten),
5385
+ refused: strip(page.refused)
4825
5386
  }));
4826
5387
  return JSON.stringify({ ...run3, pages }, null, 2);
4827
5388
  }
@@ -5315,4 +5876,4 @@ export {
5315
5876
  runKeyRotate,
5316
5877
  runKeySet
5317
5878
  };
5318
- //# sourceMappingURL=chunk-NFCH7HCA.js.map
5879
+ //# sourceMappingURL=chunk-TQUTQD7J.js.map