@inerrata-corporation/errata 2.0.6-dev.2069 → 2.0.6-dev.2082
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/errata.mjs +172 -19
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -77056,7 +77056,7 @@ function createWatchBreaker(deps) {
|
|
|
77056
77056
|
}
|
|
77057
77057
|
|
|
77058
77058
|
// src/engine.ts
|
|
77059
|
-
var DAEMON_VERSION = true ? "2.0.6-dev.
|
|
77059
|
+
var DAEMON_VERSION = true ? "2.0.6-dev.2082" : "2.0.0-alpha.0";
|
|
77060
77060
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
77061
77061
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
77062
77062
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -79783,6 +79783,13 @@ var SHIP_TERMINAL_REFUSALS = 3;
|
|
|
79783
79783
|
function refusalFingerprint(reason, description) {
|
|
79784
79784
|
return digest(`${reason}\0${description}`);
|
|
79785
79785
|
}
|
|
79786
|
+
function isRetryableRefusal(reason) {
|
|
79787
|
+
return /\bretry\b/i.test(reason);
|
|
79788
|
+
}
|
|
79789
|
+
function isTerminallyRefused(n) {
|
|
79790
|
+
const reason = String(n.attrs["shipRefusedReason"] ?? "");
|
|
79791
|
+
return typeof n.attrs["shipRefusedCount"] === "number" && n.attrs["shipRefusedCount"] >= SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason) && n.attrs["shipRefusedFingerprint"] === refusalFingerprint(reason, n.description);
|
|
79792
|
+
}
|
|
79786
79793
|
function unshippableReason(canonical, label) {
|
|
79787
79794
|
void label;
|
|
79788
79795
|
if (canonical.length < WIRE_CANONICAL_ID_MIN) {
|
|
@@ -79935,10 +79942,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
79935
79942
|
composition.autoMint++;
|
|
79936
79943
|
continue;
|
|
79937
79944
|
}
|
|
79938
|
-
if (
|
|
79939
|
-
String(n.attrs["shipRefusedReason"] ?? ""),
|
|
79940
|
-
n.description
|
|
79941
|
-
)) {
|
|
79945
|
+
if (isTerminallyRefused(n)) {
|
|
79942
79946
|
composition.terminalRefused++;
|
|
79943
79947
|
continue;
|
|
79944
79948
|
}
|
|
@@ -80022,12 +80026,14 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
80022
80026
|
}
|
|
80023
80027
|
}
|
|
80024
80028
|
const project = opts.project;
|
|
80029
|
+
const projectAnchorDigests = {};
|
|
80025
80030
|
if (project) {
|
|
80026
80031
|
const now = Date.now();
|
|
80027
80032
|
for (const sourceId of anchorSources) {
|
|
80028
80033
|
const source = store.getNode(sourceId);
|
|
80029
80034
|
if (!source) continue;
|
|
80030
80035
|
const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
|
|
80036
|
+
const planned = [];
|
|
80031
80037
|
for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
|
|
80032
80038
|
const target = store.getNode(e.to);
|
|
80033
80039
|
if (!target) continue;
|
|
@@ -80035,7 +80041,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
80035
80041
|
const qname = target.attrs["qname"];
|
|
80036
80042
|
if (typeof relPath !== "string" || typeof qname !== "string") continue;
|
|
80037
80043
|
if (ignored(relPath) || ignored(qname)) continue;
|
|
80038
|
-
|
|
80044
|
+
planned.push({ e, target, symId: projectSymbolId(project.salt, project.projectId, relPath, qname, target.label) });
|
|
80045
|
+
}
|
|
80046
|
+
if (planned.length === 0) continue;
|
|
80047
|
+
const dg = digest(
|
|
80048
|
+
planned.map(({ e, symId }) => `ANCHORED_AT>${symId}>${JSON.stringify(anchorVersionAttrs(e.attrs))}`).sort()
|
|
80049
|
+
);
|
|
80050
|
+
if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
|
|
80051
|
+
projectAnchorDigests[sourceId] = dg;
|
|
80052
|
+
for (const { e, target, symId } of planned) {
|
|
80039
80053
|
if (!contextSeen.has(symId)) {
|
|
80040
80054
|
contextSeen.add(symId);
|
|
80041
80055
|
contextNodes.push({
|
|
@@ -80142,6 +80156,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
80142
80156
|
}
|
|
80143
80157
|
const shippableNodes = heldOrphans.size === 0 ? nodes : nodes.filter((n) => !heldOrphans.has(n.id));
|
|
80144
80158
|
const shippableEdges = heldOrphans.size === 0 ? edges : edges.filter((e) => !heldOrphans.has(e.from) && !heldOrphans.has(e.to));
|
|
80159
|
+
for (const id of heldOrphans) {
|
|
80160
|
+
delete anchorDigests[id];
|
|
80161
|
+
delete semanticEdgeDigests[id];
|
|
80162
|
+
delete projectAnchorDigests[id];
|
|
80163
|
+
}
|
|
80145
80164
|
if (heldOrphans.size > 0) {
|
|
80146
80165
|
console.warn(
|
|
80147
80166
|
`[errata] held ${heldOrphans.size} causal-orphan node(s) \u2014 no shippable binding edge this drain (VS-orphan-gate)`
|
|
@@ -80171,7 +80190,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
80171
80190
|
...symbolSummaries ? { symbolSummaries } : {}
|
|
80172
80191
|
};
|
|
80173
80192
|
opts.onComposition?.(composition);
|
|
80174
|
-
return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, composition };
|
|
80193
|
+
return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
|
|
80175
80194
|
}
|
|
80176
80195
|
|
|
80177
80196
|
// src/backfill-edges.ts
|
|
@@ -83140,6 +83159,76 @@ function codexWakeCandidates(input) {
|
|
|
83140
83159
|
return out2;
|
|
83141
83160
|
}
|
|
83142
83161
|
|
|
83162
|
+
// src/hook-route.ts
|
|
83163
|
+
function msysToWindowsPath(p, platform = process.platform) {
|
|
83164
|
+
if (platform !== "win32") return p;
|
|
83165
|
+
const m = /^\/([a-zA-Z])(\/.*)?$/.exec(p);
|
|
83166
|
+
return m ? `${m[1].toUpperCase()}:${m[2] ?? "/"}` : p;
|
|
83167
|
+
}
|
|
83168
|
+
var SHELL_BREAK = /[\s"'`;&|()<>=]+/;
|
|
83169
|
+
function absolutePathsInCommand(command, platform = process.platform) {
|
|
83170
|
+
const out2 = [];
|
|
83171
|
+
for (const raw2 of command.split(SHELL_BREAK)) {
|
|
83172
|
+
const token = raw2.replace(/^[:,]+/, "").replace(/[,:]+$/, "");
|
|
83173
|
+
if (!token) continue;
|
|
83174
|
+
if (/^[a-zA-Z]:[\\/]/.test(token)) {
|
|
83175
|
+
out2.push(token);
|
|
83176
|
+
} else if (token.startsWith("/") && !token.startsWith("//")) {
|
|
83177
|
+
if (platform === "win32") {
|
|
83178
|
+
if (/^\/[a-zA-Z](\/|$)/.test(token)) out2.push(msysToWindowsPath(token, platform));
|
|
83179
|
+
} else if (token.length > 1) {
|
|
83180
|
+
out2.push(token);
|
|
83181
|
+
}
|
|
83182
|
+
}
|
|
83183
|
+
}
|
|
83184
|
+
return out2;
|
|
83185
|
+
}
|
|
83186
|
+
function hookPathCandidates(body2, platform = process.platform) {
|
|
83187
|
+
const input = body2["tool_input"] ?? {};
|
|
83188
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
|
|
83189
|
+
const out2 = [];
|
|
83190
|
+
for (const key of ["file_path", "notebook_path", "path"]) {
|
|
83191
|
+
const v = str(input[key]);
|
|
83192
|
+
if (v) out2.push(msysToWindowsPath(v, platform));
|
|
83193
|
+
}
|
|
83194
|
+
const command = str(input["command"]);
|
|
83195
|
+
if (command) out2.push(...absolutePathsInCommand(command, platform));
|
|
83196
|
+
const cwd = str(body2["cwd"]);
|
|
83197
|
+
if (cwd) out2.push(msysToWindowsPath(cwd, platform));
|
|
83198
|
+
return [...new Set(out2)];
|
|
83199
|
+
}
|
|
83200
|
+
var SESSION_AFFINITY_TTL_MS = 30 * 6e4;
|
|
83201
|
+
var SessionAffinity = class {
|
|
83202
|
+
constructor(ttlMs = SESSION_AFFINITY_TTL_MS, maxSessions = 500) {
|
|
83203
|
+
this.ttlMs = ttlMs;
|
|
83204
|
+
this.maxSessions = maxSessions;
|
|
83205
|
+
}
|
|
83206
|
+
bySession = /* @__PURE__ */ new Map();
|
|
83207
|
+
note(sessionId, root, now = Date.now()) {
|
|
83208
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return;
|
|
83209
|
+
this.bySession.delete(sessionId);
|
|
83210
|
+
this.bySession.set(sessionId, { root, at: now });
|
|
83211
|
+
while (this.bySession.size > this.maxSessions) {
|
|
83212
|
+
const oldest = this.bySession.keys().next().value;
|
|
83213
|
+
if (oldest === void 0) break;
|
|
83214
|
+
this.bySession.delete(oldest);
|
|
83215
|
+
}
|
|
83216
|
+
}
|
|
83217
|
+
rootFor(sessionId, now = Date.now()) {
|
|
83218
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return null;
|
|
83219
|
+
const hit = this.bySession.get(sessionId);
|
|
83220
|
+
if (!hit) return null;
|
|
83221
|
+
if (now - hit.at > this.ttlMs) {
|
|
83222
|
+
this.bySession.delete(sessionId);
|
|
83223
|
+
return null;
|
|
83224
|
+
}
|
|
83225
|
+
return hit.root;
|
|
83226
|
+
}
|
|
83227
|
+
forget(sessionId) {
|
|
83228
|
+
if (typeof sessionId === "string") this.bySession.delete(sessionId);
|
|
83229
|
+
}
|
|
83230
|
+
};
|
|
83231
|
+
|
|
83143
83232
|
// src/multi.ts
|
|
83144
83233
|
var projectSymbolSalts = /* @__PURE__ */ new Map();
|
|
83145
83234
|
async function resolveProjectSymbolSalt(client, projectId) {
|
|
@@ -83590,7 +83679,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
83590
83679
|
}))
|
|
83591
83680
|
})
|
|
83592
83681
|
);
|
|
83593
|
-
const
|
|
83682
|
+
const sessionAffinity = new SessionAffinity();
|
|
83683
|
+
const forward = async (c, pathInBody, opts2 = {}) => {
|
|
83594
83684
|
const raw2 = await c.req.text();
|
|
83595
83685
|
let body2 = {};
|
|
83596
83686
|
try {
|
|
@@ -83599,7 +83689,21 @@ async function startMultiDaemon(opts = {}) {
|
|
|
83599
83689
|
return c.json({ error: "bad-json" }, 400);
|
|
83600
83690
|
}
|
|
83601
83691
|
lastHook = { at: Date.now(), event: typeof body2["hook_event_name"] === "string" ? body2["hook_event_name"] : c.req.path };
|
|
83602
|
-
|
|
83692
|
+
const primary = pathInBody(body2);
|
|
83693
|
+
const others = (opts2.extraPaths?.(body2) ?? []).filter((p) => p !== primary);
|
|
83694
|
+
let owner = ownerOf(records, primary);
|
|
83695
|
+
for (const p of others) {
|
|
83696
|
+
if (owner) break;
|
|
83697
|
+
owner = ownerOf(records, p);
|
|
83698
|
+
}
|
|
83699
|
+
if (!owner && others.length > 0) {
|
|
83700
|
+
const registryRoots = listWorkspaceEntries().map((e) => e.path);
|
|
83701
|
+
const registered = others.map((p) => pickOwnerRoot(registryRoots, p)).find((r) => r != null);
|
|
83702
|
+
if (registered && attachWorkspace(registered).attached) {
|
|
83703
|
+
owner = records.find((r) => r.root === registered) ?? null;
|
|
83704
|
+
if (owner) console.log(`[errata] woke workspace ${owner.entry.name}`);
|
|
83705
|
+
}
|
|
83706
|
+
}
|
|
83603
83707
|
if (!owner) {
|
|
83604
83708
|
const missPath = pathInBody(body2);
|
|
83605
83709
|
const registeredRoot = missPath ? pickOwnerRoot(listWorkspaceEntries().map((e) => e.path), missPath) : null;
|
|
@@ -83609,10 +83713,18 @@ async function startMultiDaemon(opts = {}) {
|
|
|
83609
83713
|
if (owner) console.log(`[errata] woke workspace ${owner.entry.name}`);
|
|
83610
83714
|
}
|
|
83611
83715
|
}
|
|
83716
|
+
if (!owner && opts2.affinity === "follow") {
|
|
83717
|
+
const root = sessionAffinity.rootFor(body2["session_id"]);
|
|
83718
|
+
if (root) {
|
|
83719
|
+
owner = records.find((r) => r.root === root) ?? null;
|
|
83720
|
+
if (!owner && attachWorkspace(root).attached) owner = records.find((r) => r.root === root) ?? null;
|
|
83721
|
+
}
|
|
83722
|
+
}
|
|
83612
83723
|
if (!owner) {
|
|
83613
|
-
rootAdopter.noteMiss(
|
|
83724
|
+
rootAdopter.noteMiss(primary);
|
|
83614
83725
|
return c.json({ error: "no-matching-project" }, 404);
|
|
83615
83726
|
}
|
|
83727
|
+
if (opts2.affinity === "note") sessionAffinity.note(body2["session_id"], owner.root);
|
|
83616
83728
|
owner.lastHookAt = Date.now();
|
|
83617
83729
|
const sub = c.req.path;
|
|
83618
83730
|
const done = markPass(`${sub}:${owner.entry.name}`);
|
|
@@ -83635,7 +83747,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
83635
83747
|
const fp = input["file_path"];
|
|
83636
83748
|
const cwd = b["cwd"];
|
|
83637
83749
|
return (typeof fp === "string" ? fp : void 0) ?? (typeof cwd === "string" ? cwd : void 0);
|
|
83638
|
-
})
|
|
83750
|
+
}, { extraPaths: (b) => hookPathCandidates(b), affinity: "note" })
|
|
83639
83751
|
);
|
|
83640
83752
|
app.post(
|
|
83641
83753
|
"/api/diagnostics",
|
|
@@ -83645,10 +83757,10 @@ async function startMultiDaemon(opts = {}) {
|
|
|
83645
83757
|
})
|
|
83646
83758
|
);
|
|
83647
83759
|
const cwdOf = (b) => typeof b["cwd"] === "string" ? b["cwd"] : void 0;
|
|
83648
|
-
app.post("/api/turn", (c) => forward(c, cwdOf));
|
|
83649
|
-
app.post("/api/message", (c) => forward(c, cwdOf));
|
|
83650
|
-
app.post("/api/session-end", (c) => forward(c, cwdOf));
|
|
83651
|
-
app.post("/api/context-inject", (c) => forward(c, cwdOf));
|
|
83760
|
+
app.post("/api/turn", (c) => forward(c, cwdOf, { affinity: "follow" }));
|
|
83761
|
+
app.post("/api/message", (c) => forward(c, cwdOf, { affinity: "follow" }));
|
|
83762
|
+
app.post("/api/session-end", (c) => forward(c, cwdOf, { affinity: "follow" }));
|
|
83763
|
+
app.post("/api/context-inject", (c) => forward(c, cwdOf, { affinity: "follow" }));
|
|
83652
83764
|
for (const r of records) {
|
|
83653
83765
|
mountedIds.add(r.id);
|
|
83654
83766
|
app.route(`/ws/${r.id}`, r.webApp);
|
|
@@ -84325,7 +84437,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84325
84437
|
// Same shape as the drained row: a first/last trend reading must not
|
|
84326
84438
|
// straddle rows where the counter is merely absent.
|
|
84327
84439
|
blockedRepeat: 0,
|
|
84328
|
-
rejectedRepeat: 0
|
|
84440
|
+
rejectedRepeat: 0,
|
|
84441
|
+
edgesRejected: 0
|
|
84329
84442
|
});
|
|
84330
84443
|
}
|
|
84331
84444
|
if (instances) {
|
|
@@ -84353,6 +84466,17 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84353
84466
|
for (const rn of res.result.nodes) {
|
|
84354
84467
|
if (rn.decision === "rejected") rejected.set(rn.canonicalId, rn.reason ?? "no reason given");
|
|
84355
84468
|
}
|
|
84469
|
+
const rejectedEdges = res.result.edges.filter((re) => re.decision === "rejected");
|
|
84470
|
+
if (rejectedEdges.length > 0) {
|
|
84471
|
+
const byReason = /* @__PURE__ */ new Map();
|
|
84472
|
+
for (const re of rejectedEdges) {
|
|
84473
|
+
const why = `${re.type}: ${re.reason ?? "no reason given"}`;
|
|
84474
|
+
byReason.set(why, (byReason.get(why) ?? 0) + 1);
|
|
84475
|
+
}
|
|
84476
|
+
console.warn(
|
|
84477
|
+
`[sync\u2192cloud] [${projectName}] instances: ${rejectedEdges.length} edge(s) REJECTED by the door: ` + [...byReason.entries()].map(([why, n]) => `${n}\xD7 ${why}`).join(" | ")
|
|
84478
|
+
);
|
|
84479
|
+
}
|
|
84356
84480
|
if (rejected.size > 0) {
|
|
84357
84481
|
const sample = [...rejected.entries()].slice(0, 3).map(([id, why]) => `${store.getNode(id)?.description.slice(0, 60) ?? id}: ${why}`);
|
|
84358
84482
|
console.warn(
|
|
@@ -84368,6 +84492,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84368
84492
|
};
|
|
84369
84493
|
let blockedRepeat = 0;
|
|
84370
84494
|
let rejectedRepeat = 0;
|
|
84495
|
+
const nowHeld = [];
|
|
84371
84496
|
const noteRefused = (id, reason, repeat) => {
|
|
84372
84497
|
const owner = owningStore(id);
|
|
84373
84498
|
if (!owner) return;
|
|
@@ -84384,9 +84509,17 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84384
84509
|
shipRefusedFingerprint: fp
|
|
84385
84510
|
}
|
|
84386
84511
|
});
|
|
84512
|
+
if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
|
|
84513
|
+
nowHeld.push({ id, reason });
|
|
84514
|
+
}
|
|
84387
84515
|
};
|
|
84388
84516
|
for (const id of blocked) noteRefused(id, "blocked", () => blockedRepeat++);
|
|
84389
84517
|
for (const [id, why] of rejected) noteRefused(id, why, () => rejectedRepeat++);
|
|
84518
|
+
if (nowHeld.length > 0) {
|
|
84519
|
+
console.warn(
|
|
84520
|
+
`[sync\u2192cloud] [${projectName}] instances: HOLDING ${nowHeld.length} node(s) \u2014 refused identically ${SHIP_TERMINAL_REFUSALS}\xD7 on unchanged text; not re-sent until the text changes: ` + nowHeld.map(({ id, reason }) => `${id} "${owningStore(id)?.n.description.slice(0, 60) ?? ""}": ${reason}`).join(" | ")
|
|
84521
|
+
);
|
|
84522
|
+
}
|
|
84390
84523
|
for (const n of instances.nodes) {
|
|
84391
84524
|
const owner = owningStore(n.id);
|
|
84392
84525
|
if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) continue;
|
|
@@ -84416,6 +84549,14 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84416
84549
|
attrs: { ...owner.n.attrs, anchorsContributedDigest: dg }
|
|
84417
84550
|
});
|
|
84418
84551
|
}
|
|
84552
|
+
for (const [localId, dg] of Object.entries(instances.projectAnchorDigests)) {
|
|
84553
|
+
const owner = owningStore(localId);
|
|
84554
|
+
if (!owner) continue;
|
|
84555
|
+
if (rejected.has(localId) || blocked.has(localId)) continue;
|
|
84556
|
+
owner.s.updateNode(localId, {
|
|
84557
|
+
attrs: { ...owner.n.attrs, projectAnchorsContributedDigest: dg }
|
|
84558
|
+
});
|
|
84559
|
+
}
|
|
84419
84560
|
for (const [localId, dg] of Object.entries(instances.semanticEdgeDigests)) {
|
|
84420
84561
|
const owner = owningStore(localId);
|
|
84421
84562
|
if (!owner) continue;
|
|
@@ -84434,7 +84575,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
84434
84575
|
// node; flat at 1 with `blockedRepeat` 0 is a different node
|
|
84435
84576
|
// failing every pass. Same total, different bug.
|
|
84436
84577
|
blockedRepeat,
|
|
84437
|
-
rejectedRepeat
|
|
84578
|
+
rejectedRepeat,
|
|
84579
|
+
edgesRejected: rejectedEdges.length
|
|
84438
84580
|
});
|
|
84439
84581
|
return res.accepted;
|
|
84440
84582
|
});
|
|
@@ -85771,15 +85913,26 @@ async function cmdStatus() {
|
|
|
85771
85913
|
try {
|
|
85772
85914
|
let pending = 0;
|
|
85773
85915
|
let total = 0;
|
|
85916
|
+
let heldRefused = 0;
|
|
85917
|
+
let autoMint = 0;
|
|
85774
85918
|
for (const label of ["Problem", "Solution", "RootCause"]) {
|
|
85775
85919
|
for (const n of store.findNodesByLabel(label)) {
|
|
85776
85920
|
if (n.attrs["source"] === "cloud") continue;
|
|
85777
85921
|
total++;
|
|
85778
85922
|
const c = n.attrs["contributedAtSeq"];
|
|
85779
|
-
if (typeof c
|
|
85923
|
+
if (typeof c === "number" && (n.lastReinforcedAtSeq ?? 0) <= c) continue;
|
|
85924
|
+
if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) autoMint++;
|
|
85925
|
+
else if (isTerminallyRefused(n)) heldRefused++;
|
|
85926
|
+
else pending++;
|
|
85780
85927
|
}
|
|
85781
85928
|
}
|
|
85782
|
-
|
|
85929
|
+
const held = [
|
|
85930
|
+
...heldRefused > 0 ? [`${heldRefused} held after identical door refusals`] : [],
|
|
85931
|
+
...autoMint > 0 ? [`${autoMint} auto-close marker(s) that never ship`] : []
|
|
85932
|
+
];
|
|
85933
|
+
console.log(
|
|
85934
|
+
` contribute: ${pending} pending of ${total} instance node(s)${held.length > 0 ? ` \xB7 ${held.join(" \xB7 ")}` : ""}`
|
|
85935
|
+
);
|
|
85783
85936
|
const rejections = store.edgeRejections();
|
|
85784
85937
|
if (rejections.length > 0) {
|
|
85785
85938
|
const refused = rejections.reduce((n, r) => n + r.count, 0);
|