@inerrata-corporation/errata 2.0.14-dev.3081 → 2.0.14-dev.3125
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 +89 -0
- package/errata.mjs +238 -82
- package/package.json +1 -1
- package/pass-worker.mjs +95 -6
package/consolidate-worker.mjs
CHANGED
|
@@ -16188,6 +16188,71 @@ function installHistoryCacheFloor(db) {
|
|
|
16188
16188
|
});
|
|
16189
16189
|
}
|
|
16190
16190
|
|
|
16191
|
+
// ../../packages/local-graph/src/session-evidence.ts
|
|
16192
|
+
function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
|
|
16193
|
+
const mapping = new Map(aliases);
|
|
16194
|
+
const uuid3 = "[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}";
|
|
16195
|
+
const codex = new RegExp(`^codex:(?:rollout-.*?)?(${uuid3})$`, "i");
|
|
16196
|
+
const arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
|
|
16197
|
+
const scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
|
|
16198
|
+
const discover = (value, key = "") => {
|
|
16199
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
16200
|
+
const match = value.match(codex);
|
|
16201
|
+
if (match) {
|
|
16202
|
+
const canonical = `codex:${match[1].toLowerCase()}`;
|
|
16203
|
+
mapping.set(value, canonical);
|
|
16204
|
+
mapping.set(match[1].toLowerCase(), canonical);
|
|
16205
|
+
}
|
|
16206
|
+
} else if (Array.isArray(value)) value.forEach((v) => discover(v, key));
|
|
16207
|
+
else if (value && typeof value === "object") {
|
|
16208
|
+
for (const [k, v] of Object.entries(value)) discover(v, key === "citeAnchorHints" ? key : k);
|
|
16209
|
+
}
|
|
16210
|
+
};
|
|
16211
|
+
discover(input);
|
|
16212
|
+
const rewrite = (value, key = "") => {
|
|
16213
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
16214
|
+
return mapping.get(value) ?? mapping.get(value.toLowerCase()) ?? value;
|
|
16215
|
+
}
|
|
16216
|
+
if (Array.isArray(value)) {
|
|
16217
|
+
const values = value.map((v) => rewrite(v, key));
|
|
16218
|
+
return arrays.has(key) || key === "citeAnchorHints" ? [...new Set(values)] : values;
|
|
16219
|
+
}
|
|
16220
|
+
if (!value || typeof value !== "object") return value;
|
|
16221
|
+
const before = value;
|
|
16222
|
+
const after = Object.fromEntries(Object.entries(before).map(([k, v]) => [k, rewrite(v, key === "citeAnchorHints" ? key : k)]));
|
|
16223
|
+
for (const field of ["sources", "contributors"]) {
|
|
16224
|
+
const old = before[field], next = after[field];
|
|
16225
|
+
if (!Array.isArray(old) || !Array.isArray(next) || old.length <= next.length) continue;
|
|
16226
|
+
after["sessionAliasRepair"] = { originalCount: old.length, distinctCount: next.length };
|
|
16227
|
+
if (field === "sources" && typeof after["corroborations"] === "number") {
|
|
16228
|
+
after["corroborations"] = Math.min(after["corroborations"], Math.max(0, next.length - 1));
|
|
16229
|
+
if (after["corroborations"] === 0) after["provisional"] = true;
|
|
16230
|
+
}
|
|
16231
|
+
if (field === "contributors" && typeof after["confirmed"] === "number") {
|
|
16232
|
+
after["preAliasRepairConfirmed"] = after["confirmed"];
|
|
16233
|
+
after["confirmed"] = Math.min(after["confirmed"], next.length);
|
|
16234
|
+
}
|
|
16235
|
+
}
|
|
16236
|
+
return after;
|
|
16237
|
+
};
|
|
16238
|
+
const repaired = rewrite(input);
|
|
16239
|
+
const source = repaired["discriminatorSource"];
|
|
16240
|
+
if (typeof source === "string") {
|
|
16241
|
+
const global = repaired["perContext"]?.["*"];
|
|
16242
|
+
const contributors = Array.isArray(global?.["contributors"]) ? global["contributors"] : [];
|
|
16243
|
+
const inferred = new Set(Array.isArray(global?.["inferredContributors"]) ? global["inferredContributors"] : []);
|
|
16244
|
+
if (contributors.includes(source) || contributors.filter((id) => !inferred.has(id)).length < 2) {
|
|
16245
|
+
repaired["withdrawnDiscriminator"] = repaired["discriminator"];
|
|
16246
|
+
repaired["discriminatorWithdrawalReason"] = "insufficient-independent-witnesses";
|
|
16247
|
+
repaired["provisional"] = true;
|
|
16248
|
+
delete repaired["discriminator"];
|
|
16249
|
+
delete repaired["discriminatorSource"];
|
|
16250
|
+
delete repaired["discriminatorAsked"];
|
|
16251
|
+
}
|
|
16252
|
+
}
|
|
16253
|
+
return repaired;
|
|
16254
|
+
}
|
|
16255
|
+
|
|
16191
16256
|
// ../../packages/local-graph/src/store.ts
|
|
16192
16257
|
var LOCAL_RULE_OVERRIDES = {
|
|
16193
16258
|
ANCHORED_AT: {
|
|
@@ -16432,6 +16497,12 @@ var SqliteGraphStore = class {
|
|
|
16432
16497
|
}
|
|
16433
16498
|
this.db.exec(TEMPORAL_INDEX_SQL);
|
|
16434
16499
|
installHistoryCacheFloor(this.db);
|
|
16500
|
+
if (!this.db.prepare("SELECT value FROM store_meta WHERE key = 'session-evidence-v1'").get()) {
|
|
16501
|
+
this.db.transaction(() => {
|
|
16502
|
+
this.repairSessionAliases();
|
|
16503
|
+
this.db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES ('session-evidence-v1', 'done')").run();
|
|
16504
|
+
});
|
|
16505
|
+
}
|
|
16435
16506
|
this.stmts = {
|
|
16436
16507
|
insertNode: this.db.prepare(`
|
|
16437
16508
|
INSERT INTO nodes (
|
|
@@ -16680,6 +16751,23 @@ var SqliteGraphStore = class {
|
|
|
16680
16751
|
this.db.prepare("UPDATE schema_version SET version = ?").run(SCHEMA_VERSION);
|
|
16681
16752
|
});
|
|
16682
16753
|
}
|
|
16754
|
+
repairSessionAliases(canonical, aliases = []) {
|
|
16755
|
+
const mapping = new Map(aliases.map((alias) => [alias, canonical]));
|
|
16756
|
+
let changed = 0;
|
|
16757
|
+
for (const table of ["nodes", "edges"]) {
|
|
16758
|
+
const predicates = canonical ? aliases.map(() => "instr(attrs_json, ?) > 0") : ["instr(attrs_json, 'codex:') > 0", "instr(attrs_json, 'discriminatorSource') > 0"];
|
|
16759
|
+
if (!predicates.length) continue;
|
|
16760
|
+
const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE ${predicates.join(" OR ")}`).all(...canonical ? aliases : []);
|
|
16761
|
+
const update = this.db.prepare(`UPDATE ${table} SET attrs_json = ?${table === "edges" ? ", type = CASE WHEN type = 'CONFIRMS' AND json_extract(?, '$.provisional') = 1 THEN 'INDICATES' ELSE type END" : ""} WHERE id = ?`);
|
|
16762
|
+
for (const row of rows) {
|
|
16763
|
+
const attrs = JSON.stringify(repairSessionEvidence(JSON.parse(row.attrs_json), mapping));
|
|
16764
|
+
if (attrs === row.attrs_json) continue;
|
|
16765
|
+
update.run(...table === "edges" ? [attrs, attrs, row.id] : [attrs, row.id]);
|
|
16766
|
+
changed++;
|
|
16767
|
+
}
|
|
16768
|
+
}
|
|
16769
|
+
return changed;
|
|
16770
|
+
}
|
|
16683
16771
|
deleteNode(id) {
|
|
16684
16772
|
this.stmts.deleteNode.run(id);
|
|
16685
16773
|
}
|
|
@@ -17761,6 +17849,7 @@ function recordTriageObservation(l2, obs, ts) {
|
|
|
17761
17849
|
}
|
|
17762
17850
|
const discriminator = obs.discriminator ?? existing?.attrs["discriminator"];
|
|
17763
17851
|
const attrs = {
|
|
17852
|
+
...existing?.attrs,
|
|
17764
17853
|
driftKind: obs.driftKind ?? existing?.attrs["driftKind"] ?? DRIFT_KIND.RELOCATION,
|
|
17765
17854
|
perContext,
|
|
17766
17855
|
// A discriminator (now or previously supplied) promotes the route to a router.
|
package/errata.mjs
CHANGED
|
@@ -15495,10 +15495,9 @@ function looksLikeSecretValue(raw2, quoted) {
|
|
|
15495
15495
|
if (quoted) return raw2.length > 0;
|
|
15496
15496
|
const lower = raw2.toLowerCase();
|
|
15497
15497
|
if (ASSIGNMENT_STOPWORDS.has(lower)) return false;
|
|
15498
|
-
if (
|
|
15499
|
-
if (
|
|
15500
|
-
|
|
15501
|
-
return /[a-z]/.test(raw2) && /[A-Z]/.test(raw2);
|
|
15498
|
+
if (/^(?:process\.env\.|os\.environ(?:\[|\.)|(?:request|response|config|settings|options)\.)/.test(raw2)) return false;
|
|
15499
|
+
if (/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\(/.test(raw2)) return false;
|
|
15500
|
+
return raw2.length > 0;
|
|
15502
15501
|
}
|
|
15503
15502
|
function applyRule(text, rule, removed) {
|
|
15504
15503
|
let count = 0;
|
|
@@ -15564,7 +15563,7 @@ var HISTORY_SCRUBBER_VERSION, REDACTED_CREDENTIAL, REDACTED_EMAIL, cred, ASSIGNM
|
|
|
15564
15563
|
var init_history_text = __esm({
|
|
15565
15564
|
"../../packages/shared/src/history-text.ts"() {
|
|
15566
15565
|
"use strict";
|
|
15567
|
-
HISTORY_SCRUBBER_VERSION = "history-scrub-
|
|
15566
|
+
HISTORY_SCRUBBER_VERSION = "history-scrub-4";
|
|
15568
15567
|
REDACTED_CREDENTIAL = "[redacted:credential]";
|
|
15569
15568
|
REDACTED_EMAIL = "[redacted:email]";
|
|
15570
15569
|
cred = () => REDACTED_CREDENTIAL;
|
|
@@ -15639,9 +15638,15 @@ var init_history_text = __esm({
|
|
|
15639
15638
|
},
|
|
15640
15639
|
// Userinfo in connection URLs must be removed before the email rule runs.
|
|
15641
15640
|
{
|
|
15642
|
-
re: /\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]
|
|
15641
|
+
re: /\b([a-z][a-z0-9+.-]*:\/\/)([^\s/@:]*):([^\s/@]+)@/gi,
|
|
15643
15642
|
replace: (m) => m[2] === "[redacted" && m[3] === "credential]" ? null : `${m[1]}${REDACTED_CREDENTIAL}@`
|
|
15644
15643
|
},
|
|
15644
|
+
// MySQL's short password option attaches the value directly to -p; other
|
|
15645
|
+
// command flags (such as a port) must not be treated as passwords.
|
|
15646
|
+
{
|
|
15647
|
+
re: /\b((?:mysql|mariadb)(?:\s+[^\s]+)*?\s+-p)([^\s"'`,;)}\]]+)/gi,
|
|
15648
|
+
replace: (m) => m[2]?.startsWith("[redacted:") ? null : `${m[1]}${REDACTED_CREDENTIAL}`
|
|
15649
|
+
},
|
|
15645
15650
|
// Seeded login prose commonly writes email/password without an assignment.
|
|
15646
15651
|
{
|
|
15647
15652
|
re: /(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+|\[redacted:email\])(\s*\/\s*)(["'\x60]?)([^\s"'\x60,;)}\]]+)/gi,
|
|
@@ -18002,6 +18007,76 @@ var init_history_cache_floor = __esm({
|
|
|
18002
18007
|
}
|
|
18003
18008
|
});
|
|
18004
18009
|
|
|
18010
|
+
// ../../packages/local-graph/src/session-evidence.ts
|
|
18011
|
+
function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
|
|
18012
|
+
const mapping = new Map(aliases);
|
|
18013
|
+
const uuid3 = "[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}";
|
|
18014
|
+
const codex = new RegExp(`^codex:(?:rollout-.*?)?(${uuid3})$`, "i");
|
|
18015
|
+
const arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
|
|
18016
|
+
const scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
|
|
18017
|
+
const discover = (value, key = "") => {
|
|
18018
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
18019
|
+
const match2 = value.match(codex);
|
|
18020
|
+
if (match2) {
|
|
18021
|
+
const canonical = `codex:${match2[1].toLowerCase()}`;
|
|
18022
|
+
mapping.set(value, canonical);
|
|
18023
|
+
mapping.set(match2[1].toLowerCase(), canonical);
|
|
18024
|
+
}
|
|
18025
|
+
} else if (Array.isArray(value)) value.forEach((v) => discover(v, key));
|
|
18026
|
+
else if (value && typeof value === "object") {
|
|
18027
|
+
for (const [k, v] of Object.entries(value)) discover(v, key === "citeAnchorHints" ? key : k);
|
|
18028
|
+
}
|
|
18029
|
+
};
|
|
18030
|
+
discover(input);
|
|
18031
|
+
const rewrite = (value, key = "") => {
|
|
18032
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
18033
|
+
return mapping.get(value) ?? mapping.get(value.toLowerCase()) ?? value;
|
|
18034
|
+
}
|
|
18035
|
+
if (Array.isArray(value)) {
|
|
18036
|
+
const values = value.map((v) => rewrite(v, key));
|
|
18037
|
+
return arrays.has(key) || key === "citeAnchorHints" ? [...new Set(values)] : values;
|
|
18038
|
+
}
|
|
18039
|
+
if (!value || typeof value !== "object") return value;
|
|
18040
|
+
const before = value;
|
|
18041
|
+
const after = Object.fromEntries(Object.entries(before).map(([k, v]) => [k, rewrite(v, key === "citeAnchorHints" ? key : k)]));
|
|
18042
|
+
for (const field of ["sources", "contributors"]) {
|
|
18043
|
+
const old = before[field], next = after[field];
|
|
18044
|
+
if (!Array.isArray(old) || !Array.isArray(next) || old.length <= next.length) continue;
|
|
18045
|
+
after["sessionAliasRepair"] = { originalCount: old.length, distinctCount: next.length };
|
|
18046
|
+
if (field === "sources" && typeof after["corroborations"] === "number") {
|
|
18047
|
+
after["corroborations"] = Math.min(after["corroborations"], Math.max(0, next.length - 1));
|
|
18048
|
+
if (after["corroborations"] === 0) after["provisional"] = true;
|
|
18049
|
+
}
|
|
18050
|
+
if (field === "contributors" && typeof after["confirmed"] === "number") {
|
|
18051
|
+
after["preAliasRepairConfirmed"] = after["confirmed"];
|
|
18052
|
+
after["confirmed"] = Math.min(after["confirmed"], next.length);
|
|
18053
|
+
}
|
|
18054
|
+
}
|
|
18055
|
+
return after;
|
|
18056
|
+
};
|
|
18057
|
+
const repaired = rewrite(input);
|
|
18058
|
+
const source = repaired["discriminatorSource"];
|
|
18059
|
+
if (typeof source === "string") {
|
|
18060
|
+
const global2 = repaired["perContext"]?.["*"];
|
|
18061
|
+
const contributors = Array.isArray(global2?.["contributors"]) ? global2["contributors"] : [];
|
|
18062
|
+
const inferred = new Set(Array.isArray(global2?.["inferredContributors"]) ? global2["inferredContributors"] : []);
|
|
18063
|
+
if (contributors.includes(source) || contributors.filter((id) => !inferred.has(id)).length < 2) {
|
|
18064
|
+
repaired["withdrawnDiscriminator"] = repaired["discriminator"];
|
|
18065
|
+
repaired["discriminatorWithdrawalReason"] = "insufficient-independent-witnesses";
|
|
18066
|
+
repaired["provisional"] = true;
|
|
18067
|
+
delete repaired["discriminator"];
|
|
18068
|
+
delete repaired["discriminatorSource"];
|
|
18069
|
+
delete repaired["discriminatorAsked"];
|
|
18070
|
+
}
|
|
18071
|
+
}
|
|
18072
|
+
return repaired;
|
|
18073
|
+
}
|
|
18074
|
+
var init_session_evidence = __esm({
|
|
18075
|
+
"../../packages/local-graph/src/session-evidence.ts"() {
|
|
18076
|
+
"use strict";
|
|
18077
|
+
}
|
|
18078
|
+
});
|
|
18079
|
+
|
|
18005
18080
|
// ../../packages/local-graph/src/store.ts
|
|
18006
18081
|
function localEdgeViolation(fromLabel, type, toLabel) {
|
|
18007
18082
|
if (type in LOCAL_RULE_OVERRIDES) {
|
|
@@ -18085,6 +18160,7 @@ var init_store = __esm({
|
|
|
18085
18160
|
init_src2();
|
|
18086
18161
|
init_src();
|
|
18087
18162
|
init_history_cache_floor();
|
|
18163
|
+
init_session_evidence();
|
|
18088
18164
|
LOCAL_RULE_OVERRIDES = {
|
|
18089
18165
|
ANCHORED_AT: {
|
|
18090
18166
|
from: EDGE_RULES["ANCHORED_AT"]?.from,
|
|
@@ -18256,6 +18332,12 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
|
|
|
18256
18332
|
}
|
|
18257
18333
|
this.db.exec(TEMPORAL_INDEX_SQL);
|
|
18258
18334
|
installHistoryCacheFloor(this.db);
|
|
18335
|
+
if (!this.db.prepare("SELECT value FROM store_meta WHERE key = 'session-evidence-v1'").get()) {
|
|
18336
|
+
this.db.transaction(() => {
|
|
18337
|
+
this.repairSessionAliases();
|
|
18338
|
+
this.db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES ('session-evidence-v1', 'done')").run();
|
|
18339
|
+
});
|
|
18340
|
+
}
|
|
18259
18341
|
this.stmts = {
|
|
18260
18342
|
insertNode: this.db.prepare(`
|
|
18261
18343
|
INSERT INTO nodes (
|
|
@@ -18504,6 +18586,23 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
|
|
|
18504
18586
|
this.db.prepare("UPDATE schema_version SET version = ?").run(SCHEMA_VERSION);
|
|
18505
18587
|
});
|
|
18506
18588
|
}
|
|
18589
|
+
repairSessionAliases(canonical, aliases = []) {
|
|
18590
|
+
const mapping = new Map(aliases.map((alias) => [alias, canonical]));
|
|
18591
|
+
let changed = 0;
|
|
18592
|
+
for (const table of ["nodes", "edges"]) {
|
|
18593
|
+
const predicates = canonical ? aliases.map(() => "instr(attrs_json, ?) > 0") : ["instr(attrs_json, 'codex:') > 0", "instr(attrs_json, 'discriminatorSource') > 0"];
|
|
18594
|
+
if (!predicates.length) continue;
|
|
18595
|
+
const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE ${predicates.join(" OR ")}`).all(...canonical ? aliases : []);
|
|
18596
|
+
const update = this.db.prepare(`UPDATE ${table} SET attrs_json = ?${table === "edges" ? ", type = CASE WHEN type = 'CONFIRMS' AND json_extract(?, '$.provisional') = 1 THEN 'INDICATES' ELSE type END" : ""} WHERE id = ?`);
|
|
18597
|
+
for (const row of rows) {
|
|
18598
|
+
const attrs = JSON.stringify(repairSessionEvidence(JSON.parse(row.attrs_json), mapping));
|
|
18599
|
+
if (attrs === row.attrs_json) continue;
|
|
18600
|
+
update.run(...table === "edges" ? [attrs, attrs, row.id] : [attrs, row.id]);
|
|
18601
|
+
changed++;
|
|
18602
|
+
}
|
|
18603
|
+
}
|
|
18604
|
+
return changed;
|
|
18605
|
+
}
|
|
18507
18606
|
deleteNode(id) {
|
|
18508
18607
|
this.stmts.deleteNode.run(id);
|
|
18509
18608
|
}
|
|
@@ -23022,6 +23121,7 @@ function recordTriageObservation(l2, obs, ts) {
|
|
|
23022
23121
|
}
|
|
23023
23122
|
const discriminator = obs.discriminator ?? existing?.attrs["discriminator"];
|
|
23024
23123
|
const attrs = {
|
|
23124
|
+
...existing?.attrs,
|
|
23025
23125
|
driftKind: obs.driftKind ?? existing?.attrs["driftKind"] ?? DRIFT_KIND.RELOCATION,
|
|
23026
23126
|
perContext,
|
|
23027
23127
|
// A discriminator (now or previously supplied) promotes the route to a router.
|
|
@@ -23260,7 +23360,7 @@ function induceTriage(l2, opts) {
|
|
|
23260
23360
|
return report;
|
|
23261
23361
|
}
|
|
23262
23362
|
function pendingDiscriminators(l2, opts = {}) {
|
|
23263
|
-
const minSources = opts.minSources ??
|
|
23363
|
+
const minSources = opts.minSources ?? 2;
|
|
23264
23364
|
const minObservations = opts.minObservations ?? 2;
|
|
23265
23365
|
const out2 = [];
|
|
23266
23366
|
for (const triage of l2.findNodesByLabel("Triage")) {
|
|
@@ -23295,6 +23395,12 @@ function promoteRouteWithDiscriminator(l2, routeId, discriminator, ts, source) {
|
|
|
23295
23395
|
if (isUnfilledPlaceholder(test)) return false;
|
|
23296
23396
|
const existing = l2.getEdge(routeId);
|
|
23297
23397
|
if (!existing || !ROUTE_EDGE_TYPES.includes(existing.type)) return false;
|
|
23398
|
+
const global2 = (existing.attrs["perContext"] ?? {})[TRIAGE_GLOBAL_BUCKET] ?? {};
|
|
23399
|
+
const contributors = new Set(global2.contributors ?? []);
|
|
23400
|
+
const inferred = new Set(global2.inferredContributors ?? []);
|
|
23401
|
+
const witnesses = [...contributors].filter((id) => !inferred.has(id));
|
|
23402
|
+
if (!source || contributors.has(source) || witnesses.length < 2) return false;
|
|
23403
|
+
if (existing.attrs["discriminator"] && existing.attrs["discriminator"] !== test) return false;
|
|
23298
23404
|
const attrs = {
|
|
23299
23405
|
...existing.attrs,
|
|
23300
23406
|
discriminator: test,
|
|
@@ -24860,8 +24966,8 @@ var init_src5 = __esm({
|
|
|
24860
24966
|
});
|
|
24861
24967
|
|
|
24862
24968
|
// ../../packages/context-writer/src/render.ts
|
|
24863
|
-
function isPassiveInjectable(node2) {
|
|
24864
|
-
if (!historyReadPolicy(node2, { mode: "passive" }).allow) return false;
|
|
24969
|
+
function isPassiveInjectable(node2, atCommit) {
|
|
24970
|
+
if (!historyReadPolicy(node2, { mode: "passive", atCommit }).allow) return false;
|
|
24865
24971
|
if (node2.label === "Pattern" || node2.label === "Technique" || node2.label === "AntiPattern") {
|
|
24866
24972
|
return true;
|
|
24867
24973
|
}
|
|
@@ -24871,7 +24977,7 @@ function isPassiveInjectable(node2) {
|
|
|
24871
24977
|
return false;
|
|
24872
24978
|
}
|
|
24873
24979
|
function buildSnapshot(opts) {
|
|
24874
|
-
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive" }).allow);
|
|
24980
|
+
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
|
|
24875
24981
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
24876
24982
|
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
24877
24983
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
@@ -24901,11 +25007,11 @@ function buildSnapshot(opts) {
|
|
|
24901
25007
|
...opts.store.findNodesByLabel("Pattern"),
|
|
24902
25008
|
...opts.store.findNodesByLabel("Technique"),
|
|
24903
25009
|
...opts.store.findNodesByLabel("AntiPattern")
|
|
24904
|
-
].filter((n) => historyReadPolicy(n, { mode: "passive" }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
24905
|
-
const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile) : void 0;
|
|
25010
|
+
].filter((n) => historyReadPolicy(n, { mode: "passive", atCommit: opts.atCommit }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
25011
|
+
const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile, opts.atCommit) : void 0;
|
|
24906
25012
|
const byEpisode = /* @__PURE__ */ new Map();
|
|
24907
25013
|
for (const sol of opts.store.findNodesByLabel("Solution")) {
|
|
24908
|
-
if (!historyReadPolicy(sol, { mode: "passive" }).allow) continue;
|
|
25014
|
+
if (!historyReadPolicy(sol, { mode: "passive", atCommit: opts.atCommit }).allow) continue;
|
|
24909
25015
|
if (sol.attrs["enrichmentPending"] !== true) continue;
|
|
24910
25016
|
const ep = sol.attrs["episodeId"] ?? sol.id;
|
|
24911
25017
|
const list = byEpisode.get(ep) ?? [];
|
|
@@ -24977,7 +25083,7 @@ function buildSnapshot(opts) {
|
|
|
24977
25083
|
generatedAt: (opts.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
24978
25084
|
};
|
|
24979
25085
|
}
|
|
24980
|
-
function sliceForFile(store, relPath) {
|
|
25086
|
+
function sliceForFile(store, relPath, atCommit) {
|
|
24981
25087
|
const candidates = store.findNodesByLabel("File");
|
|
24982
25088
|
const file2 = candidates.find((n) => n.description === relPath);
|
|
24983
25089
|
if (!file2) return void 0;
|
|
@@ -25016,7 +25122,7 @@ function sliceForFile(store, relPath) {
|
|
|
25016
25122
|
}
|
|
25017
25123
|
const fp = priorsForFile(store, relPath);
|
|
25018
25124
|
if (fp) {
|
|
25019
|
-
const allowed = (n) => historyReadPolicy(n, { mode: "passive" }).allow;
|
|
25125
|
+
const allowed = (n) => historyReadPolicy(n, { mode: "passive", atCommit }).allow;
|
|
25020
25126
|
fp.openProblems = fp.openProblems.filter(allowed);
|
|
25021
25127
|
fp.constraints = fp.constraints.filter(allowed);
|
|
25022
25128
|
fp.resolvedProblems = fp.resolvedProblems.filter(allowed);
|
|
@@ -25426,6 +25532,7 @@ function budgetSnapshot(s, maxChars) {
|
|
|
25426
25532
|
function assembleAgentContext(opts) {
|
|
25427
25533
|
const snapshot = opts.snapshot ?? buildSnapshot({
|
|
25428
25534
|
store: opts.store,
|
|
25535
|
+
atCommit: opts.atCommit,
|
|
25429
25536
|
profile: opts.profile,
|
|
25430
25537
|
reviewCount: opts.reviewCount,
|
|
25431
25538
|
reviewUiUrl: opts.reviewUiUrl,
|
|
@@ -25441,7 +25548,7 @@ function assembleAgentContext(opts) {
|
|
|
25441
25548
|
if (opts.remote && opts.remote.length > 0) {
|
|
25442
25549
|
const seen = /* @__PURE__ */ new Set();
|
|
25443
25550
|
const remote = opts.remote.filter((n) => {
|
|
25444
|
-
if (!isPassiveInjectable(n)) return false;
|
|
25551
|
+
if (!isPassiveInjectable(n, opts.atCommit)) return false;
|
|
25445
25552
|
if (opts.store.getNode(n.id)) return false;
|
|
25446
25553
|
if (seen.has(n.id)) return false;
|
|
25447
25554
|
seen.add(n.id);
|
|
@@ -25643,7 +25750,7 @@ function selectDurableMemory(store, profile, opts = {}) {
|
|
|
25643
25750
|
const minContributors = opts.minContributors ?? 1;
|
|
25644
25751
|
const wsLangs = new Set(profile.languages.map((l) => l.toLowerCase()));
|
|
25645
25752
|
return store.findNodesByLabel("Claim").filter(
|
|
25646
|
-
(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
|
|
25753
|
+
(n) => historyReadPolicy(n, { mode: "passive", atCommit: opts.atCommit }).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
|
|
25647
25754
|
// language-scoped principle only bleeds into repos that USE that language —
|
|
25648
25755
|
// so a Python principle never lands a dead `**/*.py` rule in a TS repo.
|
|
25649
25756
|
(scopeLangOf(n) == null || wsLangs.has(scopeLangOf(n)))
|
|
@@ -31158,26 +31265,26 @@ function buildFileLexicon(store) {
|
|
|
31158
31265
|
for (const n of store.findNodesByLabel("File")) {
|
|
31159
31266
|
const relPath = typeof n.attrs["relPath"] === "string" && n.attrs["relPath"].length > 0 ? n.attrs["relPath"] : n.description;
|
|
31160
31267
|
if (!relPath) continue;
|
|
31161
|
-
const
|
|
31162
|
-
if (!
|
|
31163
|
-
entries.push({ relPath, basename:
|
|
31164
|
-
basenameCount.set(
|
|
31165
|
-
const stem =
|
|
31268
|
+
const basename9 = relPath.split("/").pop();
|
|
31269
|
+
if (!basename9.includes(".")) continue;
|
|
31270
|
+
entries.push({ relPath, basename: basename9 });
|
|
31271
|
+
basenameCount.set(basename9, (basenameCount.get(basename9) ?? 0) + 1);
|
|
31272
|
+
const stem = basename9.slice(0, basename9.indexOf("."));
|
|
31166
31273
|
if (isBareMatchableStem(stem)) {
|
|
31167
31274
|
let s = stemRelPaths.get(stem);
|
|
31168
31275
|
if (!s) stemRelPaths.set(stem, s = /* @__PURE__ */ new Set());
|
|
31169
31276
|
s.add(relPath);
|
|
31170
31277
|
}
|
|
31171
31278
|
}
|
|
31172
|
-
for (const { relPath, basename:
|
|
31279
|
+
for (const { relPath, basename: basename9 } of entries) {
|
|
31173
31280
|
const entry = { relPath };
|
|
31174
|
-
if (relPath !==
|
|
31175
|
-
const conventional = CONVENTION_FILENAMES.has(
|
|
31176
|
-
if (!conventional && !byKey.has(
|
|
31177
|
-
const list = byBasename.get(
|
|
31281
|
+
if (relPath !== basename9) byKey.set(relPath, entry);
|
|
31282
|
+
const conventional = CONVENTION_FILENAMES.has(basename9) || (basenameCount.get(basename9) ?? 0) >= CONVENTION_BASENAME_MIN_FILES;
|
|
31283
|
+
if (!conventional && !byKey.has(basename9)) byKey.set(basename9, entry);
|
|
31284
|
+
const list = byBasename.get(basename9);
|
|
31178
31285
|
if (list) list.push(entry);
|
|
31179
|
-
else byBasename.set(
|
|
31180
|
-
const stem =
|
|
31286
|
+
else byBasename.set(basename9, [entry]);
|
|
31287
|
+
const stem = basename9.slice(0, basename9.indexOf("."));
|
|
31181
31288
|
if (isBareMatchableStem(stem) && !CONVENTION_STEMS.has(stem) && !byStem.has(stem)) {
|
|
31182
31289
|
const dirStems = new Set(
|
|
31183
31290
|
[...stemRelPaths.get(stem) ?? []].map((p) => {
|
|
@@ -31194,8 +31301,8 @@ function resolveFileToken(token, lexicon) {
|
|
|
31194
31301
|
const exact = lexicon.byKey.get(token);
|
|
31195
31302
|
if (exact) return exact;
|
|
31196
31303
|
if (!token.includes("/")) return null;
|
|
31197
|
-
const
|
|
31198
|
-
for (const entry of lexicon.byBasename.get(
|
|
31304
|
+
const basename9 = token.split("/").pop();
|
|
31305
|
+
for (const entry of lexicon.byBasename.get(basename9) ?? []) {
|
|
31199
31306
|
if (entry.relPath === token || entry.relPath.endsWith(`/${token}`)) return entry;
|
|
31200
31307
|
}
|
|
31201
31308
|
return null;
|
|
@@ -31220,9 +31327,9 @@ function fileRolePhrase(relPath, level = 1) {
|
|
|
31220
31327
|
return "a source file";
|
|
31221
31328
|
}
|
|
31222
31329
|
function isSourceFileToken(token) {
|
|
31223
|
-
const
|
|
31224
|
-
if (CONVENTION_FILENAMES.has(
|
|
31225
|
-
const ext =
|
|
31330
|
+
const basename9 = token.split(/[/\\]/).pop() ?? token;
|
|
31331
|
+
if (CONVENTION_FILENAMES.has(basename9)) return false;
|
|
31332
|
+
const ext = basename9.split(".").pop();
|
|
31226
31333
|
return ext !== void 0 && SOURCE_EXTENSIONS.has(ext.toLowerCase());
|
|
31227
31334
|
}
|
|
31228
31335
|
function generalizeFileRefs(text, fileLexicon, level = 1) {
|
|
@@ -72758,7 +72865,7 @@ init_config();
|
|
|
72758
72865
|
// src/engine.ts
|
|
72759
72866
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
72760
72867
|
import { existsSync as existsSync25, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "node:fs";
|
|
72761
|
-
import { join as join34, relative as relative6, sep as sep4 } from "node:path";
|
|
72868
|
+
import { basename as basename7, join as join34, relative as relative6, sep as sep4 } from "node:path";
|
|
72762
72869
|
|
|
72763
72870
|
// src/source-watcher.ts
|
|
72764
72871
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
@@ -72918,10 +73025,10 @@ var ReaddirpStream = class extends Readable2 {
|
|
|
72918
73025
|
}
|
|
72919
73026
|
async _formatEntry(dirent, path2) {
|
|
72920
73027
|
let entry;
|
|
72921
|
-
const
|
|
73028
|
+
const basename9 = this._isDirent ? dirent.name : dirent;
|
|
72922
73029
|
try {
|
|
72923
|
-
const fullPath = presolve(pjoin(path2,
|
|
72924
|
-
entry = { path: prelative(this._root, fullPath), fullPath, basename:
|
|
73030
|
+
const fullPath = presolve(pjoin(path2, basename9));
|
|
73031
|
+
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename9 };
|
|
72925
73032
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
72926
73033
|
} catch (err2) {
|
|
72927
73034
|
this._onError(err2);
|
|
@@ -73460,9 +73567,9 @@ var NodeFsHandler = class {
|
|
|
73460
73567
|
_watchWithNodeFs(path2, listener) {
|
|
73461
73568
|
const opts = this.fsw.options;
|
|
73462
73569
|
const directory = sysPath.dirname(path2);
|
|
73463
|
-
const
|
|
73570
|
+
const basename9 = sysPath.basename(path2);
|
|
73464
73571
|
const parent = this.fsw._getWatchedDir(directory);
|
|
73465
|
-
parent.add(
|
|
73572
|
+
parent.add(basename9);
|
|
73466
73573
|
const absolutePath = sysPath.resolve(path2);
|
|
73467
73574
|
const options = {
|
|
73468
73575
|
persistent: opts.persistent
|
|
@@ -73472,7 +73579,7 @@ var NodeFsHandler = class {
|
|
|
73472
73579
|
let closer;
|
|
73473
73580
|
if (opts.usePolling) {
|
|
73474
73581
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
73475
|
-
options.interval = enableBin && isBinaryPath(
|
|
73582
|
+
options.interval = enableBin && isBinaryPath(basename9) ? opts.binaryInterval : opts.interval;
|
|
73476
73583
|
closer = setFsWatchFileListener(path2, absolutePath, options, {
|
|
73477
73584
|
listener,
|
|
73478
73585
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -73495,10 +73602,10 @@ var NodeFsHandler = class {
|
|
|
73495
73602
|
return;
|
|
73496
73603
|
}
|
|
73497
73604
|
const dirname14 = sysPath.dirname(file2);
|
|
73498
|
-
const
|
|
73605
|
+
const basename9 = sysPath.basename(file2);
|
|
73499
73606
|
const parent = this.fsw._getWatchedDir(dirname14);
|
|
73500
73607
|
let prevStats = stats;
|
|
73501
|
-
if (parent.has(
|
|
73608
|
+
if (parent.has(basename9))
|
|
73502
73609
|
return;
|
|
73503
73610
|
const listener = async (path2, newStats) => {
|
|
73504
73611
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
@@ -73523,9 +73630,9 @@ var NodeFsHandler = class {
|
|
|
73523
73630
|
prevStats = newStats2;
|
|
73524
73631
|
}
|
|
73525
73632
|
} catch (error48) {
|
|
73526
|
-
this.fsw._remove(dirname14,
|
|
73633
|
+
this.fsw._remove(dirname14, basename9);
|
|
73527
73634
|
}
|
|
73528
|
-
} else if (parent.has(
|
|
73635
|
+
} else if (parent.has(basename9)) {
|
|
73529
73636
|
const at = newStats.atimeMs;
|
|
73530
73637
|
const mt = newStats.mtimeMs;
|
|
73531
73638
|
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
@@ -74805,6 +74912,16 @@ import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync
|
|
|
74805
74912
|
import { basename as basename5, delimiter, dirname as dirname10, join as join20, normalize as normalize3 } from "node:path";
|
|
74806
74913
|
import { homedir as homedir4 } from "node:os";
|
|
74807
74914
|
import { createHash as createHash16 } from "node:crypto";
|
|
74915
|
+
function completeJsonlPrefix(buf) {
|
|
74916
|
+
const end = buf.lastIndexOf(10) + 1;
|
|
74917
|
+
if (end === buf.length) return end;
|
|
74918
|
+
try {
|
|
74919
|
+
JSON.parse(buf.subarray(end).toString("utf8"));
|
|
74920
|
+
return buf.length;
|
|
74921
|
+
} catch {
|
|
74922
|
+
return end;
|
|
74923
|
+
}
|
|
74924
|
+
}
|
|
74808
74925
|
function readFrom(path2, fromByte, maxBytes) {
|
|
74809
74926
|
let fd;
|
|
74810
74927
|
try {
|
|
@@ -74821,11 +74938,12 @@ function readFrom(path2, fromByte, maxBytes) {
|
|
|
74821
74938
|
for (; ; ) {
|
|
74822
74939
|
const len = Math.min(cap, remaining);
|
|
74823
74940
|
const buf = Buffer.allocUnsafe(len);
|
|
74824
|
-
readSync(fd, buf, 0, len, start2);
|
|
74825
|
-
if (len >= remaining) {
|
|
74826
|
-
|
|
74941
|
+
const read2 = readSync(fd, buf, 0, len, start2);
|
|
74942
|
+
if (len >= remaining || read2 < len) {
|
|
74943
|
+
const end = completeJsonlPrefix(buf.subarray(0, read2));
|
|
74944
|
+
return { text: buf.subarray(0, end).toString("utf8"), nextOffset: start2 + end, more: false, ioFailed: false };
|
|
74827
74945
|
}
|
|
74828
|
-
const nl = buf.lastIndexOf(10);
|
|
74946
|
+
const nl = buf.subarray(0, read2).lastIndexOf(10);
|
|
74829
74947
|
if (nl >= 0) {
|
|
74830
74948
|
return {
|
|
74831
74949
|
text: buf.subarray(0, nl + 1).toString("utf8"),
|
|
@@ -74842,41 +74960,30 @@ function readFrom(path2, fromByte, maxBytes) {
|
|
|
74842
74960
|
closeSync(fd);
|
|
74843
74961
|
}
|
|
74844
74962
|
}
|
|
74845
|
-
function transcriptSize(path2) {
|
|
74846
|
-
try {
|
|
74847
|
-
const fd = openSync(path2, "r");
|
|
74848
|
-
try {
|
|
74849
|
-
return fstatSync(fd).size;
|
|
74850
|
-
} finally {
|
|
74851
|
-
closeSync(fd);
|
|
74852
|
-
}
|
|
74853
|
-
} catch {
|
|
74854
|
-
return 0;
|
|
74855
|
-
}
|
|
74856
|
-
}
|
|
74857
74963
|
function readTail(path2, maxBytes) {
|
|
74858
74964
|
return readTailWithLosses(path2, maxBytes).text;
|
|
74859
74965
|
}
|
|
74860
|
-
function readTailWithLosses(path2, maxBytes) {
|
|
74966
|
+
function readTailWithLosses(path2, maxBytes, completeLinesOnly = false) {
|
|
74861
74967
|
let fd;
|
|
74862
74968
|
try {
|
|
74863
74969
|
fd = openSync(path2, "r");
|
|
74864
74970
|
} catch {
|
|
74865
|
-
return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
|
|
74971
|
+
return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true, nextOffset: 0 };
|
|
74866
74972
|
}
|
|
74867
74973
|
try {
|
|
74868
74974
|
const size = fstatSync(fd).size;
|
|
74869
74975
|
const start2 = Math.max(0, size - maxBytes);
|
|
74870
74976
|
const len = size - start2;
|
|
74871
|
-
if (len <= 0) return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: false };
|
|
74977
|
+
if (len <= 0) return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: false, nextOffset: 0 };
|
|
74872
74978
|
const buf = Buffer.allocUnsafe(len);
|
|
74873
|
-
readSync(fd, buf, 0, len, start2);
|
|
74874
|
-
const
|
|
74979
|
+
const read2 = readSync(fd, buf, 0, len, start2);
|
|
74980
|
+
const end = completeLinesOnly ? completeJsonlPrefix(buf.subarray(0, read2)) : read2;
|
|
74981
|
+
const text = buf.subarray(0, end).toString("utf8");
|
|
74875
74982
|
const firstNewline = buf.indexOf(10);
|
|
74876
74983
|
const parseStartByte = firstNewline < 0 ? start2 : start2 + firstNewline + 1 - Buffer.byteLength(buf.subarray(0, firstNewline + 1).toString("utf8"));
|
|
74877
|
-
return { text, bytesUnreachable: start2, parseStartByte, ioFailed: false };
|
|
74984
|
+
return { text, bytesUnreachable: start2, parseStartByte, ioFailed: false, nextOffset: start2 + end };
|
|
74878
74985
|
} catch {
|
|
74879
|
-
return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
|
|
74986
|
+
return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true, nextOffset: 0 };
|
|
74880
74987
|
} finally {
|
|
74881
74988
|
closeSync(fd);
|
|
74882
74989
|
}
|
|
@@ -74939,10 +75046,11 @@ function isUserTurnBoundary(obj) {
|
|
|
74939
75046
|
return blocks.some((b) => b["type"] === "text");
|
|
74940
75047
|
}
|
|
74941
75048
|
function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, maxBytes = 2e6) {
|
|
74942
|
-
const tail = readTailWithLosses(transcriptPath, maxBytes);
|
|
75049
|
+
const tail = readTailWithLosses(transcriptPath, maxBytes, true);
|
|
74943
75050
|
const parsed = parseAssistantTurns(tail.text, includeThinking, false, tail.parseStartByte);
|
|
74944
75051
|
return {
|
|
74945
75052
|
turns: parsed.turns,
|
|
75053
|
+
nextOffset: tail.nextOffset,
|
|
74946
75054
|
losses: {
|
|
74947
75055
|
parseFailures: parsed.parseFailures,
|
|
74948
75056
|
ioFailed: tail.ioFailed,
|
|
@@ -75253,7 +75361,13 @@ function codexSessionRoots(env2 = process.env, home = homedir4()) {
|
|
|
75253
75361
|
roots.add(join20(home, ".codex", "sessions"));
|
|
75254
75362
|
return [...roots];
|
|
75255
75363
|
}
|
|
75256
|
-
function
|
|
75364
|
+
function readCodexRolloutIdentity(path2) {
|
|
75365
|
+
const legacy = `codex:${basename5(path2, ".jsonl")}`;
|
|
75366
|
+
const identity = (cwd, id) => {
|
|
75367
|
+
const uuid3 = typeof id === "string" && /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/i.test(id) ? id.toLowerCase() : basename5(path2, ".jsonl").match(/([a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12})$/i)?.[1]?.toLowerCase();
|
|
75368
|
+
const sessionId = uuid3 ? `codex:${uuid3}` : legacy;
|
|
75369
|
+
return { cwd, sessionId, aliases: [legacy, ...uuid3 ? [uuid3] : []].filter((s) => s !== sessionId) };
|
|
75370
|
+
};
|
|
75257
75371
|
let fd;
|
|
75258
75372
|
try {
|
|
75259
75373
|
fd = openSync(path2, "r");
|
|
@@ -75276,11 +75390,11 @@ function readCodexRolloutCwd(path2) {
|
|
|
75276
75390
|
const o = JSON.parse(firstLine);
|
|
75277
75391
|
const meta3 = o?.type === "session_meta" ? o.payload ?? o : o.payload ?? o;
|
|
75278
75392
|
const cwd = meta3?.cwd ?? o?.cwd;
|
|
75279
|
-
if (typeof cwd === "string") return cwd;
|
|
75393
|
+
if (typeof cwd === "string") return identity(cwd, o.type === "session_meta" ? meta3.id : void 0);
|
|
75280
75394
|
} catch {
|
|
75281
75395
|
}
|
|
75282
75396
|
const m = firstLine.match(/"cwd"\s*:\s*"((?:[^"\\]|\\.)*)"/);
|
|
75283
|
-
return m ? JSON.parse(`"${m[1]}"`) : null;
|
|
75397
|
+
return m ? identity(JSON.parse(`"${m[1]}"`)) : null;
|
|
75284
75398
|
} catch {
|
|
75285
75399
|
return null;
|
|
75286
75400
|
} finally {
|
|
@@ -75338,15 +75452,16 @@ function codexRolloutsForCwd(cwd, opts = {}) {
|
|
|
75338
75452
|
);
|
|
75339
75453
|
activity.set(full, { size: st.size, activeAt: activityAtMs });
|
|
75340
75454
|
if (activityAtMs < sinceMs) continue;
|
|
75341
|
-
const
|
|
75342
|
-
if (
|
|
75455
|
+
const identity = readCodexRolloutIdentity(full);
|
|
75456
|
+
if (identity === null) continue;
|
|
75457
|
+
const sessionCwd = identity.cwd;
|
|
75343
75458
|
let sessionOwner = owners.get(sessionCwd);
|
|
75344
75459
|
if (sessionOwner === void 0) {
|
|
75345
75460
|
sessionOwner = checkoutRootOf(sessionCwd);
|
|
75346
75461
|
owners.set(sessionCwd, sessionOwner);
|
|
75347
75462
|
}
|
|
75348
75463
|
if (sessionOwner !== owner) continue;
|
|
75349
|
-
out2.push({ path: full, sessionId:
|
|
75464
|
+
out2.push({ path: full, sessionId: identity.sessionId, mtimeMs: st.mtimeMs, activityAtMs });
|
|
75350
75465
|
}
|
|
75351
75466
|
}
|
|
75352
75467
|
for (const path2 of activity.keys()) if (!observed.has(path2)) activity.delete(path2);
|
|
@@ -80912,7 +81027,7 @@ function createWatchBreaker(deps) {
|
|
|
80912
81027
|
}
|
|
80913
81028
|
|
|
80914
81029
|
// src/engine.ts
|
|
80915
|
-
var DAEMON_VERSION = true ? "2.0.14-dev.
|
|
81030
|
+
var DAEMON_VERSION = true ? "2.0.14-dev.3125" : "2.0.0-alpha.0";
|
|
80916
81031
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
80917
81032
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
80918
81033
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -81368,6 +81483,7 @@ function createWorkspaceEngine(opts) {
|
|
|
81368
81483
|
const elicit = isEdgeElicitationEnabled();
|
|
81369
81484
|
const snapOpts = {
|
|
81370
81485
|
profile,
|
|
81486
|
+
atCommit: readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0,
|
|
81371
81487
|
reviewCount: pendingCount(paths),
|
|
81372
81488
|
reviewUiUrl: opts.reviewUrl(),
|
|
81373
81489
|
workingFile: workingFiles.mostRecent() ?? void 0,
|
|
@@ -81381,6 +81497,10 @@ function createWorkspaceEngine(opts) {
|
|
|
81381
81497
|
);
|
|
81382
81498
|
return null;
|
|
81383
81499
|
}) : null;
|
|
81500
|
+
if (snapOpts.atCommit !== (readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0)) {
|
|
81501
|
+
contextDirty = true;
|
|
81502
|
+
return;
|
|
81503
|
+
}
|
|
81384
81504
|
const doneRender = markPass(`${prebuilt ? "context-render" : "context-render-inline"}:${profile.name}`);
|
|
81385
81505
|
const pendingUpdate = opts.pendingUpdate?.() ?? null;
|
|
81386
81506
|
const daemonDistress = opts.daemonDistress?.() ?? null;
|
|
@@ -82640,7 +82760,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82640
82760
|
readLosses.sliceGuardHits = 0;
|
|
82641
82761
|
}
|
|
82642
82762
|
};
|
|
82643
|
-
const
|
|
82763
|
+
const harvestTurnsUnqueued = async (sessionId, transcriptPath) => {
|
|
82644
82764
|
const known = turnOffset.get(sessionId);
|
|
82645
82765
|
let turns;
|
|
82646
82766
|
let nextOffset;
|
|
@@ -82648,7 +82768,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82648
82768
|
if (known === void 0) {
|
|
82649
82769
|
const first = readAssistantTurnsWithLosses(transcriptPath);
|
|
82650
82770
|
turns = first.turns;
|
|
82651
|
-
nextOffset =
|
|
82771
|
+
nextOffset = first.nextOffset;
|
|
82652
82772
|
readLosses.bytesUnreachable += first.losses.bytesUnreachable;
|
|
82653
82773
|
readLosses.parseFailures += first.losses.parseFailures;
|
|
82654
82774
|
if (first.losses.ioFailed) readLosses.ioFailures++;
|
|
@@ -82708,6 +82828,37 @@ function createWorkspaceEngine(opts) {
|
|
|
82708
82828
|
}
|
|
82709
82829
|
setImmediate(() => void harvestTexts(e.sessionId, [{ text: e.text }]));
|
|
82710
82830
|
};
|
|
82831
|
+
const harvestInFlight = /* @__PURE__ */ new Map();
|
|
82832
|
+
const repairedSessions = /* @__PURE__ */ new Set();
|
|
82833
|
+
const harvestTurns = async (inputSessionId, transcriptPath) => {
|
|
82834
|
+
const identity = basename7(transcriptPath).startsWith("rollout-") ? readCodexRolloutIdentity(transcriptPath) : null;
|
|
82835
|
+
const sessionId = identity?.sessionId ?? inputSessionId;
|
|
82836
|
+
const work = (harvestInFlight.get(sessionId) ?? Promise.resolve()).catch(() => {
|
|
82837
|
+
}).then(async () => {
|
|
82838
|
+
if (identity && !repairedSessions.has(sessionId)) {
|
|
82839
|
+
store.repairSessionAliases(sessionId, identity.aliases);
|
|
82840
|
+
opts.sharedStore?.repairSessionAliases(sessionId, identity.aliases);
|
|
82841
|
+
repairedSessions.add(sessionId);
|
|
82842
|
+
}
|
|
82843
|
+
for (const alias of identity?.aliases ?? []) {
|
|
82844
|
+
const offset = turnOffset.get(alias);
|
|
82845
|
+
if (offset !== void 0 && offset > (turnOffset.get(sessionId) ?? -1)) {
|
|
82846
|
+
turnOffset.set(sessionId, offset);
|
|
82847
|
+
const uuid3 = lastTurnUuid.get(alias);
|
|
82848
|
+
if (uuid3) lastTurnUuid.set(sessionId, uuid3);
|
|
82849
|
+
}
|
|
82850
|
+
turnOffset.delete(alias);
|
|
82851
|
+
lastTurnUuid.delete(alias);
|
|
82852
|
+
}
|
|
82853
|
+
await harvestTurnsUnqueued(sessionId, transcriptPath);
|
|
82854
|
+
});
|
|
82855
|
+
harvestInFlight.set(sessionId, work);
|
|
82856
|
+
try {
|
|
82857
|
+
await work;
|
|
82858
|
+
} finally {
|
|
82859
|
+
if (harvestInFlight.get(sessionId) === work) harvestInFlight.delete(sessionId);
|
|
82860
|
+
}
|
|
82861
|
+
};
|
|
82711
82862
|
const harvestSession = async (sessionId, transcriptPath) => {
|
|
82712
82863
|
await harvestTurns(sessionId, transcriptPath);
|
|
82713
82864
|
for (const sub of subagentTranscripts(transcriptPath, sessionId)) {
|
|
@@ -85384,12 +85535,12 @@ var GENERATED_PATH_RES = [
|
|
|
85384
85535
|
];
|
|
85385
85536
|
var RELEASE_SUBJECT_RE = /^(release|bump|chore\(release\)|v?\d+\.\d+\.\d+)/i;
|
|
85386
85537
|
var RELEASE_TAG_RE = /^v?\d+\.\d+/;
|
|
85387
|
-
function
|
|
85538
|
+
function basename8(path2) {
|
|
85388
85539
|
const i2 = path2.lastIndexOf("/");
|
|
85389
85540
|
return i2 < 0 ? path2 : path2.slice(i2 + 1);
|
|
85390
85541
|
}
|
|
85391
85542
|
function isLockfilePath(path2) {
|
|
85392
|
-
const name2 =
|
|
85543
|
+
const name2 = basename8(path2);
|
|
85393
85544
|
return LOCKFILE_NAMES.has(name2) || LOCKFILE_SUFFIX_RE.test(name2);
|
|
85394
85545
|
}
|
|
85395
85546
|
function isGeneratedPath(path2) {
|
|
@@ -89408,7 +89559,7 @@ function buildCodexHooksToml(port, options) {
|
|
|
89408
89559
|
const quote = (value) => {
|
|
89409
89560
|
if (platform === "win32") {
|
|
89410
89561
|
if (/["\r\n]/.test(value)) throw new Error("Unsupported character in Codex hook path");
|
|
89411
|
-
return "'" + value.replace(/'/g,
|
|
89562
|
+
return "'" + value.replace(/['\u2018-\u201B]/g, (quote2) => quote2 + quote2) + "'";
|
|
89412
89563
|
}
|
|
89413
89564
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
89414
89565
|
};
|
|
@@ -89426,6 +89577,9 @@ import { readFileSync } from 'node:fs';
|
|
|
89426
89577
|
|
|
89427
89578
|
try {
|
|
89428
89579
|
const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
|
|
89580
|
+
if (typeof payload.session_id === 'string' && /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/i.test(payload.session_id)) {
|
|
89581
|
+
payload.session_id = 'codex:' + payload.session_id.toLowerCase();
|
|
89582
|
+
}
|
|
89429
89583
|
const port = Number(process.argv[2]);
|
|
89430
89584
|
const event = payload.hook_event_name;
|
|
89431
89585
|
if (!Number.isInteger(port) || port < 1 || port > 65535) process.exit(0);
|
|
@@ -92739,7 +92893,9 @@ async function cmdDash(args2) {
|
|
|
92739
92893
|
for (const r of handle2.records) {
|
|
92740
92894
|
await yieldToLoop2();
|
|
92741
92895
|
try {
|
|
92742
|
-
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile
|
|
92896
|
+
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
|
|
92897
|
+
atCommit: readGitRefState(join43(r.root, ".git")).sha ?? void 0
|
|
92898
|
+
});
|
|
92743
92899
|
const res = bleedRules(join43(r.root, ".claude", "rules"), items);
|
|
92744
92900
|
if (res.written || res.pruned) {
|
|
92745
92901
|
console.log(
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -24605,6 +24605,71 @@ function installHistoryCacheFloor(db) {
|
|
|
24605
24605
|
});
|
|
24606
24606
|
}
|
|
24607
24607
|
|
|
24608
|
+
// ../../packages/local-graph/src/session-evidence.ts
|
|
24609
|
+
function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
|
|
24610
|
+
const mapping = new Map(aliases);
|
|
24611
|
+
const uuid3 = "[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}";
|
|
24612
|
+
const codex = new RegExp(`^codex:(?:rollout-.*?)?(${uuid3})$`, "i");
|
|
24613
|
+
const arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
|
|
24614
|
+
const scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
|
|
24615
|
+
const discover = (value, key = "") => {
|
|
24616
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
24617
|
+
const match = value.match(codex);
|
|
24618
|
+
if (match) {
|
|
24619
|
+
const canonical = `codex:${match[1].toLowerCase()}`;
|
|
24620
|
+
mapping.set(value, canonical);
|
|
24621
|
+
mapping.set(match[1].toLowerCase(), canonical);
|
|
24622
|
+
}
|
|
24623
|
+
} else if (Array.isArray(value)) value.forEach((v) => discover(v, key));
|
|
24624
|
+
else if (value && typeof value === "object") {
|
|
24625
|
+
for (const [k, v] of Object.entries(value)) discover(v, key === "citeAnchorHints" ? key : k);
|
|
24626
|
+
}
|
|
24627
|
+
};
|
|
24628
|
+
discover(input);
|
|
24629
|
+
const rewrite = (value, key = "") => {
|
|
24630
|
+
if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
|
|
24631
|
+
return mapping.get(value) ?? mapping.get(value.toLowerCase()) ?? value;
|
|
24632
|
+
}
|
|
24633
|
+
if (Array.isArray(value)) {
|
|
24634
|
+
const values = value.map((v) => rewrite(v, key));
|
|
24635
|
+
return arrays.has(key) || key === "citeAnchorHints" ? [...new Set(values)] : values;
|
|
24636
|
+
}
|
|
24637
|
+
if (!value || typeof value !== "object") return value;
|
|
24638
|
+
const before = value;
|
|
24639
|
+
const after = Object.fromEntries(Object.entries(before).map(([k, v]) => [k, rewrite(v, key === "citeAnchorHints" ? key : k)]));
|
|
24640
|
+
for (const field of ["sources", "contributors"]) {
|
|
24641
|
+
const old = before[field], next = after[field];
|
|
24642
|
+
if (!Array.isArray(old) || !Array.isArray(next) || old.length <= next.length) continue;
|
|
24643
|
+
after["sessionAliasRepair"] = { originalCount: old.length, distinctCount: next.length };
|
|
24644
|
+
if (field === "sources" && typeof after["corroborations"] === "number") {
|
|
24645
|
+
after["corroborations"] = Math.min(after["corroborations"], Math.max(0, next.length - 1));
|
|
24646
|
+
if (after["corroborations"] === 0) after["provisional"] = true;
|
|
24647
|
+
}
|
|
24648
|
+
if (field === "contributors" && typeof after["confirmed"] === "number") {
|
|
24649
|
+
after["preAliasRepairConfirmed"] = after["confirmed"];
|
|
24650
|
+
after["confirmed"] = Math.min(after["confirmed"], next.length);
|
|
24651
|
+
}
|
|
24652
|
+
}
|
|
24653
|
+
return after;
|
|
24654
|
+
};
|
|
24655
|
+
const repaired = rewrite(input);
|
|
24656
|
+
const source = repaired["discriminatorSource"];
|
|
24657
|
+
if (typeof source === "string") {
|
|
24658
|
+
const global = repaired["perContext"]?.["*"];
|
|
24659
|
+
const contributors = Array.isArray(global?.["contributors"]) ? global["contributors"] : [];
|
|
24660
|
+
const inferred = new Set(Array.isArray(global?.["inferredContributors"]) ? global["inferredContributors"] : []);
|
|
24661
|
+
if (contributors.includes(source) || contributors.filter((id) => !inferred.has(id)).length < 2) {
|
|
24662
|
+
repaired["withdrawnDiscriminator"] = repaired["discriminator"];
|
|
24663
|
+
repaired["discriminatorWithdrawalReason"] = "insufficient-independent-witnesses";
|
|
24664
|
+
repaired["provisional"] = true;
|
|
24665
|
+
delete repaired["discriminator"];
|
|
24666
|
+
delete repaired["discriminatorSource"];
|
|
24667
|
+
delete repaired["discriminatorAsked"];
|
|
24668
|
+
}
|
|
24669
|
+
}
|
|
24670
|
+
return repaired;
|
|
24671
|
+
}
|
|
24672
|
+
|
|
24608
24673
|
// ../../packages/local-graph/src/store.ts
|
|
24609
24674
|
var LOCAL_RULE_OVERRIDES = {
|
|
24610
24675
|
ANCHORED_AT: {
|
|
@@ -24849,6 +24914,12 @@ var SqliteGraphStore = class {
|
|
|
24849
24914
|
}
|
|
24850
24915
|
this.db.exec(TEMPORAL_INDEX_SQL);
|
|
24851
24916
|
installHistoryCacheFloor(this.db);
|
|
24917
|
+
if (!this.db.prepare("SELECT value FROM store_meta WHERE key = 'session-evidence-v1'").get()) {
|
|
24918
|
+
this.db.transaction(() => {
|
|
24919
|
+
this.repairSessionAliases();
|
|
24920
|
+
this.db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES ('session-evidence-v1', 'done')").run();
|
|
24921
|
+
});
|
|
24922
|
+
}
|
|
24852
24923
|
this.stmts = {
|
|
24853
24924
|
insertNode: this.db.prepare(`
|
|
24854
24925
|
INSERT INTO nodes (
|
|
@@ -25097,6 +25168,23 @@ var SqliteGraphStore = class {
|
|
|
25097
25168
|
this.db.prepare("UPDATE schema_version SET version = ?").run(SCHEMA_VERSION);
|
|
25098
25169
|
});
|
|
25099
25170
|
}
|
|
25171
|
+
repairSessionAliases(canonical, aliases = []) {
|
|
25172
|
+
const mapping = new Map(aliases.map((alias) => [alias, canonical]));
|
|
25173
|
+
let changed = 0;
|
|
25174
|
+
for (const table of ["nodes", "edges"]) {
|
|
25175
|
+
const predicates = canonical ? aliases.map(() => "instr(attrs_json, ?) > 0") : ["instr(attrs_json, 'codex:') > 0", "instr(attrs_json, 'discriminatorSource') > 0"];
|
|
25176
|
+
if (!predicates.length) continue;
|
|
25177
|
+
const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE ${predicates.join(" OR ")}`).all(...canonical ? aliases : []);
|
|
25178
|
+
const update = this.db.prepare(`UPDATE ${table} SET attrs_json = ?${table === "edges" ? ", type = CASE WHEN type = 'CONFIRMS' AND json_extract(?, '$.provisional') = 1 THEN 'INDICATES' ELSE type END" : ""} WHERE id = ?`);
|
|
25179
|
+
for (const row of rows) {
|
|
25180
|
+
const attrs = JSON.stringify(repairSessionEvidence(JSON.parse(row.attrs_json), mapping));
|
|
25181
|
+
if (attrs === row.attrs_json) continue;
|
|
25182
|
+
update.run(...table === "edges" ? [attrs, attrs, row.id] : [attrs, row.id]);
|
|
25183
|
+
changed++;
|
|
25184
|
+
}
|
|
25185
|
+
}
|
|
25186
|
+
return changed;
|
|
25187
|
+
}
|
|
25100
25188
|
deleteNode(id) {
|
|
25101
25189
|
this.stmts.deleteNode.run(id);
|
|
25102
25190
|
}
|
|
@@ -27543,7 +27631,7 @@ var AGENTS_POINTER_BODY = [
|
|
|
27543
27631
|
init_src2();
|
|
27544
27632
|
init_src();
|
|
27545
27633
|
function buildSnapshot(opts) {
|
|
27546
|
-
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive" }).allow);
|
|
27634
|
+
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
|
|
27547
27635
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
27548
27636
|
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
27549
27637
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
@@ -27573,11 +27661,11 @@ function buildSnapshot(opts) {
|
|
|
27573
27661
|
...opts.store.findNodesByLabel("Pattern"),
|
|
27574
27662
|
...opts.store.findNodesByLabel("Technique"),
|
|
27575
27663
|
...opts.store.findNodesByLabel("AntiPattern")
|
|
27576
|
-
].filter((n) => historyReadPolicy(n, { mode: "passive" }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
27577
|
-
const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile) : void 0;
|
|
27664
|
+
].filter((n) => historyReadPolicy(n, { mode: "passive", atCommit: opts.atCommit }).allow).sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
|
|
27665
|
+
const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile, opts.atCommit) : void 0;
|
|
27578
27666
|
const byEpisode = /* @__PURE__ */ new Map();
|
|
27579
27667
|
for (const sol of opts.store.findNodesByLabel("Solution")) {
|
|
27580
|
-
if (!historyReadPolicy(sol, { mode: "passive" }).allow) continue;
|
|
27668
|
+
if (!historyReadPolicy(sol, { mode: "passive", atCommit: opts.atCommit }).allow) continue;
|
|
27581
27669
|
if (sol.attrs["enrichmentPending"] !== true) continue;
|
|
27582
27670
|
const ep = sol.attrs["episodeId"] ?? sol.id;
|
|
27583
27671
|
const list = byEpisode.get(ep) ?? [];
|
|
@@ -27649,7 +27737,7 @@ function buildSnapshot(opts) {
|
|
|
27649
27737
|
generatedAt: (opts.now ?? /* @__PURE__ */ new Date()).toISOString()
|
|
27650
27738
|
};
|
|
27651
27739
|
}
|
|
27652
|
-
function sliceForFile(store2, relPath) {
|
|
27740
|
+
function sliceForFile(store2, relPath, atCommit) {
|
|
27653
27741
|
const candidates = store2.findNodesByLabel("File");
|
|
27654
27742
|
const file2 = candidates.find((n) => n.description === relPath);
|
|
27655
27743
|
if (!file2) return void 0;
|
|
@@ -27688,7 +27776,7 @@ function sliceForFile(store2, relPath) {
|
|
|
27688
27776
|
}
|
|
27689
27777
|
const fp = priorsForFile(store2, relPath);
|
|
27690
27778
|
if (fp) {
|
|
27691
|
-
const allowed = (n) => historyReadPolicy(n, { mode: "passive" }).allow;
|
|
27779
|
+
const allowed = (n) => historyReadPolicy(n, { mode: "passive", atCommit }).allow;
|
|
27692
27780
|
fp.openProblems = fp.openProblems.filter(allowed);
|
|
27693
27781
|
fp.constraints = fp.constraints.filter(allowed);
|
|
27694
27782
|
fp.resolvedProblems = fp.resolvedProblems.filter(allowed);
|
|
@@ -27913,6 +28001,7 @@ function runPass(msg) {
|
|
|
27913
28001
|
const p = msg.payload;
|
|
27914
28002
|
return buildSnapshot({
|
|
27915
28003
|
store,
|
|
28004
|
+
atCommit: p.atCommit,
|
|
27916
28005
|
profile: p.profile,
|
|
27917
28006
|
reviewCount: p.reviewCount,
|
|
27918
28007
|
reviewUiUrl: p.reviewUiUrl,
|