@inerrata-corporation/errata 2.0.13-dev.2998 → 2.0.13-dev.3054
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/consolidate-worker.mjs +141 -1
- package/errata.mjs +1046 -240
- package/package.json +1 -1
- package/pass-worker.mjs +183 -3
package/errata.mjs
CHANGED
|
@@ -15488,6 +15488,370 @@ var init_zod = __esm({
|
|
|
15488
15488
|
}
|
|
15489
15489
|
});
|
|
15490
15490
|
|
|
15491
|
+
// ../../packages/shared/src/history-text.ts
|
|
15492
|
+
function looksLikeSecretValue(raw2, quoted) {
|
|
15493
|
+
if (raw2.includes("${") || raw2.includes("{{") || raw2.includes("%(")) return false;
|
|
15494
|
+
if (raw2.startsWith("[redacted:")) return false;
|
|
15495
|
+
if (quoted) return raw2.length > 0;
|
|
15496
|
+
const lower = raw2.toLowerCase();
|
|
15497
|
+
if (ASSIGNMENT_STOPWORDS.has(lower)) return false;
|
|
15498
|
+
if (!/^[A-Za-z0-9+/=_-]{8,}$/.test(raw2)) return false;
|
|
15499
|
+
if (/\d/.test(raw2)) return true;
|
|
15500
|
+
if (raw2.length >= 12) return true;
|
|
15501
|
+
return /[a-z]/.test(raw2) && /[A-Z]/.test(raw2);
|
|
15502
|
+
}
|
|
15503
|
+
function applyRule(text, rule, removed) {
|
|
15504
|
+
let count = 0;
|
|
15505
|
+
const out2 = text.replace(rule.re, (...args2) => {
|
|
15506
|
+
const m = args2.slice(0, -2);
|
|
15507
|
+
const r = rule.replace(m);
|
|
15508
|
+
if (r === null) return m[0];
|
|
15509
|
+
const marker = r.indexOf(REDACTED_CREDENTIAL);
|
|
15510
|
+
if (removed && marker >= 0) {
|
|
15511
|
+
const prefix = r.slice(0, marker), suffix = r.slice(marker + REDACTED_CREDENTIAL.length);
|
|
15512
|
+
if (m[0].startsWith(prefix) && m[0].endsWith(suffix)) {
|
|
15513
|
+
const literal2 = m[0].slice(prefix.length, m[0].length - suffix.length);
|
|
15514
|
+
if (literal2 && !literal2.includes("[redacted:")) removed.add(literal2);
|
|
15515
|
+
}
|
|
15516
|
+
}
|
|
15517
|
+
count += 1;
|
|
15518
|
+
return r;
|
|
15519
|
+
});
|
|
15520
|
+
return { text: out2, count };
|
|
15521
|
+
}
|
|
15522
|
+
function scrubHistoryText(text) {
|
|
15523
|
+
return scrubText(text);
|
|
15524
|
+
}
|
|
15525
|
+
function scrubText(text, removed) {
|
|
15526
|
+
let out2 = text;
|
|
15527
|
+
let credentials = 0;
|
|
15528
|
+
for (const rule of CREDENTIAL_RULES) {
|
|
15529
|
+
const r = applyRule(out2, rule, removed);
|
|
15530
|
+
out2 = r.text;
|
|
15531
|
+
credentials += r.count;
|
|
15532
|
+
}
|
|
15533
|
+
let emails = 0;
|
|
15534
|
+
out2 = out2.replace(EMAIL_RE, () => {
|
|
15535
|
+
emails += 1;
|
|
15536
|
+
return REDACTED_EMAIL;
|
|
15537
|
+
});
|
|
15538
|
+
return { text: out2, credentials, emails };
|
|
15539
|
+
}
|
|
15540
|
+
function scrubHistoryValue(value) {
|
|
15541
|
+
const removed = /* @__PURE__ */ new Set();
|
|
15542
|
+
const visit = (input) => {
|
|
15543
|
+
if (typeof input === "string") return scrubText(input, removed).text;
|
|
15544
|
+
if (Array.isArray(input)) return input.map(visit);
|
|
15545
|
+
if (input && typeof input === "object") return Object.fromEntries(Object.entries(input).map(([key, item]) => {
|
|
15546
|
+
const field = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
15547
|
+
const credentialField = /^(?:token|credential|credentials|pwd|passwd|passphrase)$/.test(field) || /(?:password|secret|secretkey|apikey|accesskey|privatekey|authkey|accesstoken|refreshtoken)$/.test(field);
|
|
15548
|
+
if (typeof item === "string" && credentialField) {
|
|
15549
|
+
const assignment = `${key}: ${JSON.stringify(item)}`;
|
|
15550
|
+
if (scrubText(assignment, removed).credentials > 0) return [key, REDACTED_CREDENTIAL];
|
|
15551
|
+
}
|
|
15552
|
+
return [key, visit(item)];
|
|
15553
|
+
}));
|
|
15554
|
+
return input;
|
|
15555
|
+
};
|
|
15556
|
+
const safe = visit(value);
|
|
15557
|
+
if (!removed.size) return safe;
|
|
15558
|
+
const escaped = [...removed].sort((a, b) => b.length - a.length).map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
15559
|
+
const literals = new RegExp(`(?<![\\p{L}\\p{N}_])(?:${escaped.join("|")})(?![\\p{L}\\p{N}_])`, "gu");
|
|
15560
|
+
const clear = (input) => typeof input === "string" ? input.replace(literals, REDACTED_CREDENTIAL) : Array.isArray(input) ? input.map(clear) : input && typeof input === "object" ? Object.fromEntries(Object.entries(input).map(([k, v]) => [k, clear(v)])) : input;
|
|
15561
|
+
return clear(safe);
|
|
15562
|
+
}
|
|
15563
|
+
var HISTORY_SCRUBBER_VERSION, REDACTED_CREDENTIAL, REDACTED_EMAIL, cred, ASSIGNMENT_STOPWORDS, CREDENTIAL_RULES, EMAIL_RE;
|
|
15564
|
+
var init_history_text = __esm({
|
|
15565
|
+
"../../packages/shared/src/history-text.ts"() {
|
|
15566
|
+
"use strict";
|
|
15567
|
+
HISTORY_SCRUBBER_VERSION = "history-scrub-3";
|
|
15568
|
+
REDACTED_CREDENTIAL = "[redacted:credential]";
|
|
15569
|
+
REDACTED_EMAIL = "[redacted:email]";
|
|
15570
|
+
cred = () => REDACTED_CREDENTIAL;
|
|
15571
|
+
ASSIGNMENT_STOPWORDS = /* @__PURE__ */ new Set([
|
|
15572
|
+
"string",
|
|
15573
|
+
"boolean",
|
|
15574
|
+
"number",
|
|
15575
|
+
"required",
|
|
15576
|
+
"optional",
|
|
15577
|
+
"undefined",
|
|
15578
|
+
"unknown",
|
|
15579
|
+
"function",
|
|
15580
|
+
"process",
|
|
15581
|
+
"request",
|
|
15582
|
+
"response",
|
|
15583
|
+
"password",
|
|
15584
|
+
"secret",
|
|
15585
|
+
"token",
|
|
15586
|
+
"tokens",
|
|
15587
|
+
"credential",
|
|
15588
|
+
"credentials",
|
|
15589
|
+
"bearer",
|
|
15590
|
+
"basic",
|
|
15591
|
+
"example",
|
|
15592
|
+
"redacted",
|
|
15593
|
+
"nullable",
|
|
15594
|
+
"readonly",
|
|
15595
|
+
"override",
|
|
15596
|
+
"abstract",
|
|
15597
|
+
"interface",
|
|
15598
|
+
"constant",
|
|
15599
|
+
"variable",
|
|
15600
|
+
"property",
|
|
15601
|
+
"parameter",
|
|
15602
|
+
"argument",
|
|
15603
|
+
"callback",
|
|
15604
|
+
"promise",
|
|
15605
|
+
"settings",
|
|
15606
|
+
"options",
|
|
15607
|
+
"default",
|
|
15608
|
+
"disabled",
|
|
15609
|
+
"enabled",
|
|
15610
|
+
"internal",
|
|
15611
|
+
"external",
|
|
15612
|
+
"protected",
|
|
15613
|
+
"provided",
|
|
15614
|
+
"resolved",
|
|
15615
|
+
"rejected",
|
|
15616
|
+
"expected",
|
|
15617
|
+
"received",
|
|
15618
|
+
"salt",
|
|
15619
|
+
"hash",
|
|
15620
|
+
"hashed",
|
|
15621
|
+
"hashing",
|
|
15622
|
+
"authentication",
|
|
15623
|
+
"field",
|
|
15624
|
+
"format"
|
|
15625
|
+
]);
|
|
15626
|
+
CREDENTIAL_RULES = [
|
|
15627
|
+
// Human-written seed/reset notes omit assignment punctuation: password `…`
|
|
15628
|
+
// or password (…). Preserve names of fields and hash components.
|
|
15629
|
+
{
|
|
15630
|
+
re: /\b((?:password|passwd|passphrase|pwd)\s+)(["'`(])([^\s"'`,;)}\]]+)(["'`)])/gi,
|
|
15631
|
+
replace: (m) => !ASSIGNMENT_STOPWORDS.has((m[3] ?? "").toLowerCase()) && looksLikeSecretValue(m[3] ?? "", true) ? `${m[1]}${m[2]}${REDACTED_CREDENTIAL}${m[4]}` : null
|
|
15632
|
+
},
|
|
15633
|
+
// "with SeedValue42! credentials" and "with SeedValue42!/seeded account".
|
|
15634
|
+
// Require mixed-case letters plus a digit, or a password-like special char;
|
|
15635
|
+
// ordinary phrases such as "with test credentials" remain useful prose.
|
|
15636
|
+
{
|
|
15637
|
+
re: /\b(with\s+)(["'`]?)([A-Za-z0-9][A-Za-z0-9!@#$%^&*._+=?-]{7,})(["'`]?)(?=\s+credentials\b|\s*\/\s*seeded\b)/gi,
|
|
15638
|
+
replace: (m) => /[a-z]/.test(m[3]) && /[A-Z]/.test(m[3]) && /[0-9!@#$%^&*]/.test(m[3]) ? `${m[1]}${m[2]}${REDACTED_CREDENTIAL}${m[4]}` : null
|
|
15639
|
+
},
|
|
15640
|
+
// Userinfo in connection URLs must be removed before the email rule runs.
|
|
15641
|
+
{
|
|
15642
|
+
re: /\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]+):([^\s/@]+)@/gi,
|
|
15643
|
+
replace: (m) => m[2] === "[redacted" && m[3] === "credential]" ? null : `${m[1]}${REDACTED_CREDENTIAL}@`
|
|
15644
|
+
},
|
|
15645
|
+
// Seeded login prose commonly writes email/password without an assignment.
|
|
15646
|
+
{
|
|
15647
|
+
re: /(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+|\[redacted:email\])(\s*\/\s*)(["'\x60]?)([^\s"'\x60,;)}\]]+)/gi,
|
|
15648
|
+
replace: (m) => m[4]?.startsWith("[redacted:") ? null : `${m[1]}${m[2]}${m[3]}${REDACTED_CREDENTIAL}`
|
|
15649
|
+
},
|
|
15650
|
+
// Explicit natural-language passwords, including weak seeded values.
|
|
15651
|
+
{
|
|
15652
|
+
re: /\b((?:password|passwd|passphrase|pwd)\s+(?:is|was|of)\s+)(["'\x60]?)([^\s"'\x60,;)}\]]+)/gi,
|
|
15653
|
+
replace: (m) => {
|
|
15654
|
+
const value = m[3] ?? "";
|
|
15655
|
+
if (ASSIGNMENT_STOPWORDS.has(value.toLowerCase()) || value.startsWith("[redacted:") || /\$\{|\{\{|process\./.test(value)) return null;
|
|
15656
|
+
return `${m[1]}${m[2]}${REDACTED_CREDENTIAL}`;
|
|
15657
|
+
}
|
|
15658
|
+
},
|
|
15659
|
+
// Private-key blocks, including ones a diff prefixes with `+`/`-` per line
|
|
15660
|
+
// and ones the diff context cut before the END line.
|
|
15661
|
+
{
|
|
15662
|
+
re: /-----BEGIN [A-Z ]*PRIVATE KEY(?: BLOCK)?-----(?:[ \t]*\r?\n[+\- ]?[A-Za-z0-9+/=]{16,}[ \t]*)*(?:[ \t]*\r?\n[+\- ]?-----END [A-Z ]*PRIVATE KEY(?: BLOCK)?-----)?/g,
|
|
15663
|
+
replace: cred
|
|
15664
|
+
},
|
|
15665
|
+
{ re: /\b(?:AKIA|ASIA)[0-9A-Z]{16,}\b/g, replace: cred },
|
|
15666
|
+
// AWS access key id
|
|
15667
|
+
{ re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, replace: cred },
|
|
15668
|
+
{ re: /\bgh[pousr]_[A-Za-z0-9]{30,}\b/g, replace: cred },
|
|
15669
|
+
{ re: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, replace: cred },
|
|
15670
|
+
{ re: /\bxox[abeprs]-[A-Za-z0-9-]{10,}\b/g, replace: cred },
|
|
15671
|
+
// Slack
|
|
15672
|
+
{ re: /\bsk-(?:ant-)?[A-Za-z0-9_-]{20,}\b/g, replace: cred },
|
|
15673
|
+
// OpenAI / Anthropic
|
|
15674
|
+
{ re: /\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}\b/g, replace: cred },
|
|
15675
|
+
// Stripe
|
|
15676
|
+
{ re: /\brnd_[A-Za-z0-9]{20,}\b/g, replace: cred },
|
|
15677
|
+
// Render
|
|
15678
|
+
{ re: /\bnpm_[A-Za-z0-9]{36}\b/g, replace: cred },
|
|
15679
|
+
{ re: /\bAIza[0-9A-Za-z_-]{35}\b/g, replace: cred },
|
|
15680
|
+
// Google API key
|
|
15681
|
+
{ re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, replace: cred },
|
|
15682
|
+
// JWT
|
|
15683
|
+
{ re: /(?<![A-Za-z0-9])[A-Za-z0-9]{84}(?![A-Za-z0-9])/g, replace: cred },
|
|
15684
|
+
// Azure-shaped
|
|
15685
|
+
{
|
|
15686
|
+
re: /\b(Bearer|Basic|Token)(\s+)([A-Za-z0-9._~+/=-]{16,})/g,
|
|
15687
|
+
replace: (m) => `${m[1]}${m[2]}${REDACTED_CREDENTIAL}`
|
|
15688
|
+
},
|
|
15689
|
+
// Assignments after key-ish names: `password=...`, `API_KEY: "..."`,
|
|
15690
|
+
// `"client_secret": "..."`, `AWS_SECRET_ACCESS_KEY=...`, 32+ hex/base64 after
|
|
15691
|
+
// any of them. The value heuristic keeps `token: string` and
|
|
15692
|
+
// `password = process.env.X` intact.
|
|
15693
|
+
{
|
|
15694
|
+
re: /((?:[A-Za-z0-9_.-]*?)(?:password|passwd|passphrase|pwd|secret|token|api[_-]?key|apikey|access[_-]?key|private[_-]?key|auth[_-]?key|credential)(?:[A-Za-z0-9_-]*))(["']?\s*(?:=>|=|:)\s*)(["'`]?)([^\s"'`,;)}\]]+)/gi,
|
|
15695
|
+
replace: (m) => {
|
|
15696
|
+
const value = m[4] ?? "";
|
|
15697
|
+
const quote = m[3] ?? "";
|
|
15698
|
+
if (m[1]?.toLowerCase() === "credentials" && /^(include|omit|same-origin)$/.test(value)) return null;
|
|
15699
|
+
if (!looksLikeSecretValue(value, quote.length > 0)) return null;
|
|
15700
|
+
return `${m[1]}${m[2]}${quote}${REDACTED_CREDENTIAL}`;
|
|
15701
|
+
}
|
|
15702
|
+
}
|
|
15703
|
+
];
|
|
15704
|
+
EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+\b/g;
|
|
15705
|
+
}
|
|
15706
|
+
});
|
|
15707
|
+
|
|
15708
|
+
// ../../packages/shared/src/history-evidence.ts
|
|
15709
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
15710
|
+
function historyTextDigest(text) {
|
|
15711
|
+
return createHash2("sha256").update(text).digest("hex");
|
|
15712
|
+
}
|
|
15713
|
+
function historySourceBlocks(input) {
|
|
15714
|
+
const blocks = [];
|
|
15715
|
+
const add = (kind, text, commitSha, pathToken) => {
|
|
15716
|
+
const safe = scrubHistoryText(text.replace(/\r\n?/g, "\n")).text.trim();
|
|
15717
|
+
if (safe && safe !== "[truncated]") blocks.push({ id: `b${blocks.length}`, kind, commitSha, pathToken, text: safe, digest: historyTextDigest(safe) });
|
|
15718
|
+
};
|
|
15719
|
+
const narrative2 = scrubHistoryText(input.narrative.replace(/\r\n?/g, "\n")).text;
|
|
15720
|
+
if (input.narrativeSources?.length) {
|
|
15721
|
+
for (const source of input.narrativeSources) {
|
|
15722
|
+
const safe = scrubHistoryText(source.text.replace(/\r\n?/g, "\n")).text.trim();
|
|
15723
|
+
if (safe && narrative2.includes(safe)) add("narrative", safe, source.commitSha, null);
|
|
15724
|
+
}
|
|
15725
|
+
} else {
|
|
15726
|
+
add("narrative", narrative2, input.isMerge ? null : input.commitSha, null);
|
|
15727
|
+
}
|
|
15728
|
+
let token = null;
|
|
15729
|
+
let hunk = [];
|
|
15730
|
+
const flush = () => {
|
|
15731
|
+
if (hunk.some((line) => /^[+-](?![+-]{2})/.test(line))) add("diff", hunk.join("\n"), input.commitSha, token);
|
|
15732
|
+
hunk = [];
|
|
15733
|
+
};
|
|
15734
|
+
for (const line of input.diff.replace(/\r\n?/g, "\n").split("\n")) {
|
|
15735
|
+
if (line.startsWith("diff --git ")) {
|
|
15736
|
+
flush();
|
|
15737
|
+
token = /^diff --git a\/(p\d+) b\/(p\d+)$/.exec(line)?.[2] ?? null;
|
|
15738
|
+
} else if (/^@@ /.test(line)) {
|
|
15739
|
+
flush();
|
|
15740
|
+
hunk.push(line);
|
|
15741
|
+
} else if (!/^(--- |\+\+\+ |index |new file |deleted file |similarity |rename |\[truncated\])/.test(line) && token && /^[ +\-\\]/.test(line)) {
|
|
15742
|
+
hunk.push(line);
|
|
15743
|
+
}
|
|
15744
|
+
}
|
|
15745
|
+
flush();
|
|
15746
|
+
return blocks;
|
|
15747
|
+
}
|
|
15748
|
+
function resolveHistoryEvidence(selection, blocks) {
|
|
15749
|
+
const block = blocks.find((b) => b.id === selection.blockId);
|
|
15750
|
+
if (!block) return null;
|
|
15751
|
+
const quote = selection.quote.replace(/\r\n?/g, "\n");
|
|
15752
|
+
if (scrubHistoryText(quote).text !== quote) return null;
|
|
15753
|
+
let start2 = block.text.indexOf(quote);
|
|
15754
|
+
if (selection.startByte !== void 0) {
|
|
15755
|
+
const prefix = Buffer.from(block.text, "utf8").subarray(0, selection.startByte).toString("utf8");
|
|
15756
|
+
if (Buffer.byteLength(prefix, "utf8") !== selection.startByte || !block.text.startsWith(prefix)) return null;
|
|
15757
|
+
start2 = prefix.length;
|
|
15758
|
+
if (!block.text.startsWith(quote, start2)) return null;
|
|
15759
|
+
} else if (start2 < 0 || block.text.indexOf(quote, start2 + 1) !== -1) return null;
|
|
15760
|
+
const firstLine = block.text.lastIndexOf("\n", start2 - 1) + 1;
|
|
15761
|
+
const selectedLines = block.text.slice(firstLine, start2 + quote.length).split("\n");
|
|
15762
|
+
if (block.kind === "diff" && selectedLines.every((l) => l.startsWith("@@"))) return null;
|
|
15763
|
+
const signs = new Set(selectedLines.filter((l) => !l.startsWith("@@")).map((l) => l[0]));
|
|
15764
|
+
const side = block.kind === "narrative" ? "narrative" : signs.has("+") && signs.has("-") ? "mixed" : signs.has("+") ? "after" : signs.has("-") ? "before" : "context";
|
|
15765
|
+
return {
|
|
15766
|
+
...selection,
|
|
15767
|
+
quote,
|
|
15768
|
+
blockDigest: block.digest,
|
|
15769
|
+
startByte: Buffer.byteLength(block.text.slice(0, start2), "utf8"),
|
|
15770
|
+
endByte: Buffer.byteLength(block.text.slice(0, start2 + quote.length), "utf8"),
|
|
15771
|
+
sourceKind: block.kind,
|
|
15772
|
+
commitSha: block.commitSha,
|
|
15773
|
+
pathToken: block.pathToken,
|
|
15774
|
+
scrubberVersion: HISTORY_SCRUBBER_VERSION,
|
|
15775
|
+
side
|
|
15776
|
+
};
|
|
15777
|
+
}
|
|
15778
|
+
function checkHistoryCandidate(atom, blocks) {
|
|
15779
|
+
const evidence = atom.evidence.map((e) => resolveHistoryEvidence(e, blocks));
|
|
15780
|
+
if (evidence.some((e) => e === null)) return { reason: "missing-evidence", evidence: [] };
|
|
15781
|
+
const refs = evidence;
|
|
15782
|
+
if (!refs.some((e) => e.supports === "statement") || atom.rationale !== null && !refs.some((e) => e.supports === "rationale") || atom.conditions.some((_, i2) => !refs.some((e) => e.supports === "condition" && e.conditionIndex === i2)) || refs.some((e) => e.supports === "relation" || (e.supports === "condition" ? e.conditionIndex === null || e.conditionIndex >= atom.conditions.length : e.conditionIndex !== null))) {
|
|
15783
|
+
return { reason: "missing-field-evidence", evidence: [] };
|
|
15784
|
+
}
|
|
15785
|
+
if (atom.label === "Claim" !== (atom.claimKind !== null)) return { reason: "invalid-kind", evidence: [] };
|
|
15786
|
+
if (atom.anchorTokens.some((token) => !blocks.some((b) => b.kind === "diff" && b.pathToken === token)) || atom.label !== "Claim" && atom.anchorTokens.length === 0) return { reason: "invalid-anchor", evidence: [] };
|
|
15787
|
+
return { reason: "accepted", evidence: refs };
|
|
15788
|
+
}
|
|
15789
|
+
var HISTORY_EVIDENCE_SCHEMA_VERSION, HistoryAnchorSourceSchema, HistorySymbolAnchorSchema, HistoryEvidenceSelectionSchema, HistoryCandidateSchema, HistoryRelationCandidateSchema, HistoryCandidateBatchSchema, HistoryEvidenceRefSchema;
|
|
15790
|
+
var init_history_evidence = __esm({
|
|
15791
|
+
"../../packages/shared/src/history-evidence.ts"() {
|
|
15792
|
+
"use strict";
|
|
15793
|
+
init_zod();
|
|
15794
|
+
init_history_text();
|
|
15795
|
+
HISTORY_EVIDENCE_SCHEMA_VERSION = "history-evidence-1";
|
|
15796
|
+
HistoryAnchorSourceSchema = external_exports.strictObject({
|
|
15797
|
+
sourceCommitSha: external_exports.string().regex(/^[a-f0-9]{40,64}$/),
|
|
15798
|
+
commitSha: external_exports.string().regex(/^[a-f0-9]{40,64}$/),
|
|
15799
|
+
side: external_exports.enum(["before", "after"]),
|
|
15800
|
+
blockDigest: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
15801
|
+
startByte: external_exports.number().int().nonnegative(),
|
|
15802
|
+
endByte: external_exports.number().int().positive(),
|
|
15803
|
+
bodyHash: external_exports.string().regex(/^[a-f0-9]{8,64}$/).optional()
|
|
15804
|
+
}).refine((v) => v.endByte > v.startByte);
|
|
15805
|
+
HistorySymbolAnchorSchema = external_exports.object({
|
|
15806
|
+
symbolId: external_exports.string().regex(/^sym_[a-f0-9]{8,64}$/),
|
|
15807
|
+
kind: external_exports.string().max(40),
|
|
15808
|
+
/** Legacy association, never a source-revision or live validation. */
|
|
15809
|
+
contentHash: external_exports.string().regex(/^[a-f0-9]{8,64}$/).optional(),
|
|
15810
|
+
historical: HistoryAnchorSourceSchema.optional()
|
|
15811
|
+
});
|
|
15812
|
+
HistoryEvidenceSelectionSchema = external_exports.strictObject({
|
|
15813
|
+
blockId: external_exports.string().min(1).max(80),
|
|
15814
|
+
quote: external_exports.string().min(3).max(1600),
|
|
15815
|
+
supports: external_exports.enum(["statement", "condition", "rationale", "relation"]),
|
|
15816
|
+
conditionIndex: external_exports.number().int().min(0).max(7).nullable(),
|
|
15817
|
+
/** Optional exact location disambiguates repeated source lines. */
|
|
15818
|
+
startByte: external_exports.number().int().nonnegative().optional()
|
|
15819
|
+
});
|
|
15820
|
+
HistoryCandidateSchema = external_exports.strictObject({
|
|
15821
|
+
tempId: external_exports.string().regex(/^a[0-9]{1,3}$/),
|
|
15822
|
+
label: external_exports.enum(["Problem", "Solution", "RootCause", "Claim"]),
|
|
15823
|
+
statement: external_exports.string().min(10).max(2e3),
|
|
15824
|
+
claimKind: external_exports.enum(["snapshot", "decision", "constraint"]).nullable(),
|
|
15825
|
+
qualifier: external_exports.enum(["instance", "project"]),
|
|
15826
|
+
conditions: external_exports.array(external_exports.string().min(1).max(300)).max(8),
|
|
15827
|
+
rationale: external_exports.string().min(1).max(1e3).nullable(),
|
|
15828
|
+
evidence: external_exports.array(HistoryEvidenceSelectionSchema).min(1).max(12),
|
|
15829
|
+
anchorTokens: external_exports.array(external_exports.string().regex(/^p[0-9]+$/)).max(8)
|
|
15830
|
+
});
|
|
15831
|
+
HistoryRelationCandidateSchema = external_exports.strictObject({
|
|
15832
|
+
tempId: external_exports.string().regex(/^r[0-9]{1,3}$/),
|
|
15833
|
+
fromTempId: external_exports.string().regex(/^a[0-9]{1,3}$/),
|
|
15834
|
+
toTempId: external_exports.string().regex(/^a[0-9]{1,3}$/),
|
|
15835
|
+
meaning: external_exports.enum(["resolves", "mitigates", "caused-by"]),
|
|
15836
|
+
evidence: external_exports.array(HistoryEvidenceSelectionSchema).min(1).max(8)
|
|
15837
|
+
});
|
|
15838
|
+
HistoryCandidateBatchSchema = external_exports.strictObject({
|
|
15839
|
+
atoms: external_exports.array(HistoryCandidateSchema).max(32),
|
|
15840
|
+
relations: external_exports.array(HistoryRelationCandidateSchema).max(32)
|
|
15841
|
+
});
|
|
15842
|
+
HistoryEvidenceRefSchema = HistoryEvidenceSelectionSchema.extend({
|
|
15843
|
+
blockDigest: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
15844
|
+
startByte: external_exports.number().int().nonnegative(),
|
|
15845
|
+
endByte: external_exports.number().int().nonnegative(),
|
|
15846
|
+
sourceKind: external_exports.enum(["narrative", "diff"]),
|
|
15847
|
+
commitSha: external_exports.string().regex(/^[a-f0-9]{40,64}$/).nullable(),
|
|
15848
|
+
pathToken: external_exports.string().regex(/^p[0-9]+$/).nullable(),
|
|
15849
|
+
scrubberVersion: external_exports.string().max(80),
|
|
15850
|
+
side: external_exports.enum(["before", "after", "context", "mixed", "narrative"])
|
|
15851
|
+
});
|
|
15852
|
+
}
|
|
15853
|
+
});
|
|
15854
|
+
|
|
15491
15855
|
// ../../packages/shared/src/edge-rules.ts
|
|
15492
15856
|
function isValidEdge(from, type, to) {
|
|
15493
15857
|
const rule = EDGE_RULES[type];
|
|
@@ -15526,7 +15890,9 @@ var init_edge_rules = __esm({
|
|
|
15526
15890
|
// ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
|
|
15527
15891
|
TARGETS: { from: ["Exploit"], to: ["Vulnerability"] },
|
|
15528
15892
|
ENABLES: { from: ["AntiPattern"], to: ["Vulnerability"] },
|
|
15529
|
-
|
|
15893
|
+
// Partial remedies also apply to project Problems/RootCauses. Direction stays
|
|
15894
|
+
// remedy -> ailment; a mitigation must never claim complete SOLVED_BY status.
|
|
15895
|
+
MITIGATES: { from: ["Solution"], to: ["Vulnerability", "Problem", "RootCause"] },
|
|
15530
15896
|
PRESENTS: { from: ["Solution"], to: ["Problem", "Vulnerability"] },
|
|
15531
15897
|
// SOLVED_BY sources: Vulnerability (v1 comment) + Problem/RootCause
|
|
15532
15898
|
// (upstream design-problem.ts + triage.ts mint both).
|
|
@@ -15804,6 +16170,7 @@ var init_wire = __esm({
|
|
|
15804
16170
|
"../../packages/shared/src/wire.ts"() {
|
|
15805
16171
|
"use strict";
|
|
15806
16172
|
init_zod();
|
|
16173
|
+
init_history_evidence();
|
|
15807
16174
|
init_castalia();
|
|
15808
16175
|
init_edge_rules();
|
|
15809
16176
|
init_symbol_intent();
|
|
@@ -15930,6 +16297,12 @@ var init_wire = __esm({
|
|
|
15930
16297
|
attrs: external_exports.object({
|
|
15931
16298
|
confidence: external_exports.number().min(0).max(1).optional(),
|
|
15932
16299
|
extractedBy: external_exports.enum(INGEST_EXTRACTION_SOURCES).optional(),
|
|
16300
|
+
sourceSupport: external_exports.literal("supported").optional(),
|
|
16301
|
+
historicalAnchors: external_exports.array(HistoryAnchorSourceSchema).max(160).optional(),
|
|
16302
|
+
evidence: external_exports.array(HistoryEvidenceRefSchema).max(12).optional(),
|
|
16303
|
+
verificationEvidence: external_exports.array(HistoryEvidenceRefSchema).max(12).optional(),
|
|
16304
|
+
verifierBuild: external_exports.string().max(80).optional(),
|
|
16305
|
+
unitDigest: external_exports.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
15933
16306
|
/** Triage route per-context counts (T3 induction). Carried as structured data
|
|
15934
16307
|
* here; stored JSON-encoded on the Neo4j rel (`perContextJson`). */
|
|
15935
16308
|
perContext: external_exports.record(external_exports.string(), RouteContextCountWireSchema).optional(),
|
|
@@ -16740,6 +17113,178 @@ var init_manifests = __esm({
|
|
|
16740
17113
|
}
|
|
16741
17114
|
});
|
|
16742
17115
|
|
|
17116
|
+
// ../../packages/shared/src/history-quality.ts
|
|
17117
|
+
var init_history_quality = __esm({
|
|
17118
|
+
"../../packages/shared/src/history-quality.ts"() {
|
|
17119
|
+
"use strict";
|
|
17120
|
+
}
|
|
17121
|
+
});
|
|
17122
|
+
|
|
17123
|
+
// ../../packages/shared/src/history-read.ts
|
|
17124
|
+
function historyReadFields(source, attrsJson) {
|
|
17125
|
+
const attrs = unpackHistoryAttrs(typeof attrsJson === "string" ? { attrsJson } : {});
|
|
17126
|
+
const policy = historyReadPolicy({ extractionSource: source, attrs });
|
|
17127
|
+
if (!policy.history) return {};
|
|
17128
|
+
const quality = attrs["historyQuality"];
|
|
17129
|
+
return {
|
|
17130
|
+
historyNotice: policy.notice,
|
|
17131
|
+
...quality && typeof quality === "object" && !Array.isArray(quality) ? { historyQuality: quality } : {}
|
|
17132
|
+
};
|
|
17133
|
+
}
|
|
17134
|
+
function unpackHistoryAttrs(attrs = {}) {
|
|
17135
|
+
let nested = {};
|
|
17136
|
+
if (typeof attrs["attrsJson"] === "string") {
|
|
17137
|
+
try {
|
|
17138
|
+
const parsed = JSON.parse(attrs["attrsJson"]);
|
|
17139
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) nested = parsed;
|
|
17140
|
+
} catch {
|
|
17141
|
+
}
|
|
17142
|
+
}
|
|
17143
|
+
return { ...nested, ...attrs };
|
|
17144
|
+
}
|
|
17145
|
+
function historyReadPolicy(node2, options = {}) {
|
|
17146
|
+
const attrs = unpackHistoryAttrs(node2.attrs);
|
|
17147
|
+
if (attrs["source"] === "cloud" && typeof attrs["extractionSource"] !== "string" && attrs["historyQuality"] == null) {
|
|
17148
|
+
return { allow: options.mode !== "passive", history: false, notice: "Cloud provenance is missing; refresh this cached result before using it as a standing prior." };
|
|
17149
|
+
}
|
|
17150
|
+
const isHistory = node2.extractionSource === "history-mined" || attrs["extractionSource"] === "history-mined" || attrs["historyQuality"] != null;
|
|
17151
|
+
if (!isHistory) return { allow: true, history: false, notice: null };
|
|
17152
|
+
const raw2 = attrs["historyQuality"];
|
|
17153
|
+
const q = raw2 && typeof raw2 === "object" ? raw2 : {};
|
|
17154
|
+
const source = q["sourceSupport"] ?? "unreviewed";
|
|
17155
|
+
const applicability = q["applicability"] ?? "unknown";
|
|
17156
|
+
const current = options.atCommit !== void 0 && q["evaluatedAtCommit"] === options.atCommit;
|
|
17157
|
+
const invalid = source === "contradicted" || source === "quarantined";
|
|
17158
|
+
const passive = options.mode === "passive";
|
|
17159
|
+
const validation = node2.validationSource ?? attrs["validationSource"];
|
|
17160
|
+
const independentlyValidated = validation === "human-explicit" || validation === "human-implicit" || validation === "agent-observed";
|
|
17161
|
+
const allow = !invalid && (!passive || source === "supported" && current && applicability === "applicable" && independentlyValidated);
|
|
17162
|
+
const at = typeof attrs["commitSha"] === "string" ? ` at ${attrs["commitSha"].slice(0, 12)}` : "";
|
|
17163
|
+
return {
|
|
17164
|
+
allow,
|
|
17165
|
+
history: true,
|
|
17166
|
+
notice: `History-derived${at}; source ${String(source)}; applicability ${current ? String(applicability) : "unknown at this checkout"}; ${independentlyValidated ? "separate validation recorded" : "not independently validated"}.`
|
|
17167
|
+
};
|
|
17168
|
+
}
|
|
17169
|
+
var init_history_read = __esm({
|
|
17170
|
+
"../../packages/shared/src/history-read.ts"() {
|
|
17171
|
+
"use strict";
|
|
17172
|
+
}
|
|
17173
|
+
});
|
|
17174
|
+
|
|
17175
|
+
// ../../packages/shared/src/history-temporal.ts
|
|
17176
|
+
async function evaluateHistoryApplicability(intervals, atCommit, isAncestor) {
|
|
17177
|
+
let superseded = false;
|
|
17178
|
+
let historical = false;
|
|
17179
|
+
let uncertain = false;
|
|
17180
|
+
for (const interval of intervals) {
|
|
17181
|
+
const [begun, covered, coherent] = await Promise.all([
|
|
17182
|
+
isAncestor(interval.fromCommit, atCommit),
|
|
17183
|
+
isAncestor(atCommit, interval.throughCommit),
|
|
17184
|
+
isAncestor(interval.fromCommit, interval.throughCommit)
|
|
17185
|
+
]);
|
|
17186
|
+
if (begun === null || covered === null || coherent === null) {
|
|
17187
|
+
uncertain = true;
|
|
17188
|
+
continue;
|
|
17189
|
+
}
|
|
17190
|
+
if (!begun || !covered || !coherent) continue;
|
|
17191
|
+
if (interval.untilCommit) {
|
|
17192
|
+
const [ended, validEnd] = await Promise.all([isAncestor(interval.untilCommit, atCommit), isAncestor(interval.fromCommit, interval.untilCommit)]);
|
|
17193
|
+
if (ended === null || validEnd === null || !validEnd) {
|
|
17194
|
+
uncertain = true;
|
|
17195
|
+
continue;
|
|
17196
|
+
}
|
|
17197
|
+
if (ended) {
|
|
17198
|
+
if (interval.supersededByOccurrence) superseded = true;
|
|
17199
|
+
else historical = true;
|
|
17200
|
+
continue;
|
|
17201
|
+
}
|
|
17202
|
+
}
|
|
17203
|
+
return "applicable";
|
|
17204
|
+
}
|
|
17205
|
+
return uncertain ? "unknown" : superseded ? "superseded" : historical ? "historical" : "unknown";
|
|
17206
|
+
}
|
|
17207
|
+
var init_history_temporal = __esm({
|
|
17208
|
+
"../../packages/shared/src/history-temporal.ts"() {
|
|
17209
|
+
"use strict";
|
|
17210
|
+
}
|
|
17211
|
+
});
|
|
17212
|
+
|
|
17213
|
+
// ../../packages/shared/src/history-revision.ts
|
|
17214
|
+
function historyDag(records) {
|
|
17215
|
+
const graph = new Map(records.map((r) => [r.commit, r.parents]));
|
|
17216
|
+
if (graph.size !== records.length) throw new Error("duplicate Git commit in history proof");
|
|
17217
|
+
const incoming = new Map([...graph].map(([id, parents]) => [id, parents.filter((p) => graph.has(p)).length]));
|
|
17218
|
+
const children = /* @__PURE__ */ new Map();
|
|
17219
|
+
for (const [id, parents] of graph) for (const p of parents) if (graph.has(p)) children.set(p, [...children.get(p) ?? [], id]);
|
|
17220
|
+
const ready = [...incoming].filter(([, n]) => n === 0).map(([id]) => id);
|
|
17221
|
+
let visited = 0;
|
|
17222
|
+
while (ready.length) {
|
|
17223
|
+
const id = ready.pop();
|
|
17224
|
+
visited++;
|
|
17225
|
+
for (const child of children.get(id) ?? []) {
|
|
17226
|
+
const n = incoming.get(child) - 1;
|
|
17227
|
+
incoming.set(child, n);
|
|
17228
|
+
if (n === 0) ready.push(child);
|
|
17229
|
+
}
|
|
17230
|
+
}
|
|
17231
|
+
if (visited !== graph.size) throw new Error("cyclic history proof");
|
|
17232
|
+
return (a, b) => {
|
|
17233
|
+
if (!graph.has(a) || !graph.has(b)) return null;
|
|
17234
|
+
const pending = [b], seen = /* @__PURE__ */ new Set();
|
|
17235
|
+
let missing = false;
|
|
17236
|
+
while (pending.length) {
|
|
17237
|
+
const id = pending.pop();
|
|
17238
|
+
if (id === a) return true;
|
|
17239
|
+
if (seen.has(id)) continue;
|
|
17240
|
+
seen.add(id);
|
|
17241
|
+
const parents = graph.get(id);
|
|
17242
|
+
if (!parents) missing = true;
|
|
17243
|
+
else pending.push(...parents);
|
|
17244
|
+
}
|
|
17245
|
+
return missing ? null : false;
|
|
17246
|
+
};
|
|
17247
|
+
}
|
|
17248
|
+
function occurrenceSourceCommit(o) {
|
|
17249
|
+
const sha2 = o.quality["commitSha"];
|
|
17250
|
+
return typeof sha2 === "string" && Sha.safeParse(sha2).success ? sha2 : null;
|
|
17251
|
+
}
|
|
17252
|
+
function historySemanticKey(projectId, o) {
|
|
17253
|
+
const q = o.quality;
|
|
17254
|
+
const anchors = q["historicalAnchors"];
|
|
17255
|
+
if (q["sourceSupport"] !== "supported" || !anchors?.length || anchors.some((a) => !a.symbolId)) return null;
|
|
17256
|
+
return digest([projectId, o.label, o.statement, q["claimKind"] ?? null, q["qualifier"], q["conditions"], q["rationale"], [...new Set(anchors.map((a) => a.symbolId))].sort()]);
|
|
17257
|
+
}
|
|
17258
|
+
function preservedHistoryOccurrence(o, observed, atCommit, ancestor) {
|
|
17259
|
+
const q = o.quality, source = occurrenceSourceCommit(o);
|
|
17260
|
+
if (!source || ancestor(source, atCommit) !== true || q["sourceSupport"] !== "supported" || !observed) return false;
|
|
17261
|
+
const parsed = external_exports.array(HistoryEvidenceRefSchema).safeParse(q["evidence"]);
|
|
17262
|
+
if (!parsed.success || !parsed.data.length || parsed.data.some((e) => e.sourceKind !== "diff" || !["after", "context"].includes(e.side))) return false;
|
|
17263
|
+
const anchors = q["historicalAnchors"];
|
|
17264
|
+
if (!anchors?.length || anchors.some((a) => a.side !== "after" || !a.bodyHash || !observed.symbols.some((s) => s.symbolId === a.symbolId && s.bodyHash === a.bodyHash))) return false;
|
|
17265
|
+
return parsed.data.every((e) => anchors.some((a) => a.blockDigest === e.blockDigest && a.startByte <= e.startByte && a.endByte >= e.endByte));
|
|
17266
|
+
}
|
|
17267
|
+
var Sha, HistoryRevisionRequestSchema;
|
|
17268
|
+
var init_history_revision = __esm({
|
|
17269
|
+
"../../packages/shared/src/history-revision.ts"() {
|
|
17270
|
+
"use strict";
|
|
17271
|
+
init_zod();
|
|
17272
|
+
init_hash();
|
|
17273
|
+
init_history_evidence();
|
|
17274
|
+
Sha = external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
|
|
17275
|
+
HistoryRevisionRequestSchema = external_exports.strictObject({
|
|
17276
|
+
atCommit: Sha,
|
|
17277
|
+
parents: external_exports.array(external_exports.strictObject({ commit: Sha, parents: external_exports.array(Sha).max(32) })).max(8192),
|
|
17278
|
+
observations: external_exports.array(external_exports.strictObject({
|
|
17279
|
+
occurrenceId: external_exports.string().min(1).max(100),
|
|
17280
|
+
symbols: external_exports.array(external_exports.strictObject({ symbolId: external_exports.string().regex(/^sym_[a-f0-9]{8,64}$/), bodyHash: external_exports.string().regex(/^[a-f0-9]{8,64}$/) })).max(32),
|
|
17281
|
+
/** Scrubbed, tokenized net change from this occurrence's source to atCommit. */
|
|
17282
|
+
diff: external_exports.string().max(16e3).optional()
|
|
17283
|
+
})).max(50)
|
|
17284
|
+
});
|
|
17285
|
+
}
|
|
17286
|
+
});
|
|
17287
|
+
|
|
16743
17288
|
// ../../packages/shared/src/nlp/canonicalize.ts
|
|
16744
17289
|
function canonicalize(value) {
|
|
16745
17290
|
return value.normalize("NFC").trim().toLowerCase().replace(/\s+/g, " ");
|
|
@@ -16809,6 +17354,16 @@ __export(src_exports, {
|
|
|
16809
17354
|
FILE_ANCHOR_QNAME: () => FILE_ANCHOR_QNAME,
|
|
16810
17355
|
GIT_EDGES: () => GIT_EDGES,
|
|
16811
17356
|
GRAPH_EVENT_VOCABULARIES: () => GRAPH_EVENT_VOCABULARIES,
|
|
17357
|
+
HISTORY_EVIDENCE_SCHEMA_VERSION: () => HISTORY_EVIDENCE_SCHEMA_VERSION,
|
|
17358
|
+
HISTORY_SCRUBBER_VERSION: () => HISTORY_SCRUBBER_VERSION,
|
|
17359
|
+
HistoryAnchorSourceSchema: () => HistoryAnchorSourceSchema,
|
|
17360
|
+
HistoryCandidateBatchSchema: () => HistoryCandidateBatchSchema,
|
|
17361
|
+
HistoryCandidateSchema: () => HistoryCandidateSchema,
|
|
17362
|
+
HistoryEvidenceRefSchema: () => HistoryEvidenceRefSchema,
|
|
17363
|
+
HistoryEvidenceSelectionSchema: () => HistoryEvidenceSelectionSchema,
|
|
17364
|
+
HistoryRelationCandidateSchema: () => HistoryRelationCandidateSchema,
|
|
17365
|
+
HistoryRevisionRequestSchema: () => HistoryRevisionRequestSchema,
|
|
17366
|
+
HistorySymbolAnchorSchema: () => HistorySymbolAnchorSchema,
|
|
16812
17367
|
IDENTITY_EDGES: () => IDENTITY_EDGES,
|
|
16813
17368
|
INGEST_EXTRACTION_SOURCES: () => INGEST_EXTRACTION_SOURCES,
|
|
16814
17369
|
INGEST_SOURCES: () => INGEST_SOURCES,
|
|
@@ -16824,6 +17379,8 @@ __export(src_exports, {
|
|
|
16824
17379
|
PROJECT_ONLY_EDGE_TYPES: () => PROJECT_ONLY_EDGE_TYPES,
|
|
16825
17380
|
PROJECT_ONLY_NODE_LABELS: () => PROJECT_ONLY_NODE_LABELS,
|
|
16826
17381
|
QUARANTINE_EXTRACTION_SOURCE_PREFIX: () => QUARANTINE_EXTRACTION_SOURCE_PREFIX,
|
|
17382
|
+
REDACTED_CREDENTIAL: () => REDACTED_CREDENTIAL,
|
|
17383
|
+
REDACTED_EMAIL: () => REDACTED_EMAIL,
|
|
16827
17384
|
RESOLUTION_EDGES: () => RESOLUTION_EDGES,
|
|
16828
17385
|
RE_LEADING_ARTICLE: () => RE_LEADING_ARTICLE,
|
|
16829
17386
|
ROUTING_REASONS: () => ROUTING_REASONS,
|
|
@@ -16854,6 +17411,7 @@ __export(src_exports, {
|
|
|
16854
17411
|
canonicalizeContext: () => canonicalizeContext,
|
|
16855
17412
|
canonicalizeError: () => canonicalizeError,
|
|
16856
17413
|
canonicalizeToken: () => canonicalizeToken,
|
|
17414
|
+
checkHistoryCandidate: () => checkHistoryCandidate,
|
|
16857
17415
|
claimStructure: () => claimStructure,
|
|
16858
17416
|
conceptBag: () => conceptBag,
|
|
16859
17417
|
conceptTokens: () => conceptTokens,
|
|
@@ -16863,8 +17421,15 @@ __export(src_exports, {
|
|
|
16863
17421
|
detectStance: () => detectStance,
|
|
16864
17422
|
digest: () => digest,
|
|
16865
17423
|
errorSignatureEqual: () => errorSignatureEqual,
|
|
17424
|
+
evaluateHistoryApplicability: () => evaluateHistoryApplicability,
|
|
16866
17425
|
extractIdentifierTokens: () => extractIdentifierTokens,
|
|
16867
17426
|
genericCanonicalId: () => genericCanonicalId,
|
|
17427
|
+
historyDag: () => historyDag,
|
|
17428
|
+
historyReadFields: () => historyReadFields,
|
|
17429
|
+
historyReadPolicy: () => historyReadPolicy,
|
|
17430
|
+
historySemanticKey: () => historySemanticKey,
|
|
17431
|
+
historySourceBlocks: () => historySourceBlocks,
|
|
17432
|
+
historyTextDigest: () => historyTextDigest,
|
|
16868
17433
|
identityId: () => identityId,
|
|
16869
17434
|
isAnchorLabelKind: () => isAnchorLabelKind,
|
|
16870
17435
|
isCausalProtected: () => isCausalProtected,
|
|
@@ -16891,6 +17456,7 @@ __export(src_exports, {
|
|
|
16891
17456
|
normalizeSymbolPath: () => normalizeSymbolPath,
|
|
16892
17457
|
normalizeToolName: () => normalizeToolName,
|
|
16893
17458
|
npmPurl: () => npmPurl,
|
|
17459
|
+
occurrenceSourceCommit: () => occurrenceSourceCommit,
|
|
16894
17460
|
operatingSystemCanonicalId: () => operatingSystemCanonicalId,
|
|
16895
17461
|
osNameForPlatform: () => osNameForPlatform,
|
|
16896
17462
|
packageCanonicalId: () => packageCanonicalId,
|
|
@@ -16902,14 +17468,18 @@ __export(src_exports, {
|
|
|
16902
17468
|
parsePackageRef: () => parsePackageRef,
|
|
16903
17469
|
parsePnpmLock: () => parsePnpmLock,
|
|
16904
17470
|
prefilterEntities: () => prefilterEntities,
|
|
17471
|
+
preservedHistoryOccurrence: () => preservedHistoryOccurrence,
|
|
16905
17472
|
problemIdFromError: () => problemIdFromError,
|
|
16906
17473
|
projectSaltedNodeId: () => projectSaltedNodeId,
|
|
16907
17474
|
projectSymbolId: () => projectSymbolId,
|
|
16908
17475
|
provenanceBand: () => provenanceBand,
|
|
16909
17476
|
resolveCanonical: () => resolveCanonical,
|
|
16910
17477
|
resolveCanonicalId: () => resolveCanonicalId,
|
|
17478
|
+
resolveHistoryEvidence: () => resolveHistoryEvidence,
|
|
16911
17479
|
resolveUnambiguousCanonicalId: () => resolveUnambiguousCanonicalId,
|
|
16912
17480
|
retrievalTokens: () => retrievalTokens,
|
|
17481
|
+
scrubHistoryText: () => scrubHistoryText,
|
|
17482
|
+
scrubHistoryValue: () => scrubHistoryValue,
|
|
16913
17483
|
sha256: () => sha256,
|
|
16914
17484
|
sha256Short: () => sha256Short,
|
|
16915
17485
|
sidecarDropBucket: () => sidecarDropBucket,
|
|
@@ -16922,6 +17492,7 @@ __export(src_exports, {
|
|
|
16922
17492
|
toCloudAttrs: () => toCloudAttrs,
|
|
16923
17493
|
toolCanonicalId: () => toolCanonicalId,
|
|
16924
17494
|
triageDiscriminatorAttrs: () => triageDiscriminatorAttrs,
|
|
17495
|
+
unpackHistoryAttrs: () => unpackHistoryAttrs,
|
|
16925
17496
|
unregisteredGraphEventKeys: () => unregisteredGraphEventKeys,
|
|
16926
17497
|
validateCastaliaPayload: () => validateCastaliaPayload,
|
|
16927
17498
|
versionlessPurl: () => versionlessPurl,
|
|
@@ -16940,6 +17511,11 @@ var init_src = __esm({
|
|
|
16940
17511
|
init_project_symbol();
|
|
16941
17512
|
init_lockfile();
|
|
16942
17513
|
init_manifests();
|
|
17514
|
+
init_history_quality();
|
|
17515
|
+
init_history_read();
|
|
17516
|
+
init_history_temporal();
|
|
17517
|
+
init_history_revision();
|
|
17518
|
+
init_history_evidence();
|
|
16943
17519
|
init_hash();
|
|
16944
17520
|
init_error_signature();
|
|
16945
17521
|
init_canonicalize();
|
|
@@ -16949,6 +17525,7 @@ var init_src = __esm({
|
|
|
16949
17525
|
init_predicate();
|
|
16950
17526
|
init_taxonomy();
|
|
16951
17527
|
init_triage_canon();
|
|
17528
|
+
init_history_text();
|
|
16952
17529
|
}
|
|
16953
17530
|
});
|
|
16954
17531
|
|
|
@@ -21307,6 +21884,15 @@ function percolate(l1, l2, opts) {
|
|
|
21307
21884
|
for (const label of PERCOLATING_LABELS) {
|
|
21308
21885
|
for (const n of l1.findNodesByLabel(label)) {
|
|
21309
21886
|
if (n.label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
21887
|
+
if (n.attrs["source"] === "cloud") {
|
|
21888
|
+
const raw2 = l2.getMeta?.(`history-correction:${String(n.attrs["cloudNodeId"] ?? n.id)}`);
|
|
21889
|
+
const correction = raw2 ? JSON.parse(raw2) : null;
|
|
21890
|
+
const support2 = n.attrs["historyQuality"]?.["sourceSupport"];
|
|
21891
|
+
if (correction?.action === "quarantine" || correction?.sourceSupport === "contradicted" || support2 === "quarantined" || support2 === "contradicted") {
|
|
21892
|
+
result.nodesSkipped++;
|
|
21893
|
+
continue;
|
|
21894
|
+
}
|
|
21895
|
+
}
|
|
21310
21896
|
present.add(n.id);
|
|
21311
21897
|
const existing = l2.getNode(n.id);
|
|
21312
21898
|
if (!existing) {
|
|
@@ -24222,6 +24808,7 @@ var init_src5 = __esm({
|
|
|
24222
24808
|
|
|
24223
24809
|
// ../../packages/context-writer/src/render.ts
|
|
24224
24810
|
function isPassiveInjectable(node2) {
|
|
24811
|
+
if (!historyReadPolicy(node2, { mode: "passive" }).allow) return false;
|
|
24225
24812
|
if (node2.label === "Pattern" || node2.label === "Technique" || node2.label === "AntiPattern") {
|
|
24226
24813
|
return true;
|
|
24227
24814
|
}
|
|
@@ -24231,7 +24818,7 @@ function isPassiveInjectable(node2) {
|
|
|
24231
24818
|
return false;
|
|
24232
24819
|
}
|
|
24233
24820
|
function buildSnapshot(opts) {
|
|
24234
|
-
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0);
|
|
24821
|
+
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive" }).allow);
|
|
24235
24822
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
24236
24823
|
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
24237
24824
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
@@ -24261,10 +24848,11 @@ function buildSnapshot(opts) {
|
|
|
24261
24848
|
...opts.store.findNodesByLabel("Pattern"),
|
|
24262
24849
|
...opts.store.findNodesByLabel("Technique"),
|
|
24263
24850
|
...opts.store.findNodesByLabel("AntiPattern")
|
|
24264
|
-
].sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
24851
|
+
].filter((n) => historyReadPolicy(n, { mode: "passive" }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
24265
24852
|
const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile) : void 0;
|
|
24266
24853
|
const byEpisode = /* @__PURE__ */ new Map();
|
|
24267
24854
|
for (const sol of opts.store.findNodesByLabel("Solution")) {
|
|
24855
|
+
if (!historyReadPolicy(sol, { mode: "passive" }).allow) continue;
|
|
24268
24856
|
if (sol.attrs["enrichmentPending"] !== true) continue;
|
|
24269
24857
|
const ep = sol.attrs["episodeId"] ?? sol.id;
|
|
24270
24858
|
const list = byEpisode.get(ep) ?? [];
|
|
@@ -24374,6 +24962,14 @@ function sliceForFile(store, relPath) {
|
|
|
24374
24962
|
if (externalRefs.length >= 20) break;
|
|
24375
24963
|
}
|
|
24376
24964
|
const fp = priorsForFile(store, relPath);
|
|
24965
|
+
if (fp) {
|
|
24966
|
+
const allowed = (n) => historyReadPolicy(n, { mode: "passive" }).allow;
|
|
24967
|
+
fp.openProblems = fp.openProblems.filter(allowed);
|
|
24968
|
+
fp.constraints = fp.constraints.filter(allowed);
|
|
24969
|
+
fp.resolvedProblems = fp.resolvedProblems.filter(allowed);
|
|
24970
|
+
fp.related = fp.related.filter(allowed);
|
|
24971
|
+
for (const [id, solutions] of fp.solutionsByProblem) fp.solutionsByProblem.set(id, solutions.filter(allowed));
|
|
24972
|
+
}
|
|
24377
24973
|
const priors = fp ? {
|
|
24378
24974
|
openProblems: fp.openProblems.slice(0, 3).map((p) => ({
|
|
24379
24975
|
id: p.id,
|
|
@@ -24846,6 +25442,7 @@ var init_render = __esm({
|
|
|
24846
25442
|
"use strict";
|
|
24847
25443
|
init_src5();
|
|
24848
25444
|
init_src2();
|
|
25445
|
+
init_src();
|
|
24849
25446
|
RECALL_FIRST_HEADER = "## errata \u2014 recall before you work";
|
|
24850
25447
|
RECALL_FIRST_BODY = "Before investigating any bug or error, your FIRST tool call must be `mcp__errata__errata_search` with a few words describing the problem. This machine's knowledge graph records previously solved problems \u2014 the answer may already be recorded. Read what it returns before touching any files.";
|
|
24851
25448
|
RECALL_FIRST_BLOCK = `${RECALL_FIRST_HEADER}
|
|
@@ -24993,7 +25590,7 @@ function selectDurableMemory(store, profile, opts = {}) {
|
|
|
24993
25590
|
const minContributors = opts.minContributors ?? 1;
|
|
24994
25591
|
const wsLangs = new Set(profile.languages.map((l) => l.toLowerCase()));
|
|
24995
25592
|
return store.findNodesByLabel("Claim").filter(
|
|
24996
|
-
(n) => Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) === ABSTRACTION_LEVEL.PRINCIPLE && n.attrs["provisional"] === false && contributorsOf(n) >= minContributors && // Lang-relevance: universal principles (no scope.lang) bleed everywhere; a
|
|
25593
|
+
(n) => historyReadPolicy(n, { mode: "passive" }).allow && Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) === ABSTRACTION_LEVEL.PRINCIPLE && n.attrs["provisional"] === false && contributorsOf(n) >= minContributors && // Lang-relevance: universal principles (no scope.lang) bleed everywhere; a
|
|
24997
25594
|
// language-scoped principle only bleeds into repos that USE that language —
|
|
24998
25595
|
// so a Python principle never lands a dead `**/*.py` rule in a TS repo.
|
|
24999
25596
|
(scopeLangOf(n) == null || wsLangs.has(scopeLangOf(n)))
|
|
@@ -25017,6 +25614,7 @@ var init_select_durable_memory = __esm({
|
|
|
25017
25614
|
"../../packages/context-writer/src/select-durable-memory.ts"() {
|
|
25018
25615
|
"use strict";
|
|
25019
25616
|
init_src2();
|
|
25617
|
+
init_src();
|
|
25020
25618
|
num2 = (v, d = 0) => typeof v === "number" && Number.isFinite(v) ? v : d;
|
|
25021
25619
|
LANG_GLOBS = {
|
|
25022
25620
|
typescript: ["**/*.ts", "**/*.tsx"],
|
|
@@ -25854,7 +26452,7 @@ var init_client = __esm({
|
|
|
25854
26452
|
label: n.label,
|
|
25855
26453
|
description: n.description,
|
|
25856
26454
|
extractionConfidence: typeof n.attrs["score"] === "number" ? clamp012(n.attrs["score"]) : 0.5,
|
|
25857
|
-
extractionSource: "
|
|
26455
|
+
extractionSource: INGEST_EXTRACTION_SOURCES.includes(n.attrs["extractionSource"]) ? n.attrs["extractionSource"] : "cold-start-seed",
|
|
25858
26456
|
embedding: [],
|
|
25859
26457
|
cumulativeSurprise: 0,
|
|
25860
26458
|
peakSurprise: 0,
|
|
@@ -25866,7 +26464,7 @@ var init_client = __esm({
|
|
|
25866
26464
|
isLandmark: false,
|
|
25867
26465
|
community: null,
|
|
25868
26466
|
stability: "stable",
|
|
25869
|
-
attrs: { ...n.attrs, source: "cloud", cloudNodeId: n.nodeId }
|
|
26467
|
+
attrs: { ...unpackHistoryAttrs(n.attrs), source: "cloud", cloudNodeId: n.nodeId }
|
|
25870
26468
|
}));
|
|
25871
26469
|
const edges = res.edges.map((e) => ({
|
|
25872
26470
|
id: digest({ from: e.fromCanonicalId, type: e.type, to: e.toCanonicalId }),
|
|
@@ -25915,6 +26513,17 @@ var init_client = __esm({
|
|
|
25915
26513
|
* daemon filters the page against its own checkout, and nothing about which
|
|
25916
26514
|
* symbols it holds is sent. Same membership gate as priors.
|
|
25917
26515
|
*/
|
|
26516
|
+
/** Content-free invalidations, independent of code-symbol/anchor availability. */
|
|
26517
|
+
async getProjectHistoryCorrections(projectId, since, limit = 200) {
|
|
26518
|
+
return this.json("GET", `/v2/projects/${encodeURIComponent(projectId)}/anchors?correctionsOnly=1&correctionSince=${String(since)}&limit=${String(limit)}`);
|
|
26519
|
+
}
|
|
26520
|
+
async getHistoryOccurrences(projectId, atCommit, after) {
|
|
26521
|
+
const query = new URLSearchParams({ atCommit, limit: "50", ...after ? { after } : {} });
|
|
26522
|
+
return this.json("GET", `/v2/projects/${encodeURIComponent(projectId)}/history/occurrences?${query}`);
|
|
26523
|
+
}
|
|
26524
|
+
async reconcileHistory(projectId, proof) {
|
|
26525
|
+
return this.json("POST", `/v2/projects/${encodeURIComponent(projectId)}/history/reconcile`, proof);
|
|
26526
|
+
}
|
|
25918
26527
|
async getProjectAnchors(projectId, since, limit = 200) {
|
|
25919
26528
|
const res = await this.json(
|
|
25920
26529
|
"GET",
|
|
@@ -26066,13 +26675,13 @@ var init_client = __esm({
|
|
|
26066
26675
|
});
|
|
26067
26676
|
|
|
26068
26677
|
// ../../packages/cloud-client/src/pkce.ts
|
|
26069
|
-
import { createHash as
|
|
26678
|
+
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
26070
26679
|
function base64url3(buf) {
|
|
26071
26680
|
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
26072
26681
|
}
|
|
26073
26682
|
function generatePkce() {
|
|
26074
26683
|
const verifier = base64url3(randomBytes(32));
|
|
26075
|
-
const challenge = base64url3(
|
|
26684
|
+
const challenge = base64url3(createHash3("sha256").update(verifier).digest());
|
|
26076
26685
|
return { verifier, challenge, method: "S256" };
|
|
26077
26686
|
}
|
|
26078
26687
|
function randomState() {
|
|
@@ -29368,14 +29977,14 @@ var init_git_remote = __esm({
|
|
|
29368
29977
|
|
|
29369
29978
|
// src/profile.ts
|
|
29370
29979
|
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
29371
|
-
import { createHash as
|
|
29980
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
29372
29981
|
import { join as join7 } from "node:path";
|
|
29373
29982
|
function workspaceId(root) {
|
|
29374
|
-
return "wp_" +
|
|
29983
|
+
return "wp_" + createHash4("sha256").update(root).digest("hex").slice(0, 12);
|
|
29375
29984
|
}
|
|
29376
29985
|
function sessionOriginKey(sessionId) {
|
|
29377
29986
|
if (!sessionId) return void 0;
|
|
29378
|
-
return "ws_" +
|
|
29987
|
+
return "ws_" + createHash4("sha256").update(sessionId).digest("hex").slice(0, 12);
|
|
29379
29988
|
}
|
|
29380
29989
|
function refreshRepoLocator(root, profile) {
|
|
29381
29990
|
const detected = detectRepoLocator(root, profile.repoRemote);
|
|
@@ -29813,7 +30422,7 @@ function scrub(input) {
|
|
|
29813
30422
|
return `<api-key:${id}>`;
|
|
29814
30423
|
});
|
|
29815
30424
|
}
|
|
29816
|
-
text = text.replace(
|
|
30425
|
+
text = text.replace(EMAIL_RE2, (m) => {
|
|
29817
30426
|
const id = sha256Short(m, 6);
|
|
29818
30427
|
bump("email", `<email:${id}>`);
|
|
29819
30428
|
return `<email:${id}>`;
|
|
@@ -29864,8 +30473,8 @@ function detectViolations(input) {
|
|
|
29864
30473
|
if (p.re.test(input)) violations.add("api-key");
|
|
29865
30474
|
p.re.lastIndex = 0;
|
|
29866
30475
|
}
|
|
29867
|
-
if (
|
|
29868
|
-
|
|
30476
|
+
if (EMAIL_RE2.test(input)) violations.add("email");
|
|
30477
|
+
EMAIL_RE2.lastIndex = 0;
|
|
29869
30478
|
if (WIN_PATH_RE.test(input)) violations.add("windows-path");
|
|
29870
30479
|
WIN_PATH_RE.lastIndex = 0;
|
|
29871
30480
|
if (WIN_UNC_RE.test(input)) violations.add("windows-path");
|
|
@@ -29876,7 +30485,7 @@ function detectViolations(input) {
|
|
|
29876
30485
|
IPV4_RE.lastIndex = 0;
|
|
29877
30486
|
return [...violations];
|
|
29878
30487
|
}
|
|
29879
|
-
var API_KEY_PATTERNS,
|
|
30488
|
+
var API_KEY_PATTERNS, EMAIL_RE2, IPV4_RE, IPV6_RE, WIN_PATH_RE, WIN_UNC_RE, POSIX_USER_PATH_RE, LONG_HASH_RE, UUID_RE;
|
|
29880
30489
|
var init_scrub = __esm({
|
|
29881
30490
|
"../../packages/canonical/src/scrub.ts"() {
|
|
29882
30491
|
"use strict";
|
|
@@ -29890,7 +30499,7 @@ var init_scrub = __esm({
|
|
|
29890
30499
|
{ name: "stripe-key", re: /\b(sk|pk)_(test|live)_[0-9a-zA-Z]{24,}\b/g },
|
|
29891
30500
|
{ name: "bearer", re: /\bBearer\s+[A-Za-z0-9_\-\.]{16,}\b/gi }
|
|
29892
30501
|
];
|
|
29893
|
-
|
|
30502
|
+
EMAIL_RE2 = /\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b/g;
|
|
29894
30503
|
IPV4_RE = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
|
|
29895
30504
|
IPV6_RE = /\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9:]{1,4}\b/g;
|
|
29896
30505
|
WIN_PATH_RE = /\b[A-Za-z]:[\\/](?![\\/])(?:[^\\/\s"']+[\\/])*[^\\/\s"']*/g;
|
|
@@ -32622,6 +33231,7 @@ var init_nightly = __esm({
|
|
|
32622
33231
|
});
|
|
32623
33232
|
|
|
32624
33233
|
// ../../packages/generalizer/src/embed-code.ts
|
|
33234
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
32625
33235
|
function embedCodeNodes(store, opts = {}) {
|
|
32626
33236
|
return embedNodesByLabels(store, CODE_LABELS, opts);
|
|
32627
33237
|
}
|
|
@@ -32630,9 +33240,15 @@ function embedSemanticNodes(store, opts = {}) {
|
|
|
32630
33240
|
}
|
|
32631
33241
|
async function ensureNodeEmbedded(store, nodeId, opts = {}) {
|
|
32632
33242
|
const node2 = store.getNode(nodeId);
|
|
32633
|
-
if (!node2
|
|
33243
|
+
if (!node2) return false;
|
|
33244
|
+
if (!eligibleForEmbedding(store, node2)) {
|
|
33245
|
+
clearWithdrawnVector(store, node2.id);
|
|
33246
|
+
return false;
|
|
33247
|
+
}
|
|
33248
|
+
if (node2.embedding.length > 0) return false;
|
|
32634
33249
|
const text = buildText(store, node2);
|
|
32635
33250
|
if (!text) return false;
|
|
33251
|
+
const before = embeddingSnapshot(node2, text);
|
|
32636
33252
|
let result;
|
|
32637
33253
|
try {
|
|
32638
33254
|
if (opts.mode === "hash") {
|
|
@@ -32646,12 +33262,41 @@ async function ensureNodeEmbedded(store, nodeId, opts = {}) {
|
|
|
32646
33262
|
} catch {
|
|
32647
33263
|
return false;
|
|
32648
33264
|
}
|
|
32649
|
-
store.
|
|
33265
|
+
return store.transaction(() => writeIfUnchanged(store, before, result));
|
|
33266
|
+
}
|
|
33267
|
+
function embeddingState(node2) {
|
|
33268
|
+
return createHash5("sha256").update(JSON.stringify([node2.attrs["embeddingVersion"] ?? null, node2.embedding])).digest("hex");
|
|
33269
|
+
}
|
|
33270
|
+
function embeddingSnapshot(node2, text) {
|
|
33271
|
+
return { id: node2.id, text, validTo: node2.validTo, vectorState: embeddingState(node2) };
|
|
33272
|
+
}
|
|
33273
|
+
function writeIfUnchanged(store, before, result) {
|
|
33274
|
+
const current = store.getNode(before.id);
|
|
33275
|
+
if (!current || !eligibleForEmbedding(store, current) || buildText(store, current) !== before.text || current.validTo !== before.validTo || embeddingState(current) !== before.vectorState)
|
|
33276
|
+
return false;
|
|
33277
|
+
store.updateNode(current.id, {
|
|
32650
33278
|
embedding: result.vector,
|
|
32651
|
-
attrs: { ...
|
|
33279
|
+
attrs: { ...current.attrs, embeddingVersion: result.version }
|
|
32652
33280
|
});
|
|
32653
33281
|
return true;
|
|
32654
33282
|
}
|
|
33283
|
+
function eligibleForEmbedding(store, node2) {
|
|
33284
|
+
const cloudId = node2.attrs["cloudNodeId"];
|
|
33285
|
+
const raw2 = node2.attrs["source"] === "cloud" ? store.getMeta?.(`history-correction:${typeof cloudId === "string" ? cloudId : node2.id}`) : null;
|
|
33286
|
+
const correction = raw2 ? JSON.parse(raw2) : null;
|
|
33287
|
+
const withdrawn = correction && Number(correction.seq) >= Number(node2.attrs["historyCorrectionSeq"] ?? 0) && (correction.action === "quarantine" || correction.sourceSupport === "contradicted");
|
|
33288
|
+
return !withdrawn && historyReadPolicy(node2).allow && !node2.attrs["mergedInto"] && !node2.attrs["fusedInto"];
|
|
33289
|
+
}
|
|
33290
|
+
function clearWithdrawnVector(store, nodeId) {
|
|
33291
|
+
store.transaction(() => {
|
|
33292
|
+
const node2 = store.getNode(nodeId);
|
|
33293
|
+
if (!node2 || eligibleForEmbedding(store, node2)) return;
|
|
33294
|
+
if (node2.embedding.length || node2.attrs["embeddingVersion"] !== void 0) {
|
|
33295
|
+
const { embeddingVersion: _version, ...attrs } = node2.attrs;
|
|
33296
|
+
store.mergeNode({ ...node2, embedding: [], attrs });
|
|
33297
|
+
}
|
|
33298
|
+
});
|
|
33299
|
+
}
|
|
32655
33300
|
async function embedNodesByLabels(store, labels, opts = {}) {
|
|
32656
33301
|
const started2 = Date.now();
|
|
32657
33302
|
const report = {
|
|
@@ -32666,8 +33311,14 @@ async function embedNodesByLabels(store, labels, opts = {}) {
|
|
|
32666
33311
|
const currentVersion = hashOnly ? EMBEDDING_VERSION : (await embedBatchWithModelOrHash(["probe"]))[0]?.version ?? "unknown";
|
|
32667
33312
|
const todo = [];
|
|
32668
33313
|
for (const label of labels) {
|
|
32669
|
-
for (const node2 of store.findNodesByLabel(
|
|
33314
|
+
for (const node2 of store.findNodesByLabel(
|
|
33315
|
+
label
|
|
33316
|
+
)) {
|
|
32670
33317
|
report.scanned++;
|
|
33318
|
+
if (!eligibleForEmbedding(store, node2)) {
|
|
33319
|
+
clearWithdrawnVector(store, node2.id);
|
|
33320
|
+
continue;
|
|
33321
|
+
}
|
|
32671
33322
|
const existingVersion = node2.attrs["embeddingVersion"] ?? null;
|
|
32672
33323
|
if (existingVersion) {
|
|
32673
33324
|
report.versionsSeen[existingVersion] = (report.versionsSeen[existingVersion] ?? 0) + 1;
|
|
@@ -32682,7 +33333,7 @@ async function embedNodesByLabels(store, labels, opts = {}) {
|
|
|
32682
33333
|
}
|
|
32683
33334
|
const text = buildText(store, node2);
|
|
32684
33335
|
if (!text) continue;
|
|
32685
|
-
todo.push(
|
|
33336
|
+
todo.push(embeddingSnapshot(node2, text));
|
|
32686
33337
|
}
|
|
32687
33338
|
}
|
|
32688
33339
|
for (let i2 = 0; i2 < todo.length; i2 += BATCH_SIZE) {
|
|
@@ -32699,17 +33350,12 @@ async function embedNodesByLabels(store, labels, opts = {}) {
|
|
|
32699
33350
|
}
|
|
32700
33351
|
store.transaction(() => {
|
|
32701
33352
|
for (let j = 0; j < batch.length; j++) {
|
|
32702
|
-
const
|
|
32703
|
-
if (!
|
|
32704
|
-
|
|
32705
|
-
|
|
32706
|
-
|
|
32707
|
-
|
|
32708
|
-
store.updateNode(batch[j].id, {
|
|
32709
|
-
embedding: results[j].vector,
|
|
32710
|
-
attrs: newAttrs
|
|
32711
|
-
});
|
|
32712
|
-
report.embedded++;
|
|
33353
|
+
const result = results[j];
|
|
33354
|
+
if (!result) {
|
|
33355
|
+
report.failed++;
|
|
33356
|
+
continue;
|
|
33357
|
+
}
|
|
33358
|
+
if (writeIfUnchanged(store, batch[j], result)) report.embedded++;
|
|
32713
33359
|
}
|
|
32714
33360
|
});
|
|
32715
33361
|
if (opts.progress) opts.progress(report.embedded, todo.length);
|
|
@@ -32738,6 +33384,7 @@ var CODE_LABELS, SEMANTIC_LABELS, BATCH_SIZE;
|
|
|
32738
33384
|
var init_embed_code = __esm({
|
|
32739
33385
|
"../../packages/generalizer/src/embed-code.ts"() {
|
|
32740
33386
|
"use strict";
|
|
33387
|
+
init_src();
|
|
32741
33388
|
init_src3();
|
|
32742
33389
|
CODE_LABELS = ["Function", "Method", "Class", "Const"];
|
|
32743
33390
|
SEMANTIC_LABELS = ["Problem", "RootCause", "Solution", "Pattern", "Claim"];
|
|
@@ -32901,7 +33548,7 @@ var init_src10 = __esm({
|
|
|
32901
33548
|
});
|
|
32902
33549
|
|
|
32903
33550
|
// ../../packages/indexer/src/parse-cache.ts
|
|
32904
|
-
import { createHash as
|
|
33551
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
32905
33552
|
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync9 } from "node:fs";
|
|
32906
33553
|
import { homedir as homedir3 } from "node:os";
|
|
32907
33554
|
import { join as join11 } from "node:path";
|
|
@@ -32909,7 +33556,7 @@ function parseCacheDir() {
|
|
|
32909
33556
|
return process.env["ERRATA_PARSE_CACHE"] ?? join11(homedir3(), ".errata", "parse-cache");
|
|
32910
33557
|
}
|
|
32911
33558
|
function parseCacheKey(source, providerId) {
|
|
32912
|
-
return
|
|
33559
|
+
return createHash6("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
|
|
32913
33560
|
}
|
|
32914
33561
|
function entryPath(dir, key) {
|
|
32915
33562
|
return join11(dir, key.slice(0, 2), `${key.slice(2)}.json`);
|
|
@@ -33207,7 +33854,7 @@ var init_identity3 = __esm({
|
|
|
33207
33854
|
import { appendFileSync, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
|
|
33208
33855
|
import { readdir } from "node:fs/promises";
|
|
33209
33856
|
import { extname, join as join12, relative as relative2, sep } from "node:path";
|
|
33210
|
-
import { createHash as
|
|
33857
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
33211
33858
|
import { execFileSync } from "node:child_process";
|
|
33212
33859
|
function nowTs() {
|
|
33213
33860
|
return indexNow ?? Date.now();
|
|
@@ -33216,7 +33863,7 @@ function fingerprintOf(signature, bodyHash) {
|
|
|
33216
33863
|
return `${signature ?? ""}|${bodyHash ?? ""}`;
|
|
33217
33864
|
}
|
|
33218
33865
|
function sha(s) {
|
|
33219
|
-
return
|
|
33866
|
+
return createHash7("sha256").update(s).digest("hex").slice(0, 16);
|
|
33220
33867
|
}
|
|
33221
33868
|
function fileNodeId(workspaceId2, relPath) {
|
|
33222
33869
|
return `file_${sha(workspaceId2 + ":" + relPath.replace(/\\/g, "/"))}`;
|
|
@@ -33344,7 +33991,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
33344
33991
|
for (const rel of [...changedRelPaths]) {
|
|
33345
33992
|
let h;
|
|
33346
33993
|
try {
|
|
33347
|
-
h =
|
|
33994
|
+
h = createHash7("sha256").update(readFileSync11(join12(rootPath, rel))).digest("hex");
|
|
33348
33995
|
} catch {
|
|
33349
33996
|
continue;
|
|
33350
33997
|
}
|
|
@@ -34267,7 +34914,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
|
|
|
34267
34914
|
if (existing && fileUnchanged(existing.attrs, f, skip)) return;
|
|
34268
34915
|
let contentHash;
|
|
34269
34916
|
try {
|
|
34270
|
-
contentHash =
|
|
34917
|
+
contentHash = createHash7("sha256").update(readFileSync11(f.absPath)).digest("hex");
|
|
34271
34918
|
} catch {
|
|
34272
34919
|
}
|
|
34273
34920
|
const carried = { ...existing?.attrs ?? {} };
|
|
@@ -38796,7 +39443,7 @@ var init_tree_sitter_loader = __esm({
|
|
|
38796
39443
|
});
|
|
38797
39444
|
|
|
38798
39445
|
// ../../packages/indexer/src/languages/typescript-treesitter.ts
|
|
38799
|
-
import { createHash as
|
|
39446
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
38800
39447
|
function extractNode(node2, source, containerQname, containerKind) {
|
|
38801
39448
|
switch (node2.type) {
|
|
38802
39449
|
case "function_declaration":
|
|
@@ -39009,7 +39656,7 @@ function scopeRecord(kind, name2, qname, node2, body2, source) {
|
|
|
39009
39656
|
const sig = header.replace(/\s+/g, " ").trim();
|
|
39010
39657
|
if (sig) rec.signature = sig;
|
|
39011
39658
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
39012
|
-
rec.bodyHash =
|
|
39659
|
+
rec.bodyHash = createHash8("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
39013
39660
|
rec.bodySimhash = toHex(simhash(bodyText));
|
|
39014
39661
|
}
|
|
39015
39662
|
}
|
|
@@ -39451,14 +40098,14 @@ var init_typescript_treesitter = __esm({
|
|
|
39451
40098
|
});
|
|
39452
40099
|
|
|
39453
40100
|
// ../../packages/indexer/src/languages/python-treesitter.ts
|
|
39454
|
-
import { createHash as
|
|
40101
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
39455
40102
|
function sigAndHash(node2, body2, source) {
|
|
39456
40103
|
if (!body2) return {};
|
|
39457
40104
|
const out2 = {};
|
|
39458
40105
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
39459
40106
|
if (sig) out2.signature = sig;
|
|
39460
40107
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
39461
|
-
out2.bodyHash =
|
|
40108
|
+
out2.bodyHash = createHash9("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
39462
40109
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
39463
40110
|
return out2;
|
|
39464
40111
|
}
|
|
@@ -39871,7 +40518,7 @@ var init_python_treesitter = __esm({
|
|
|
39871
40518
|
});
|
|
39872
40519
|
|
|
39873
40520
|
// ../../packages/indexer/src/languages/cpp-treesitter.ts
|
|
39874
|
-
import { createHash as
|
|
40521
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
39875
40522
|
function extractNode3(node2, containerQname, containerIsClass, source) {
|
|
39876
40523
|
switch (node2.type) {
|
|
39877
40524
|
case "function_definition":
|
|
@@ -40055,7 +40702,7 @@ function sigAndHash2(node2, body2, source) {
|
|
|
40055
40702
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
40056
40703
|
if (sig) out2.signature = sig;
|
|
40057
40704
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
40058
|
-
out2.bodyHash =
|
|
40705
|
+
out2.bodyHash = createHash10("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
40059
40706
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
40060
40707
|
return out2;
|
|
40061
40708
|
}
|
|
@@ -40216,7 +40863,7 @@ var init_cpp_treesitter = __esm({
|
|
|
40216
40863
|
});
|
|
40217
40864
|
|
|
40218
40865
|
// ../../packages/indexer/src/languages/go-treesitter.ts
|
|
40219
|
-
import { createHash as
|
|
40866
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
40220
40867
|
function extractNode4(node2, containerQname, source) {
|
|
40221
40868
|
switch (node2.type) {
|
|
40222
40869
|
case "function_declaration": {
|
|
@@ -40378,7 +41025,7 @@ function sigAndHash3(node2, body2, source) {
|
|
|
40378
41025
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
40379
41026
|
if (sig) out2.signature = sig;
|
|
40380
41027
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
40381
|
-
out2.bodyHash =
|
|
41028
|
+
out2.bodyHash = createHash11("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
40382
41029
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
40383
41030
|
return out2;
|
|
40384
41031
|
}
|
|
@@ -40522,7 +41169,7 @@ var init_go_treesitter = __esm({
|
|
|
40522
41169
|
});
|
|
40523
41170
|
|
|
40524
41171
|
// ../../packages/indexer/src/languages/rust-treesitter.ts
|
|
40525
|
-
import { createHash as
|
|
41172
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
40526
41173
|
function extractNode5(node2, containerQname, containerIsClass, source) {
|
|
40527
41174
|
switch (node2.type) {
|
|
40528
41175
|
case "function_item":
|
|
@@ -40737,7 +41384,7 @@ function sigAndHash4(node2, body2, source) {
|
|
|
40737
41384
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
40738
41385
|
if (sig) out2.signature = sig;
|
|
40739
41386
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
40740
|
-
out2.bodyHash =
|
|
41387
|
+
out2.bodyHash = createHash12("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
40741
41388
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
40742
41389
|
return out2;
|
|
40743
41390
|
}
|
|
@@ -40888,7 +41535,7 @@ var init_rust_treesitter = __esm({
|
|
|
40888
41535
|
});
|
|
40889
41536
|
|
|
40890
41537
|
// ../../packages/indexer/src/languages/ruby-treesitter.ts
|
|
40891
|
-
import { createHash as
|
|
41538
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
40892
41539
|
function sigAndHash5(node2, body2, source) {
|
|
40893
41540
|
if (!body2) {
|
|
40894
41541
|
const sig2 = source.slice(node2.startIndex, node2.endIndex).replace(/\s+/g, " ").trim();
|
|
@@ -40898,7 +41545,7 @@ function sigAndHash5(node2, body2, source) {
|
|
|
40898
41545
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
40899
41546
|
if (sig) out2.signature = sig;
|
|
40900
41547
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
40901
|
-
out2.bodyHash =
|
|
41548
|
+
out2.bodyHash = createHash13("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
40902
41549
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
40903
41550
|
return out2;
|
|
40904
41551
|
}
|
|
@@ -41244,7 +41891,7 @@ var init_ruby_treesitter = __esm({
|
|
|
41244
41891
|
});
|
|
41245
41892
|
|
|
41246
41893
|
// ../../packages/indexer/src/languages/csharp-treesitter.ts
|
|
41247
|
-
import { createHash as
|
|
41894
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
41248
41895
|
function extractNode7(node2, containerQname, containerIsType, source, eof) {
|
|
41249
41896
|
switch (node2.type) {
|
|
41250
41897
|
case "method_declaration":
|
|
@@ -41446,7 +42093,7 @@ function sigAndHash6(node2, body2, source) {
|
|
|
41446
42093
|
const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
|
|
41447
42094
|
if (sig) out2.signature = sig;
|
|
41448
42095
|
const bodyText = source.slice(body2.startIndex, body2.endIndex);
|
|
41449
|
-
out2.bodyHash =
|
|
42096
|
+
out2.bodyHash = createHash14("sha256").update(bodyText).digest("hex").slice(0, 16);
|
|
41450
42097
|
out2.bodySimhash = toHex(simhash(bodyText));
|
|
41451
42098
|
return out2;
|
|
41452
42099
|
}
|
|
@@ -51362,10 +52009,10 @@ import {
|
|
|
51362
52009
|
writeFileSync as writeFileSync11
|
|
51363
52010
|
} from "node:fs";
|
|
51364
52011
|
import { join as join16 } from "node:path";
|
|
51365
|
-
import { createHash as
|
|
52012
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
51366
52013
|
function enqueueOutbox(paths, payload) {
|
|
51367
52014
|
ensureDir(paths.outbox);
|
|
51368
|
-
const id =
|
|
52015
|
+
const id = createHash15("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
|
|
51369
52016
|
const file2 = join16(paths.outbox, `${Date.now()}-${id}.json`);
|
|
51370
52017
|
writeFileSync11(file2, JSON.stringify(payload, null, 2), "utf8");
|
|
51371
52018
|
return file2;
|
|
@@ -63247,7 +63894,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
63247
63894
|
var require_mock_client = __commonJS({
|
|
63248
63895
|
"../../node_modules/.pnpm/undici@6.24.1/node_modules/undici/lib/mock/mock-client.js"(exports, module2) {
|
|
63249
63896
|
"use strict";
|
|
63250
|
-
var { promisify:
|
|
63897
|
+
var { promisify: promisify4 } = __require("node:util");
|
|
63251
63898
|
var Client = require_client();
|
|
63252
63899
|
var { buildMockDispatch } = require_mock_utils();
|
|
63253
63900
|
var {
|
|
@@ -63287,7 +63934,7 @@ var require_mock_client = __commonJS({
|
|
|
63287
63934
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
63288
63935
|
}
|
|
63289
63936
|
async [kClose]() {
|
|
63290
|
-
await
|
|
63937
|
+
await promisify4(this[kOriginalClose])();
|
|
63291
63938
|
this[kConnected] = 0;
|
|
63292
63939
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
63293
63940
|
}
|
|
@@ -63300,7 +63947,7 @@ var require_mock_client = __commonJS({
|
|
|
63300
63947
|
var require_mock_pool = __commonJS({
|
|
63301
63948
|
"../../node_modules/.pnpm/undici@6.24.1/node_modules/undici/lib/mock/mock-pool.js"(exports, module2) {
|
|
63302
63949
|
"use strict";
|
|
63303
|
-
var { promisify:
|
|
63950
|
+
var { promisify: promisify4 } = __require("node:util");
|
|
63304
63951
|
var Pool = require_pool();
|
|
63305
63952
|
var { buildMockDispatch } = require_mock_utils();
|
|
63306
63953
|
var {
|
|
@@ -63340,7 +63987,7 @@ var require_mock_pool = __commonJS({
|
|
|
63340
63987
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
63341
63988
|
}
|
|
63342
63989
|
async [kClose]() {
|
|
63343
|
-
await
|
|
63990
|
+
await promisify4(this[kOriginalClose])();
|
|
63344
63991
|
this[kConnected] = 0;
|
|
63345
63992
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
63346
63993
|
}
|
|
@@ -74104,7 +74751,7 @@ init_checkout_root();
|
|
|
74104
74751
|
import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
|
|
74105
74752
|
import { basename as basename5, delimiter, dirname as dirname10, join as join20, normalize as normalize3 } from "node:path";
|
|
74106
74753
|
import { homedir as homedir4 } from "node:os";
|
|
74107
|
-
import { createHash as
|
|
74754
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
74108
74755
|
function readFrom(path2, fromByte, maxBytes) {
|
|
74109
74756
|
let fd;
|
|
74110
74757
|
try {
|
|
@@ -74413,7 +75060,7 @@ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false, start
|
|
|
74413
75060
|
turns.push({
|
|
74414
75061
|
// Slice-local line numbers repeat on every Stop. Position distinguishes
|
|
74415
75062
|
// identical messages; the digest distinguishes a replaced row at that position.
|
|
74416
|
-
uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${
|
|
75063
|
+
uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${createHash16("sha256").update(line.trimEnd()).digest("hex")}`,
|
|
74417
75064
|
text: parts2.join("\n\n"),
|
|
74418
75065
|
hostHarness: "codex"
|
|
74419
75066
|
});
|
|
@@ -74662,7 +75309,7 @@ function geminiSessionRoots(env2 = process.env, home = homedir4()) {
|
|
|
74662
75309
|
return [...roots];
|
|
74663
75310
|
}
|
|
74664
75311
|
function geminiProjectHash(cwd) {
|
|
74665
|
-
return
|
|
75312
|
+
return createHash16("sha256").update(cwd).digest("hex");
|
|
74666
75313
|
}
|
|
74667
75314
|
function geminiHashesFor(cwd) {
|
|
74668
75315
|
const variants = /* @__PURE__ */ new Set([cwd, cwd.replace(/\/+$/, "")]);
|
|
@@ -77983,7 +78630,7 @@ var TelemetryRecorder = class {
|
|
|
77983
78630
|
// src/file-activity.ts
|
|
77984
78631
|
import { readFileSync as readFileSync22 } from "node:fs";
|
|
77985
78632
|
import { join as join28 } from "node:path";
|
|
77986
|
-
import { createHash as
|
|
78633
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
77987
78634
|
|
|
77988
78635
|
// ../../packages/privacy/src/patterns/credentials.ts
|
|
77989
78636
|
var CREDENTIAL_PATTERNS = [
|
|
@@ -78732,6 +79379,7 @@ var openaiAgent = new import_undici.Agent({
|
|
|
78732
79379
|
init_git_remote();
|
|
78733
79380
|
|
|
78734
79381
|
// src/history-bundle.ts
|
|
79382
|
+
init_src();
|
|
78735
79383
|
import { execFile as execFile2 } from "node:child_process";
|
|
78736
79384
|
import { readFileSync as readFileSync21 } from "node:fs";
|
|
78737
79385
|
import { join as join27 } from "node:path";
|
|
@@ -78740,8 +79388,6 @@ var FILE_LIST_CAP = 60;
|
|
|
78740
79388
|
var DIFF_FILE_CAP = 40;
|
|
78741
79389
|
var GENERATED_JSON_MAX_CHURN = 800;
|
|
78742
79390
|
var TRUNCATION_MARKER = "\n[truncated]";
|
|
78743
|
-
var REDACTED_CREDENTIAL = "[redacted:credential]";
|
|
78744
|
-
var REDACTED_EMAIL = "[redacted:email]";
|
|
78745
79391
|
var CHARS_PER_TOKEN = 3.5;
|
|
78746
79392
|
function estimateTokens(text) {
|
|
78747
79393
|
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
@@ -78882,138 +79528,6 @@ function isSourceFile(f) {
|
|
|
78882
79528
|
if (ext === "json" && f.adds + f.dels > GENERATED_JSON_MAX_CHURN) return false;
|
|
78883
79529
|
return true;
|
|
78884
79530
|
}
|
|
78885
|
-
var cred = () => REDACTED_CREDENTIAL;
|
|
78886
|
-
var ASSIGNMENT_STOPWORDS = /* @__PURE__ */ new Set([
|
|
78887
|
-
"string",
|
|
78888
|
-
"boolean",
|
|
78889
|
-
"number",
|
|
78890
|
-
"required",
|
|
78891
|
-
"optional",
|
|
78892
|
-
"undefined",
|
|
78893
|
-
"unknown",
|
|
78894
|
-
"function",
|
|
78895
|
-
"process",
|
|
78896
|
-
"request",
|
|
78897
|
-
"response",
|
|
78898
|
-
"password",
|
|
78899
|
-
"secret",
|
|
78900
|
-
"token",
|
|
78901
|
-
"tokens",
|
|
78902
|
-
"credential",
|
|
78903
|
-
"credentials",
|
|
78904
|
-
"bearer",
|
|
78905
|
-
"basic",
|
|
78906
|
-
"example",
|
|
78907
|
-
"redacted",
|
|
78908
|
-
"nullable",
|
|
78909
|
-
"readonly",
|
|
78910
|
-
"override",
|
|
78911
|
-
"abstract",
|
|
78912
|
-
"interface",
|
|
78913
|
-
"constant",
|
|
78914
|
-
"variable",
|
|
78915
|
-
"property",
|
|
78916
|
-
"parameter",
|
|
78917
|
-
"argument",
|
|
78918
|
-
"callback",
|
|
78919
|
-
"promise",
|
|
78920
|
-
"settings",
|
|
78921
|
-
"options",
|
|
78922
|
-
"default",
|
|
78923
|
-
"disabled",
|
|
78924
|
-
"enabled",
|
|
78925
|
-
"internal",
|
|
78926
|
-
"external",
|
|
78927
|
-
"protected",
|
|
78928
|
-
"provided",
|
|
78929
|
-
"resolved",
|
|
78930
|
-
"rejected",
|
|
78931
|
-
"expected",
|
|
78932
|
-
"received"
|
|
78933
|
-
]);
|
|
78934
|
-
function looksLikeSecretValue(raw2, quoted) {
|
|
78935
|
-
if (raw2.includes("${") || raw2.includes("{{") || raw2.includes("%(")) return false;
|
|
78936
|
-
if (raw2.startsWith(REDACTED_CREDENTIAL) || raw2.startsWith(REDACTED_EMAIL)) return false;
|
|
78937
|
-
const lower = raw2.toLowerCase();
|
|
78938
|
-
if (ASSIGNMENT_STOPWORDS.has(lower)) return false;
|
|
78939
|
-
if (quoted) return raw2.length >= 6;
|
|
78940
|
-
if (!/^[A-Za-z0-9+/=_-]{8,}$/.test(raw2)) return false;
|
|
78941
|
-
if (/\d/.test(raw2)) return true;
|
|
78942
|
-
if (raw2.length >= 12) return true;
|
|
78943
|
-
return /[a-z]/.test(raw2) && /[A-Z]/.test(raw2);
|
|
78944
|
-
}
|
|
78945
|
-
var CREDENTIAL_RULES = [
|
|
78946
|
-
// Private-key blocks, including ones a diff prefixes with `+`/`-` per line
|
|
78947
|
-
// and ones the diff context cut before the END line.
|
|
78948
|
-
{
|
|
78949
|
-
re: /-----BEGIN [A-Z ]*PRIVATE KEY(?: BLOCK)?-----(?:[ \t]*\r?\n[+\- ]?[A-Za-z0-9+/=]{16,}[ \t]*)*(?:[ \t]*\r?\n[+\- ]?-----END [A-Z ]*PRIVATE KEY(?: BLOCK)?-----)?/g,
|
|
78950
|
-
replace: cred
|
|
78951
|
-
},
|
|
78952
|
-
{ re: /\b(?:AKIA|ASIA)[0-9A-Z]{16,}\b/g, replace: cred },
|
|
78953
|
-
// AWS access key id
|
|
78954
|
-
{ re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, replace: cred },
|
|
78955
|
-
{ re: /\bgh[pousr]_[A-Za-z0-9]{30,}\b/g, replace: cred },
|
|
78956
|
-
{ re: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, replace: cred },
|
|
78957
|
-
{ re: /\bxox[abeprs]-[A-Za-z0-9-]{10,}\b/g, replace: cred },
|
|
78958
|
-
// Slack
|
|
78959
|
-
{ re: /\bsk-(?:ant-)?[A-Za-z0-9_-]{20,}\b/g, replace: cred },
|
|
78960
|
-
// OpenAI / Anthropic
|
|
78961
|
-
{ re: /\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{20,}\b/g, replace: cred },
|
|
78962
|
-
// Stripe
|
|
78963
|
-
{ re: /\brnd_[A-Za-z0-9]{20,}\b/g, replace: cred },
|
|
78964
|
-
// Render
|
|
78965
|
-
{ re: /\bnpm_[A-Za-z0-9]{36}\b/g, replace: cred },
|
|
78966
|
-
{ re: /\bAIza[0-9A-Za-z_-]{35}\b/g, replace: cred },
|
|
78967
|
-
// Google API key
|
|
78968
|
-
{ re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, replace: cred },
|
|
78969
|
-
// JWT
|
|
78970
|
-
{ re: /(?<![A-Za-z0-9])[A-Za-z0-9]{84}(?![A-Za-z0-9])/g, replace: cred },
|
|
78971
|
-
// Azure-shaped
|
|
78972
|
-
{
|
|
78973
|
-
re: /\b(Bearer|Basic|Token)(\s+)([A-Za-z0-9._~+/=-]{16,})/g,
|
|
78974
|
-
replace: (m) => `${m[1]}${m[2]}${REDACTED_CREDENTIAL}`
|
|
78975
|
-
},
|
|
78976
|
-
// Assignments after key-ish names: `password=...`, `API_KEY: "..."`,
|
|
78977
|
-
// `"client_secret": "..."`, `AWS_SECRET_ACCESS_KEY=...`, 32+ hex/base64 after
|
|
78978
|
-
// any of them. The value heuristic keeps `token: string` and
|
|
78979
|
-
// `password = process.env.X` intact.
|
|
78980
|
-
{
|
|
78981
|
-
re: /((?:[A-Za-z0-9_.-]*?)(?:password|passwd|passphrase|pwd|secret|token|api[_-]?key|apikey|access[_-]?key|private[_-]?key|auth[_-]?key|credential)(?:[A-Za-z0-9_-]*))(["']?\s*(?:=>|=|:)\s*)(["'`]?)([^\s"'`,;)}\]]+)/gi,
|
|
78982
|
-
replace: (m) => {
|
|
78983
|
-
const value = m[4] ?? "";
|
|
78984
|
-
const quote = m[3] ?? "";
|
|
78985
|
-
if (!looksLikeSecretValue(value, quote.length > 0)) return null;
|
|
78986
|
-
return `${m[1]}${m[2]}${quote}${REDACTED_CREDENTIAL}`;
|
|
78987
|
-
}
|
|
78988
|
-
}
|
|
78989
|
-
];
|
|
78990
|
-
var EMAIL_RE2 = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+\b/g;
|
|
78991
|
-
function applyRule(text, rule) {
|
|
78992
|
-
let count = 0;
|
|
78993
|
-
const out2 = text.replace(rule.re, (...args2) => {
|
|
78994
|
-
const m = args2.slice(0, -2);
|
|
78995
|
-
const r = rule.replace(m);
|
|
78996
|
-
if (r === null) return m[0];
|
|
78997
|
-
count += 1;
|
|
78998
|
-
return r;
|
|
78999
|
-
});
|
|
79000
|
-
return { text: out2, count };
|
|
79001
|
-
}
|
|
79002
|
-
function scrubText(text) {
|
|
79003
|
-
let out2 = text;
|
|
79004
|
-
let credentials = 0;
|
|
79005
|
-
for (const rule of CREDENTIAL_RULES) {
|
|
79006
|
-
const r = applyRule(out2, rule);
|
|
79007
|
-
out2 = r.text;
|
|
79008
|
-
credentials += r.count;
|
|
79009
|
-
}
|
|
79010
|
-
let emails = 0;
|
|
79011
|
-
out2 = out2.replace(EMAIL_RE2, () => {
|
|
79012
|
-
emails += 1;
|
|
79013
|
-
return REDACTED_EMAIL;
|
|
79014
|
-
});
|
|
79015
|
-
return { text: out2, credentials, emails };
|
|
79016
|
-
}
|
|
79017
79531
|
var TRAILER_KEYS = [
|
|
79018
79532
|
"signed-off-by",
|
|
79019
79533
|
"co-authored-by",
|
|
@@ -79135,12 +79649,18 @@ async function buildUnitBundle(root, unit, opts = {}) {
|
|
|
79135
79649
|
const rawDiff = await unitDiff(root, unit, diffPaths);
|
|
79136
79650
|
for (const p of headerPaths(rawDiff)) tokens.token(p);
|
|
79137
79651
|
const narrativeRaw = opts.narrative ?? [unit.subject.trim(), stripTrailers(unit.body)].filter((s) => s.length > 0).join("\n\n");
|
|
79138
|
-
const n =
|
|
79139
|
-
const fl =
|
|
79140
|
-
const d =
|
|
79141
|
-
|
|
79142
|
-
|
|
79143
|
-
|
|
79652
|
+
const n = scrubHistoryText(tokens.apply(stripTrailers(narrativeRaw)));
|
|
79653
|
+
const fl = scrubHistoryText(tokens.apply(fileListRaw));
|
|
79654
|
+
const d = scrubHistoryText(tokens.apply(rawDiff));
|
|
79655
|
+
const safe = scrubHistoryValue({
|
|
79656
|
+
narrative: tokens.apply(stripTrailers(narrativeRaw)),
|
|
79657
|
+
fileList: tokens.apply(fileListRaw),
|
|
79658
|
+
diff: tokens.apply(rawDiff),
|
|
79659
|
+
narrativeSources: opts.narrativeSources?.map((source) => ({ commitSha: source.commitSha, text: tokens.apply(stripTrailers(source.text)).trim() }))
|
|
79660
|
+
});
|
|
79661
|
+
let narrative2 = safe.narrative;
|
|
79662
|
+
let fileList = safe.fileList;
|
|
79663
|
+
let diff = safe.diff;
|
|
79144
79664
|
const separators = 2;
|
|
79145
79665
|
let prose = estimateTokens(narrative2) + estimateTokens(fileList) + separators;
|
|
79146
79666
|
if (prose > maxTokens) {
|
|
@@ -79159,6 +79679,7 @@ async function buildUnitBundle(root, unit, opts = {}) {
|
|
|
79159
79679
|
return {
|
|
79160
79680
|
sha: unit.sha,
|
|
79161
79681
|
narrative: narrative2,
|
|
79682
|
+
...safe.narrativeSources ? { narrativeSources: safe.narrativeSources.filter((source) => source.text.length > 0 && narrative2.includes(source.text)).slice(0, 64) } : {},
|
|
79162
79683
|
fileList,
|
|
79163
79684
|
diff,
|
|
79164
79685
|
tokenEstimate: estimateTokens(narrative2) + estimateTokens(fileList) + estimateTokens(diff) + separators,
|
|
@@ -79281,7 +79802,7 @@ var FileActivityReporter = class {
|
|
|
79281
79802
|
const current = this.options.binding();
|
|
79282
79803
|
if (!identity || this.stopped || !current.enabled || current.projectId !== binding.projectId)
|
|
79283
79804
|
return false;
|
|
79284
|
-
const hash2 =
|
|
79805
|
+
const hash2 = createHash17("sha256").update(JSON.stringify([identity, source, at, clean, operation, branch, previousBranch])).digest("hex");
|
|
79285
79806
|
const id = `${hash2.slice(0, 8)}-${hash2.slice(8, 12)}-5${hash2.slice(13, 16)}-8${hash2.slice(17, 20)}-${hash2.slice(20, 32)}`;
|
|
79286
79807
|
if (!this.pending.some((item) => item.event.id === id))
|
|
79287
79808
|
this.pending.push({
|
|
@@ -80338,7 +80859,7 @@ function createWatchBreaker(deps) {
|
|
|
80338
80859
|
}
|
|
80339
80860
|
|
|
80340
80861
|
// src/engine.ts
|
|
80341
|
-
var DAEMON_VERSION = true ? "2.0.13-dev.
|
|
80862
|
+
var DAEMON_VERSION = true ? "2.0.13-dev.3054" : "2.0.0-alpha.0";
|
|
80342
80863
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
80343
80864
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
80344
80865
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -82797,10 +83318,10 @@ init_registry();
|
|
|
82797
83318
|
init_identity2();
|
|
82798
83319
|
|
|
82799
83320
|
// src/instance-receipts.ts
|
|
82800
|
-
import { createHash as
|
|
83321
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
82801
83322
|
var FIELDS = ["contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
|
|
82802
83323
|
function instanceDestinationKey(input) {
|
|
82803
|
-
return
|
|
83324
|
+
return createHash18("sha256").update(JSON.stringify([
|
|
82804
83325
|
input.workspace,
|
|
82805
83326
|
input.cloudUrl.replace(/\/+$/, ""),
|
|
82806
83327
|
input.installationId ?? input.profileName ?? "default",
|
|
@@ -84282,6 +84803,69 @@ init_profile2();
|
|
|
84282
84803
|
init_src();
|
|
84283
84804
|
init_src11();
|
|
84284
84805
|
init_profile2();
|
|
84806
|
+
|
|
84807
|
+
// src/history-corrections.ts
|
|
84808
|
+
init_profile2();
|
|
84809
|
+
function applyHistoryCorrections(store, page) {
|
|
84810
|
+
let changed = 0;
|
|
84811
|
+
for (const correction of page.changes) {
|
|
84812
|
+
const key = `history-correction:${correction.nodeId}`;
|
|
84813
|
+
const previous = store.getMeta?.(key);
|
|
84814
|
+
if (!previous || Number(JSON.parse(previous).seq) < correction.seq) store.setMeta?.(key, JSON.stringify(correction));
|
|
84815
|
+
const current = store.getNode(correction.canonicalId) ?? store.getNode(correction.nodeId);
|
|
84816
|
+
if (!current) continue;
|
|
84817
|
+
const privacy = correction.action === "quarantine";
|
|
84818
|
+
const copies = privacy ? store.nodeHistory(current.logicalId ?? current.id) : [current];
|
|
84819
|
+
for (const node2 of copies) {
|
|
84820
|
+
if (node2.attrs["source"] !== "cloud" || node2.attrs["cloudNodeId"] && node2.attrs["cloudNodeId"] !== correction.nodeId || Number(node2.attrs["historyCorrectionSeq"] ?? 0) >= correction.seq) continue;
|
|
84821
|
+
const quality = { sourceSupport: correction.sourceSupport ?? (privacy ? "quarantined" : "unreviewed"), applicability: "unknown" };
|
|
84822
|
+
store.mergeNode({
|
|
84823
|
+
...node2,
|
|
84824
|
+
lastUpdatedAt: Date.now(),
|
|
84825
|
+
...privacy ? { description: "History source withdrawn.", embedding: [], isLandmark: false } : {},
|
|
84826
|
+
attrs: {
|
|
84827
|
+
...privacy ? {} : node2.attrs,
|
|
84828
|
+
source: "cloud",
|
|
84829
|
+
cloudNodeId: correction.nodeId,
|
|
84830
|
+
extractionSource: "history-mined",
|
|
84831
|
+
historyQuality: quality,
|
|
84832
|
+
historyCorrectionSeq: correction.seq
|
|
84833
|
+
}
|
|
84834
|
+
});
|
|
84835
|
+
if (privacy) for (const edge2 of [...store.inEdges(node2.id), ...store.outEdges(node2.id)]) {
|
|
84836
|
+
if (edge2.attrs["source"] === "cloud") store.mergeEdge({ ...edge2, attrs: { source: "cloud", historySourceWithdrawn: true } });
|
|
84837
|
+
}
|
|
84838
|
+
changed++;
|
|
84839
|
+
}
|
|
84840
|
+
}
|
|
84841
|
+
return changed;
|
|
84842
|
+
}
|
|
84843
|
+
async function syncHistoryCorrections(opts) {
|
|
84844
|
+
const { root, profile, store, cloud } = opts;
|
|
84845
|
+
if (!profile.projectId || !cloud.getProjectHistoryCorrections) return;
|
|
84846
|
+
let cursor = profile.projectHistoryCorrectionCursor ?? 0;
|
|
84847
|
+
for (let i2 = 0; i2 < 25; i2++) {
|
|
84848
|
+
const page = await cloud.getProjectHistoryCorrections(profile.projectId, cursor, 200);
|
|
84849
|
+
if (!Number.isSafeInteger(page.cursor) || page.cursor < cursor || !Array.isArray(page.changes) || page.changes.length > 200 || page.changes.some((c, j) => !Number.isSafeInteger(c.seq) || c.seq <= (page.changes[j - 1]?.seq ?? cursor) || c.seq > page.cursor || !["quarantine", "unreviewed"].includes(c.action) || c.sourceSupport !== void 0 && !["supported", "contradicted", "unreviewed", "quarantined"].includes(c.sourceSupport) || typeof c.nodeId !== "string" || typeof c.canonicalId !== "string")) {
|
|
84850
|
+
throw new Error("Invalid history correction page");
|
|
84851
|
+
}
|
|
84852
|
+
if (page.cursor !== (page.changes.at(-1)?.seq ?? cursor)) throw new Error("History correction cursor skipped a page");
|
|
84853
|
+
applyHistoryCorrections(store, page);
|
|
84854
|
+
for (const mirror of opts.mirrors ?? []) applyHistoryCorrections(mirror, page);
|
|
84855
|
+
if (page.changes.some((c) => c.sourceSupport === "supported")) {
|
|
84856
|
+
profile.projectAnchorCursor = 0;
|
|
84857
|
+
delete profile.historyRevisionCursor;
|
|
84858
|
+
}
|
|
84859
|
+
if (page.cursor > cursor) {
|
|
84860
|
+
cursor = page.cursor;
|
|
84861
|
+
profile.projectHistoryCorrectionCursor = cursor;
|
|
84862
|
+
saveProfile(root, profile);
|
|
84863
|
+
}
|
|
84864
|
+
if (page.changes.length < 200) break;
|
|
84865
|
+
}
|
|
84866
|
+
}
|
|
84867
|
+
|
|
84868
|
+
// src/project-reanchor.ts
|
|
84285
84869
|
var DEFAULT_LIMIT = 50;
|
|
84286
84870
|
var ANCHOR_SYMBOL_KINDS2 = [
|
|
84287
84871
|
"Function",
|
|
@@ -84497,6 +85081,7 @@ async function syncProjectAnchors(opts) {
|
|
|
84497
85081
|
let landed = 0;
|
|
84498
85082
|
let cursor = profile.projectAnchorCursor ?? 0;
|
|
84499
85083
|
try {
|
|
85084
|
+
await syncHistoryCorrections({ root, profile, store, cloud, ...opts.correctionMirrors ? { mirrors: opts.correctionMirrors } : {} });
|
|
84500
85085
|
for (let page = 0; page < maxPages; page++) {
|
|
84501
85086
|
const res = await cloud.getProjectAnchors(projectId, cursor, limit);
|
|
84502
85087
|
if (res.anchors.length === 0) break;
|
|
@@ -84611,13 +85196,109 @@ async function hydrateProject(opts) {
|
|
|
84611
85196
|
}
|
|
84612
85197
|
}
|
|
84613
85198
|
|
|
85199
|
+
// src/history-reconcile.ts
|
|
85200
|
+
init_src11();
|
|
85201
|
+
init_src();
|
|
85202
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
85203
|
+
import { promisify as promisify2 } from "node:util";
|
|
85204
|
+
import { extname as extname3 } from "node:path";
|
|
85205
|
+
init_profile2();
|
|
85206
|
+
var exec = promisify2(execFile4);
|
|
85207
|
+
var KINDS = { function: "Function", class: "Class", method: "Method", interface: "Interface", const: "Const", enum: "Enum", typealias: "TypeAlias", namespace: "Namespace", property: "Property" };
|
|
85208
|
+
async function syncHistoryRevision(opts) {
|
|
85209
|
+
const { root, profile, store, cloud, salt } = opts;
|
|
85210
|
+
if (!profile.projectId) return { changed: 0, remaining: false };
|
|
85211
|
+
const projectId = profile.projectId;
|
|
85212
|
+
const git3 = opts.git ?? (async (args2) => (await exec("git", ["-C", root, ...args2], { windowsHide: true, maxBuffer: 8 * 1024 * 1024 })).stdout);
|
|
85213
|
+
const atCommit = (await git3(["rev-parse", "--verify", "HEAD"])).trim();
|
|
85214
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(atCommit)) throw new Error("history revision is not a full Git object id");
|
|
85215
|
+
const oldCursor = profile.historyRevisionCursor;
|
|
85216
|
+
const same = oldCursor?.atCommit === atCommit;
|
|
85217
|
+
if (same && oldCursor.complete && Date.now() - oldCursor.updatedAt < 60 * 6e4) return { changed: 0, remaining: false };
|
|
85218
|
+
const after = same && !oldCursor.complete ? oldCursor.after : void 0;
|
|
85219
|
+
const page = await cloud.getHistoryOccurrences(projectId, atCommit, after);
|
|
85220
|
+
if (!Array.isArray(page.occurrences) || page.occurrences.length > 50 || page.occurrences.some((o, i2) => o.occurrenceId <= (page.occurrences[i2 - 1]?.occurrenceId ?? after ?? "")) || page.cursor !== null && page.cursor !== page.occurrences.at(-1)?.occurrenceId) throw new Error("invalid history occurrence page");
|
|
85221
|
+
const parents = (await git3(["rev-list", "--parents", "--max-count=8192", atCommit])).trim().split("\n").filter(Boolean).map((row) => {
|
|
85222
|
+
const [commit, ...parents2] = row.trim().split(/\s+/);
|
|
85223
|
+
return { commit, parents: parents2 };
|
|
85224
|
+
});
|
|
85225
|
+
const reverse = buildReverseSymbolMap({ store, projectId, salt });
|
|
85226
|
+
const ignore2 = loadRepoIgnore(root, profile.ignoreExtra ?? []);
|
|
85227
|
+
const providers = defaultProviders();
|
|
85228
|
+
const parsedFiles = /* @__PURE__ */ new Map();
|
|
85229
|
+
const observations = [];
|
|
85230
|
+
for (const occurrence of page.occurrences) {
|
|
85231
|
+
const anchors = occurrence.quality["historicalAnchors"];
|
|
85232
|
+
const paths = /* @__PURE__ */ new Set(), symbols = [];
|
|
85233
|
+
for (const anchor of anchors ?? []) {
|
|
85234
|
+
const localId = reverse.get(anchor.symbolId), local = localId ? store.getNode(localId) : null;
|
|
85235
|
+
const path2 = local?.attrs["relPath"];
|
|
85236
|
+
if (typeof path2 !== "string" || !pathAllowedByFloor(path2) || isPathBlocked(ignore2, path2) || /[\r\n]/.test(path2)) continue;
|
|
85237
|
+
paths.add(path2);
|
|
85238
|
+
if (!parsedFiles.has(path2)) {
|
|
85239
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
85240
|
+
parsedFiles.set(path2, hashes);
|
|
85241
|
+
const provider = providers.find((p) => p.fileExtensions.includes(extname3(path2).toLowerCase()));
|
|
85242
|
+
if (!provider) continue;
|
|
85243
|
+
const source2 = await git3(["show", `${atCommit}:${path2}`]).catch(() => null);
|
|
85244
|
+
if (source2 === null || Buffer.byteLength(source2) > 1e6 || source2.includes("\0")) continue;
|
|
85245
|
+
await provider.preload?.();
|
|
85246
|
+
for (const symbol2 of provider.extractSymbols(source2, path2)) {
|
|
85247
|
+
const kind = KINDS[symbol2.kind];
|
|
85248
|
+
if (kind && symbol2.bodyHash) hashes.set(projectSymbolId(salt, projectId, path2, symbol2.qname ?? symbol2.name, kind), symbol2.bodyHash);
|
|
85249
|
+
}
|
|
85250
|
+
}
|
|
85251
|
+
const bodyHash = parsedFiles.get(path2).get(anchor.symbolId);
|
|
85252
|
+
if (bodyHash) symbols.push({ symbolId: anchor.symbolId, bodyHash });
|
|
85253
|
+
}
|
|
85254
|
+
const source = occurrenceSourceCommit(occurrence);
|
|
85255
|
+
let diff;
|
|
85256
|
+
if (source && source !== atCommit && paths.size) {
|
|
85257
|
+
const bundle = await buildUnitBundle(root, {
|
|
85258
|
+
sha: atCommit,
|
|
85259
|
+
parents: [source],
|
|
85260
|
+
isMerge: true,
|
|
85261
|
+
index: 0,
|
|
85262
|
+
subIndex: 0,
|
|
85263
|
+
subject: "",
|
|
85264
|
+
body: "",
|
|
85265
|
+
authorDate: "",
|
|
85266
|
+
files: [...paths].map((path2) => ({ path: path2, adds: 1, dels: 1, binary: false }))
|
|
85267
|
+
}, { maxTokens: 4e3, ignorePatterns: profile.ignoreExtra ?? [] }).catch(() => null);
|
|
85268
|
+
if (bundle && !bundle.truncated) diff = bundle.diff;
|
|
85269
|
+
}
|
|
85270
|
+
observations.push({ occurrenceId: occurrence.occurrenceId, symbols, ...diff ? { diff } : {} });
|
|
85271
|
+
}
|
|
85272
|
+
const response = page.occurrences.length ? await cloud.reconcileHistory(projectId, { atCommit, parents, observations }) : { atCommit, receipts: [] };
|
|
85273
|
+
if (response.atCommit !== atCommit || response.receipts.length !== page.occurrences.length || new Set(response.receipts.map((r) => r.occurrenceId)).size !== response.receipts.length || response.receipts.some((r) => r.atCommit !== atCommit || !observations.some((o) => o.occurrenceId === r.occurrenceId))) throw new Error("incomplete history reconciliation response");
|
|
85274
|
+
if ((await git3(["rev-parse", "--verify", "HEAD"])).trim() !== atCommit) return { changed: 0, remaining: true };
|
|
85275
|
+
let changed = 0;
|
|
85276
|
+
for (const occurrence of page.occurrences) {
|
|
85277
|
+
const node2 = store.getNode(occurrence.canonicalId) ?? (occurrence.nodeId ? store.getNode(occurrence.nodeId) : null);
|
|
85278
|
+
if (!node2 || node2.attrs["source"] !== "cloud" || node2.attrs["historyQuality"]?.["sourceSupport"] === "quarantined") continue;
|
|
85279
|
+
const receipt = response.receipts.find((r) => r.occurrenceId === occurrence.occurrenceId);
|
|
85280
|
+
const previous = node2.attrs["historyQuality"];
|
|
85281
|
+
if (previous?.["evaluatedAtCommit"] === atCommit && previous["applicability"] === "applicable" && receipt.verdict !== "applicable") continue;
|
|
85282
|
+
store.mergeNode({ ...node2, attrs: { ...node2.attrs, historyQuality: {
|
|
85283
|
+
...occurrence.quality,
|
|
85284
|
+
evaluatedAtCommit: atCommit,
|
|
85285
|
+
applicability: receipt.verdict,
|
|
85286
|
+
reconciliationEvidence: receipt.evidence
|
|
85287
|
+
} } });
|
|
85288
|
+
changed++;
|
|
85289
|
+
}
|
|
85290
|
+
profile.historyRevisionCursor = { atCommit, ...page.cursor ? { after: page.cursor } : {}, complete: page.cursor === null, updatedAt: Date.now() };
|
|
85291
|
+
(opts.save ?? ((p) => saveProfile(root, p)))(profile);
|
|
85292
|
+
return { changed, remaining: page.cursor !== null };
|
|
85293
|
+
}
|
|
85294
|
+
|
|
84614
85295
|
// src/project-history.ts
|
|
84615
85296
|
init_src7();
|
|
84616
85297
|
init_src();
|
|
84617
|
-
import { execFile as
|
|
85298
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
84618
85299
|
import { readFileSync as readFileSync32 } from "node:fs";
|
|
84619
85300
|
import { join as join37 } from "node:path";
|
|
84620
|
-
import { promisify as
|
|
85301
|
+
import { promisify as promisify3 } from "node:util";
|
|
84621
85302
|
|
|
84622
85303
|
// src/history-walk.ts
|
|
84623
85304
|
var LOCKFILE_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -84935,10 +85616,13 @@ function message(u) {
|
|
|
84935
85616
|
${u.body}` : u.subject;
|
|
84936
85617
|
}
|
|
84937
85618
|
function narrative(unit, group) {
|
|
84938
|
-
|
|
85619
|
+
return narrativeSources(unit, group).map((source) => source.text).join("\n\n");
|
|
85620
|
+
}
|
|
85621
|
+
function narrativeSources(unit, group) {
|
|
85622
|
+
if (!group || group.length === 0) return [{ commitSha: unit.sha, text: message(unit).trim() }].filter((s) => s.text.length > 0);
|
|
84939
85623
|
const members = group.filter((g) => g.groupSha === (unit.groupSha ?? unit.sha)).sort((a, b) => a.subIndex - b.subIndex);
|
|
84940
85624
|
const source = members.length > 0 ? members : [...group].sort((a, b) => a.subIndex - b.subIndex);
|
|
84941
|
-
return source.map(
|
|
85625
|
+
return source.map((member) => ({ commitSha: member.sha, text: message(member).trim() })).filter((s) => s.text.length > 0);
|
|
84942
85626
|
}
|
|
84943
85627
|
|
|
84944
85628
|
// src/git-batch.ts
|
|
@@ -85042,13 +85726,116 @@ var GitBlobReader = class {
|
|
|
85042
85726
|
}
|
|
85043
85727
|
};
|
|
85044
85728
|
|
|
85729
|
+
// src/history-anchors.ts
|
|
85730
|
+
init_src11();
|
|
85731
|
+
init_src();
|
|
85732
|
+
import { extname as extname4 } from "node:path";
|
|
85733
|
+
var LABELS = {
|
|
85734
|
+
function: "Function",
|
|
85735
|
+
class: "Class",
|
|
85736
|
+
method: "Method",
|
|
85737
|
+
interface: "Interface",
|
|
85738
|
+
const: "Const",
|
|
85739
|
+
enum: "Enum",
|
|
85740
|
+
typealias: "TypeAlias",
|
|
85741
|
+
namespace: "Namespace",
|
|
85742
|
+
property: "Property"
|
|
85743
|
+
};
|
|
85744
|
+
var MAX_SOURCE_BYTES = 1e6;
|
|
85745
|
+
var MAX_ANCHORS = 20;
|
|
85746
|
+
async function historicalAnchors(input) {
|
|
85747
|
+
if (!/^[a-f0-9]{40,64}$/.test(input.unit.sha)) return void 0;
|
|
85748
|
+
const ignore2 = loadRepoIgnore(input.root, input.ignorePatterns);
|
|
85749
|
+
const providers = input.providers ?? defaultProviders();
|
|
85750
|
+
const beforeTokens = /* @__PURE__ */ new Map();
|
|
85751
|
+
for (const line of input.bundle.diff.split("\n")) {
|
|
85752
|
+
const m = /^diff --git a\/(p\d+) b\/(p\d+)$/.exec(line);
|
|
85753
|
+
if (m) beforeTokens.set(m[2], m[1]);
|
|
85754
|
+
}
|
|
85755
|
+
const parsed = /* @__PURE__ */ new Map();
|
|
85756
|
+
const parse4 = (commit, token) => {
|
|
85757
|
+
const path2 = input.bundle.pathTokens[token];
|
|
85758
|
+
if (!path2 || /[\r\n]/.test(path2) || !pathAllowedByFloor(path2) || isPathBlocked(ignore2, path2)) return Promise.resolve(null);
|
|
85759
|
+
const provider = providers.find((p) => p.fileExtensions.includes(extname4(path2).toLowerCase()));
|
|
85760
|
+
if (!provider) return Promise.resolve(null);
|
|
85761
|
+
const spec = `${commit}:${path2}`;
|
|
85762
|
+
if (!parsed.has(spec)) parsed.set(spec, (async () => {
|
|
85763
|
+
try {
|
|
85764
|
+
const source = await input.readBlob(spec);
|
|
85765
|
+
if (source === null || source.includes("\0") || Buffer.byteLength(source) > MAX_SOURCE_BYTES) return null;
|
|
85766
|
+
await provider.preload?.();
|
|
85767
|
+
const symbols = provider.extractSymbols(source, path2).filter((s) => LABELS[s.kind] && s.startByte >= 0 && s.endByte > s.startByte);
|
|
85768
|
+
const offsets = [0];
|
|
85769
|
+
for (let i2 = 0; i2 < source.length; i2++) if (source[i2] === "\n") offsets.push(i2 + 1);
|
|
85770
|
+
offsets.push(source.length + 1);
|
|
85771
|
+
return { symbols, offsets };
|
|
85772
|
+
} catch {
|
|
85773
|
+
return null;
|
|
85774
|
+
}
|
|
85775
|
+
})());
|
|
85776
|
+
return parsed.get(spec);
|
|
85777
|
+
};
|
|
85778
|
+
const out2 = {};
|
|
85779
|
+
const blocks = historySourceBlocks({ narrative: "", diff: input.bundle.diff, commitSha: input.unit.sha });
|
|
85780
|
+
for (const block of blocks) {
|
|
85781
|
+
if (block.kind !== "diff" || !block.pathToken) continue;
|
|
85782
|
+
const lines = block.text.split("\n");
|
|
85783
|
+
const header = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(lines[0]);
|
|
85784
|
+
if (!header) continue;
|
|
85785
|
+
let before = Number(header[1]), after = Number(header[2]);
|
|
85786
|
+
let offset = Buffer.byteLength(lines[0]) + 1;
|
|
85787
|
+
const list = out2[block.pathToken] ?? [];
|
|
85788
|
+
for (const line of lines.slice(1)) {
|
|
85789
|
+
const end = offset + Buffer.byteLength(line);
|
|
85790
|
+
const side = line[0] === "+" ? "after" : line[0] === "-" ? "before" : null;
|
|
85791
|
+
if (side) {
|
|
85792
|
+
const commit = side === "after" ? input.unit.sha : input.unit.parents[0];
|
|
85793
|
+
const token = side === "after" ? block.pathToken : beforeTokens.get(block.pathToken);
|
|
85794
|
+
if (commit && /^[a-f0-9]{40,64}$/.test(commit) && token) {
|
|
85795
|
+
const file2 = await parse4(commit, token);
|
|
85796
|
+
const row = (side === "after" ? after : before) - 1;
|
|
85797
|
+
const start2 = file2?.offsets[row], stop2 = file2?.offsets[row + 1];
|
|
85798
|
+
if (file2 && start2 !== void 0 && stop2 !== void 0) {
|
|
85799
|
+
const symbols = file2.symbols.filter((s) => s.startByte < stop2 && s.endByte > start2).sort((a, b) => a.endByte - a.startByte - (b.endByte - b.startByte));
|
|
85800
|
+
const symbol2 = symbols[0];
|
|
85801
|
+
if (symbol2) {
|
|
85802
|
+
const kind = LABELS[symbol2.kind];
|
|
85803
|
+
const symbolId = projectSymbolId(input.salt, input.projectId, input.bundle.pathTokens[token], symbol2.qname ?? symbol2.name, kind);
|
|
85804
|
+
const prev = list.at(-1);
|
|
85805
|
+
if (prev?.symbolId === symbolId && prev.historical?.side === side && prev.historical.blockDigest === block.digest && prev.historical.endByte + 1 === offset) {
|
|
85806
|
+
prev.historical.endByte = end;
|
|
85807
|
+
} else if (list.length < MAX_ANCHORS) list.push({
|
|
85808
|
+
symbolId,
|
|
85809
|
+
kind,
|
|
85810
|
+
historical: {
|
|
85811
|
+
sourceCommitSha: input.unit.sha,
|
|
85812
|
+
commitSha: commit,
|
|
85813
|
+
side,
|
|
85814
|
+
blockDigest: block.digest,
|
|
85815
|
+
startByte: offset,
|
|
85816
|
+
endByte: end,
|
|
85817
|
+
...symbol2.bodyHash ? { bodyHash: symbol2.bodyHash } : {}
|
|
85818
|
+
}
|
|
85819
|
+
});
|
|
85820
|
+
}
|
|
85821
|
+
}
|
|
85822
|
+
}
|
|
85823
|
+
}
|
|
85824
|
+
if (line[0] === " " || line[0] === "-") before++;
|
|
85825
|
+
if (line[0] === " " || line[0] === "+") after++;
|
|
85826
|
+
offset = end + 1;
|
|
85827
|
+
}
|
|
85828
|
+
if (list.length) out2[block.pathToken] = list;
|
|
85829
|
+
}
|
|
85830
|
+
return Object.keys(out2).length ? out2 : void 0;
|
|
85831
|
+
}
|
|
85832
|
+
|
|
85045
85833
|
// src/project-history.ts
|
|
85046
85834
|
init_profile2();
|
|
85047
|
-
var execFileAsync2 =
|
|
85835
|
+
var execFileAsync2 = promisify3(execFile5);
|
|
85048
85836
|
var HISTORY_EXTRACTOR_VERSION = "history-2";
|
|
85049
85837
|
var LEASE_POLL_MS = 2e4;
|
|
85050
85838
|
var RECOVERY_DEADLINE_MS = 15 * 6e4;
|
|
85051
|
-
var MAX_ANCHORS_PER_TOKEN = 20;
|
|
85052
85839
|
var DEFAULT_LOOKAHEAD = 2;
|
|
85053
85840
|
async function defaultGit(root, args2) {
|
|
85054
85841
|
const { stdout } = await execFileAsync2("git", ["-C", root, ...args2], { maxBuffer: 64 * 1024 * 1024, windowsHide: true });
|
|
@@ -85099,27 +85886,6 @@ async function spineForUnit(git3, root, unit, readBlob) {
|
|
|
85099
85886
|
const wire = (d) => ({ ecosystem: d.ecosystem, name: d.name, version: d.version, kind: d.kind, manifest: d.manifest });
|
|
85100
85887
|
return { declared: rings.declared.map(wire), context: rings.context.map(wire) };
|
|
85101
85888
|
}
|
|
85102
|
-
function anchorsFor(pathTokens, ignoreLines, projectId, anchors) {
|
|
85103
|
-
if (!anchors) return void 0;
|
|
85104
|
-
const out2 = {};
|
|
85105
|
-
const ignored = (p) => ignoreLines.some((rule) => p === rule || p.startsWith(rule.replace(/\/+$/, "") + "/"));
|
|
85106
|
-
for (const [token, relPath] of Object.entries(pathTokens)) {
|
|
85107
|
-
if (ignored(relPath)) continue;
|
|
85108
|
-
const nodes = anchors.index.nodesByRelPath([relPath]);
|
|
85109
|
-
const list = [];
|
|
85110
|
-
for (const n of nodes) {
|
|
85111
|
-
const qname = n.attrs["qname"];
|
|
85112
|
-
if (typeof qname !== "string") continue;
|
|
85113
|
-
list.push({
|
|
85114
|
-
symbolId: projectSymbolId(anchors.salt, projectId, relPath, qname, n.label),
|
|
85115
|
-
kind: n.label
|
|
85116
|
-
});
|
|
85117
|
-
if (list.length >= MAX_ANCHORS_PER_TOKEN) break;
|
|
85118
|
-
}
|
|
85119
|
-
if (list.length > 0) out2[token] = list;
|
|
85120
|
-
}
|
|
85121
|
-
return Object.keys(out2).length > 0 ? out2 : void 0;
|
|
85122
|
-
}
|
|
85123
85889
|
function stage(profile, patch, now) {
|
|
85124
85890
|
const at = now().toISOString();
|
|
85125
85891
|
const prev = profile.historyStage;
|
|
@@ -85137,6 +85903,7 @@ function stage(profile, patch, now) {
|
|
|
85137
85903
|
// keep showing the error it recovered from); an absent key keeps it.
|
|
85138
85904
|
..."lastError" in patch ? patch.lastError ? { lastError: patch.lastError } : {} : prev?.lastError ? { lastError: prev.lastError } : {},
|
|
85139
85905
|
...patch.counts ? { counts: patch.counts } : prev?.counts ? { counts: prev.counts } : {},
|
|
85906
|
+
...patch.coverageGaps ? { coverageGaps: patch.coverageGaps } : prev?.coverageGaps ? { coverageGaps: prev.coverageGaps } : {},
|
|
85140
85907
|
...patch.backfillAnchor ? { backfillAnchor: patch.backfillAnchor } : prev?.backfillAnchor ? { backfillAnchor: prev.backfillAnchor } : {}
|
|
85141
85908
|
}
|
|
85142
85909
|
};
|
|
@@ -85156,7 +85923,7 @@ function unitTiming(postStarted, prepMs, receipt) {
|
|
|
85156
85923
|
}
|
|
85157
85924
|
function addCounts(a, b) {
|
|
85158
85925
|
const sum = (k) => (a[k] ?? 0) + (b[k] ?? 0);
|
|
85159
|
-
return { commitsWalked: sum("commitsWalked"), changesExtracted: sum("changesExtracted"), pairs: sum("pairs"), claims: sum("claims"), anchors: sum("anchors"), packages: sum("packages") };
|
|
85926
|
+
return { commitsWalked: sum("commitsWalked"), changesExtracted: sum("changesExtracted"), pairs: sum("pairs"), claims: sum("claims"), anchors: sum("anchors"), packages: sum("packages"), deferredUnits: sum("deferredUnits") };
|
|
85160
85927
|
}
|
|
85161
85928
|
async function runHistoryWalk(root, input, client, opts = {}) {
|
|
85162
85929
|
const reader = opts.git ? null : new GitBlobReader(root);
|
|
@@ -85198,7 +85965,12 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85198
85965
|
return { profile, processed: 0, state: "refused" };
|
|
85199
85966
|
}
|
|
85200
85967
|
if (units.length === 0) {
|
|
85201
|
-
|
|
85968
|
+
const deferred = profile.historyStage?.counts?.deferredUnits ?? 0;
|
|
85969
|
+
profile = stage(profile, {
|
|
85970
|
+
state: "done",
|
|
85971
|
+
watermarkSha: headSha,
|
|
85972
|
+
...deferred > 0 ? { lastError: `${deferred} history units deferred; coverage gaps require source review and re-extraction.` } : {}
|
|
85973
|
+
}, now);
|
|
85202
85974
|
persist(profile);
|
|
85203
85975
|
await reportHistoryStage(client, profile, log);
|
|
85204
85976
|
return { profile, processed: 0, state: "done" };
|
|
@@ -85227,7 +85999,8 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85227
85999
|
const group = byIndex.get(u.index) ?? [u];
|
|
85228
86000
|
const bundle = await buildUnitBundle(root, u, {
|
|
85229
86001
|
ignorePatterns: ignoreLines,
|
|
85230
|
-
narrative: narrative(u, u.isMerge ? group : void 0)
|
|
86002
|
+
narrative: narrative(u, u.isMerge ? group : void 0),
|
|
86003
|
+
narrativeSources: narrativeSources(u, u.isMerge ? group : void 0)
|
|
85231
86004
|
});
|
|
85232
86005
|
const prev = dryRun ? void 0 : predecessor(k);
|
|
85233
86006
|
const body2 = {
|
|
@@ -85240,6 +86013,7 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85240
86013
|
...u.authorDate ? { authorDate: u.authorDate } : {}
|
|
85241
86014
|
},
|
|
85242
86015
|
narrative: bundle.narrative,
|
|
86016
|
+
...bundle.narrativeSources?.length ? { narrativeSources: bundle.narrativeSources } : {},
|
|
85243
86017
|
fileList: bundle.fileList,
|
|
85244
86018
|
diff: bundle.diff,
|
|
85245
86019
|
pathTokens: Object.keys(bundle.pathTokens),
|
|
@@ -85251,7 +86025,15 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85251
86025
|
};
|
|
85252
86026
|
const spine = await spineForUnit(git3, root, u, readBlob);
|
|
85253
86027
|
if (spine) body2.spine = spine;
|
|
85254
|
-
const anchors =
|
|
86028
|
+
const anchors = opts.anchors ? await historicalAnchors({
|
|
86029
|
+
root,
|
|
86030
|
+
projectId,
|
|
86031
|
+
salt: opts.anchors.salt,
|
|
86032
|
+
unit: u,
|
|
86033
|
+
bundle,
|
|
86034
|
+
ignorePatterns: ignoreLines,
|
|
86035
|
+
readBlob
|
|
86036
|
+
}) : void 0;
|
|
85255
86037
|
if (anchors) body2.anchors = anchors;
|
|
85256
86038
|
return { body: body2, prepMs: Date.now() - prepStarted };
|
|
85257
86039
|
})();
|
|
@@ -85384,6 +86166,15 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85384
86166
|
return { profile, processed, state: "refused" };
|
|
85385
86167
|
case "rejected":
|
|
85386
86168
|
case "error":
|
|
86169
|
+
if (outcome.status === "error" && outcome.parked && outcome.runId && ["deferred-context", "deferred-budget"].includes(outcome.errorCode ?? "")) {
|
|
86170
|
+
const gaps = [...profile.historyStage?.coverageGaps ?? []];
|
|
86171
|
+
const known = gaps.some((g) => g.runId === outcome.runId);
|
|
86172
|
+
counts = addCounts(counts, { commitsWalked: 1, deferredUnits: known ? 0 : 1 });
|
|
86173
|
+
if (!known) gaps.push({ sha: u.sha, subIndex: u.subIndex, runId: outcome.runId, reason: outcome.errorCode });
|
|
86174
|
+
profile = stage(profile, { coverageGaps: gaps.slice(-1e3) }, now);
|
|
86175
|
+
log(`[errata] history ${label}: deferred (${outcome.errorCode}); coverage gap retained as ${outcome.runId}`);
|
|
86176
|
+
break;
|
|
86177
|
+
}
|
|
85387
86178
|
profile = stage(profile, { state: "paused", lastError: `unit ${label} ${outcome.status}: ${outcome.error.slice(0, 200)}` }, now);
|
|
85388
86179
|
persist(profile);
|
|
85389
86180
|
await reportHistoryStage(client, profile, log);
|
|
@@ -85394,7 +86185,11 @@ async function walk10(root, input, client, opts, readBlob) {
|
|
|
85394
86185
|
processed += 1;
|
|
85395
86186
|
}
|
|
85396
86187
|
const reachedHead = (profile.historyStage?.unitsDone ?? 0) >= total;
|
|
85397
|
-
profile = stage(profile, reachedHead ? {
|
|
86188
|
+
profile = stage(profile, reachedHead ? {
|
|
86189
|
+
state: "done",
|
|
86190
|
+
watermarkSha: headSha,
|
|
86191
|
+
...(counts.deferredUnits ?? 0) > 0 ? { lastError: `${counts.deferredUnits} history units deferred; coverage gaps require source review and re-extraction.` } : {}
|
|
86192
|
+
} : { state: dryRun ? "extracting" : "contributing" }, now);
|
|
85398
86193
|
persist(profile);
|
|
85399
86194
|
await reportHistoryStage(client, profile, log);
|
|
85400
86195
|
return { profile, processed, state: profile.historyStage?.state ?? "done" };
|
|
@@ -85477,7 +86272,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
|
|
|
85477
86272
|
|
|
85478
86273
|
// src/link-flow.ts
|
|
85479
86274
|
init_cloud_auth();
|
|
85480
|
-
import { createHash as
|
|
86275
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
85481
86276
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
85482
86277
|
import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
|
|
85483
86278
|
import { join as join38 } from "node:path";
|
|
@@ -85771,7 +86566,7 @@ async function loginOAuthLoopback(opts) {
|
|
|
85771
86566
|
|
|
85772
86567
|
// src/link-flow.ts
|
|
85773
86568
|
function remoteFingerprint(locator) {
|
|
85774
|
-
return
|
|
86569
|
+
return createHash19("sha256").update(locator).digest("hex");
|
|
85775
86570
|
}
|
|
85776
86571
|
function isDecision(value) {
|
|
85777
86572
|
if (!value || typeof value !== "object") return false;
|
|
@@ -87057,13 +87852,24 @@ async function startMultiDaemon(opts = {}) {
|
|
|
87057
87852
|
});
|
|
87058
87853
|
const pullProjectAnchors = async (r, client, salt) => {
|
|
87059
87854
|
const donePass = markPass(`anchor-pull:${r.engine.profile.name}`);
|
|
87855
|
+
const beforeCorrections = r.engine.profile.projectHistoryCorrectionCursor ?? 0;
|
|
87060
87856
|
const sync = await syncProjectAnchors({
|
|
87061
87857
|
root: r.root,
|
|
87062
87858
|
profile: r.engine.profile,
|
|
87063
87859
|
store: r.engine.store,
|
|
87860
|
+
correctionMirrors: [sharedStore],
|
|
87064
87861
|
cloud: client,
|
|
87065
87862
|
salt
|
|
87066
87863
|
}).finally(donePass);
|
|
87864
|
+
if ((r.engine.profile.projectHistoryCorrectionCursor ?? 0) > beforeCorrections) {
|
|
87865
|
+
for (const record2 of records) record2.engine.markContextDirty();
|
|
87866
|
+
}
|
|
87867
|
+
try {
|
|
87868
|
+
const revision = await syncHistoryRevision({ root: r.root, profile: r.engine.profile, store: r.engine.store, cloud: client, salt });
|
|
87869
|
+
if (revision.changed) r.engine.markContextDirty();
|
|
87870
|
+
} catch (err2) {
|
|
87871
|
+
console.warn(`[errata] history revision reconciliation failed for ${r.engine.profile.name}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
87872
|
+
}
|
|
87067
87873
|
if (sync.synced) {
|
|
87068
87874
|
if (sync.anchors + sync.updated > 0) {
|
|
87069
87875
|
r.engine.markContextDirty();
|