@inerrata-corporation/errata 2.0.0-dev.35 → 2.0.0-dev.36
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 +33 -2
- package/errata.mjs +596 -219
- package/package.json +1 -1
- package/pass-worker.mjs +33 -2
package/errata.mjs
CHANGED
|
@@ -15268,6 +15268,85 @@ var init_edge_rules = __esm({
|
|
|
15268
15268
|
}
|
|
15269
15269
|
});
|
|
15270
15270
|
|
|
15271
|
+
// ../../packages/shared/src/symbol-intent.ts
|
|
15272
|
+
function extractIdentifierTokens(text) {
|
|
15273
|
+
const out2 = [];
|
|
15274
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15275
|
+
for (const m of text.matchAll(TOKEN_RE2)) {
|
|
15276
|
+
if (!seen.has(m[0])) {
|
|
15277
|
+
seen.add(m[0]);
|
|
15278
|
+
out2.push(m[0]);
|
|
15279
|
+
}
|
|
15280
|
+
}
|
|
15281
|
+
return out2;
|
|
15282
|
+
}
|
|
15283
|
+
function summaryRejectionReason(summary, isKnownToken) {
|
|
15284
|
+
if (!summary.trim()) return "empty summary";
|
|
15285
|
+
if (summary.length > MAX_SYMBOL_SUMMARY_CHARS) return "summary too long";
|
|
15286
|
+
if (PATH_SHAPE_RE.test(summary)) return "contains a path shape";
|
|
15287
|
+
if (QUOTED_LITERAL_RE.test(summary.replace(CONTRACTION_RE, "$1$2")))
|
|
15288
|
+
return "contains a quoted literal";
|
|
15289
|
+
for (const tok of extractIdentifierTokens(summary)) {
|
|
15290
|
+
if (isKnownToken(tok)) return `contains verbatim identifier '${tok}'`;
|
|
15291
|
+
if (tok.includes(".")) {
|
|
15292
|
+
const segs = tok.split(".");
|
|
15293
|
+
for (let i2 = 0; i2 < segs.length; i2++) {
|
|
15294
|
+
let span = "";
|
|
15295
|
+
for (let j = i2; j < segs.length; j++) {
|
|
15296
|
+
span = span ? `${span}.${segs[j]}` : segs[j];
|
|
15297
|
+
if (span !== tok && span && isKnownToken(span))
|
|
15298
|
+
return `contains verbatim identifier '${span}'`;
|
|
15299
|
+
}
|
|
15300
|
+
}
|
|
15301
|
+
}
|
|
15302
|
+
}
|
|
15303
|
+
return null;
|
|
15304
|
+
}
|
|
15305
|
+
function substituteSymbolSummaries(text, summaryByToken) {
|
|
15306
|
+
if (summaryByToken.size === 0) return text;
|
|
15307
|
+
const present = extractIdentifierTokens(text).filter((t) => summaryByToken.has(t));
|
|
15308
|
+
present.sort((a, b) => b.length - a.length);
|
|
15309
|
+
let out2 = text;
|
|
15310
|
+
for (const key of present) {
|
|
15311
|
+
const re = new RegExp(`(?<![A-Za-z0-9_$.])${escapeRe2(key)}(?![A-Za-z0-9_$])`, "g");
|
|
15312
|
+
out2 = out2.replace(re, summaryByToken.get(key));
|
|
15313
|
+
}
|
|
15314
|
+
return out2;
|
|
15315
|
+
}
|
|
15316
|
+
function vetSidecarSummaries(sidecar) {
|
|
15317
|
+
if (!sidecar) return null;
|
|
15318
|
+
const keys = new Set(Object.keys(sidecar));
|
|
15319
|
+
if (keys.size === 0 || keys.size > MAX_SIDECAR_SYMBOLS) return null;
|
|
15320
|
+
const clean = /* @__PURE__ */ new Map();
|
|
15321
|
+
for (const [symbol2, entry] of Object.entries(sidecar)) {
|
|
15322
|
+
if (!entry || typeof entry.summary !== "string") continue;
|
|
15323
|
+
if (summaryRejectionReason(entry.summary, (t) => keys.has(t)) !== null) continue;
|
|
15324
|
+
clean.set(symbol2, entry.summary);
|
|
15325
|
+
}
|
|
15326
|
+
return clean.size > 0 ? clean : null;
|
|
15327
|
+
}
|
|
15328
|
+
var SYMBOL_SUMMARY_KINDS, MAX_SYMBOL_SUMMARY_CHARS, MAX_SIDECAR_SYMBOLS, TOKEN_RE2, RE_RESERVED, escapeRe2, PATH_SHAPE_RE, CONTRACTION_RE, QUOTED_LITERAL_RE;
|
|
15329
|
+
var init_symbol_intent = __esm({
|
|
15330
|
+
"../../packages/shared/src/symbol-intent.ts"() {
|
|
15331
|
+
"use strict";
|
|
15332
|
+
SYMBOL_SUMMARY_KINDS = [
|
|
15333
|
+
"function",
|
|
15334
|
+
"method",
|
|
15335
|
+
"class",
|
|
15336
|
+
"interface",
|
|
15337
|
+
"constant"
|
|
15338
|
+
];
|
|
15339
|
+
MAX_SYMBOL_SUMMARY_CHARS = 300;
|
|
15340
|
+
MAX_SIDECAR_SYMBOLS = 200;
|
|
15341
|
+
TOKEN_RE2 = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
|
|
15342
|
+
RE_RESERVED = /[.*+?^${}()|[\]\\]/g;
|
|
15343
|
+
escapeRe2 = (s) => s.replace(RE_RESERVED, "\\$&");
|
|
15344
|
+
PATH_SHAPE_RE = /[\w.~-]+[/\\][\w.$~-]+/;
|
|
15345
|
+
CONTRACTION_RE = /([A-Za-z])'([A-Za-z])/g;
|
|
15346
|
+
QUOTED_LITERAL_RE = /"[^"]+"|'[^']+'|`[^`]+`/;
|
|
15347
|
+
}
|
|
15348
|
+
});
|
|
15349
|
+
|
|
15271
15350
|
// ../../packages/shared/src/wire.ts
|
|
15272
15351
|
function provenanceBand(source) {
|
|
15273
15352
|
switch (source) {
|
|
@@ -15317,13 +15396,14 @@ function summarizeIngestResult(r) {
|
|
|
15317
15396
|
...r.patternReconciliation ? { patternReconciliation: r.patternReconciliation } : {}
|
|
15318
15397
|
};
|
|
15319
15398
|
}
|
|
15320
|
-
var CLOUD_NODE_LABELS, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, CastaliaIngestPayloadSchema;
|
|
15399
|
+
var CLOUD_NODE_LABELS, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15321
15400
|
var init_wire = __esm({
|
|
15322
15401
|
"../../packages/shared/src/wire.ts"() {
|
|
15323
15402
|
"use strict";
|
|
15324
15403
|
init_zod();
|
|
15325
15404
|
init_castalia();
|
|
15326
15405
|
init_edge_rules();
|
|
15406
|
+
init_symbol_intent();
|
|
15327
15407
|
CLOUD_NODE_LABELS = [
|
|
15328
15408
|
...SEMANTIC_NODE_LABELS,
|
|
15329
15409
|
...CONTEXT_NODE_LABELS
|
|
@@ -15373,12 +15453,24 @@ var init_wire = __esm({
|
|
|
15373
15453
|
perContext: external_exports.record(external_exports.string(), RouteContextCountWireSchema).optional()
|
|
15374
15454
|
}).optional()
|
|
15375
15455
|
});
|
|
15456
|
+
SymbolSummarySidecarSchema = external_exports.record(
|
|
15457
|
+
external_exports.string().min(1).max(160),
|
|
15458
|
+
external_exports.object({
|
|
15459
|
+
kind: external_exports.enum(SYMBOL_SUMMARY_KINDS),
|
|
15460
|
+
summary: external_exports.string().min(1).max(MAX_SYMBOL_SUMMARY_CHARS)
|
|
15461
|
+
})
|
|
15462
|
+
).refine((m) => Object.keys(m).length <= MAX_SIDECAR_SYMBOLS, {
|
|
15463
|
+
message: `symbolSummaries sidecar exceeds ${MAX_SIDECAR_SYMBOLS} entries`
|
|
15464
|
+
});
|
|
15376
15465
|
CastaliaIngestPayloadSchema = external_exports.object({
|
|
15377
15466
|
/** Client-supplied UUID — one batch; pairs with the payload digest for replay. */
|
|
15378
15467
|
runId: external_exports.string().uuid(),
|
|
15379
15468
|
source: external_exports.enum(INGEST_SOURCES),
|
|
15380
15469
|
nodes: external_exports.array(CastaliaIngestNodeSchema).max(1e3),
|
|
15381
|
-
edges: external_exports.array(CastaliaIngestEdgeSchema).max(5e3)
|
|
15470
|
+
edges: external_exports.array(CastaliaIngestEdgeSchema).max(5e3),
|
|
15471
|
+
/** Optional symbol→intent-summary sidecar (PP-symbol-intent). Only symbols
|
|
15472
|
+
* present in this payload's node text; server re-vets no-verbatim. */
|
|
15473
|
+
symbolSummaries: SymbolSummarySidecarSchema.optional()
|
|
15382
15474
|
});
|
|
15383
15475
|
}
|
|
15384
15476
|
});
|
|
@@ -15443,12 +15535,16 @@ __export(src_exports, {
|
|
|
15443
15535
|
JUSTIFICATION_EDGES: () => JUSTIFICATION_EDGES,
|
|
15444
15536
|
MAX_EDGES_PER_PAYLOAD: () => MAX_EDGES_PER_PAYLOAD,
|
|
15445
15537
|
MAX_NODES_PER_PAYLOAD: () => MAX_NODES_PER_PAYLOAD,
|
|
15538
|
+
MAX_SIDECAR_SYMBOLS: () => MAX_SIDECAR_SYMBOLS,
|
|
15539
|
+
MAX_SYMBOL_SUMMARY_CHARS: () => MAX_SYMBOL_SUMMARY_CHARS,
|
|
15446
15540
|
PAGERANK_EXCLUSIONS: () => PAGERANK_EXCLUSIONS,
|
|
15447
15541
|
PROBLEM_RESOLUTION: () => PROBLEM_RESOLUTION,
|
|
15448
15542
|
RESOLUTION_EDGES: () => RESOLUTION_EDGES,
|
|
15449
15543
|
RouteContextCountWireSchema: () => RouteContextCountWireSchema,
|
|
15450
15544
|
SEMANTIC_NODE_LABELS: () => SEMANTIC_NODE_LABELS,
|
|
15451
15545
|
STRUCTURAL_EDGES: () => STRUCTURAL_EDGES,
|
|
15546
|
+
SYMBOL_SUMMARY_KINDS: () => SYMBOL_SUMMARY_KINDS,
|
|
15547
|
+
SymbolSummarySidecarSchema: () => SymbolSummarySidecarSchema,
|
|
15452
15548
|
TAXONOMY_EDGES: () => TAXONOMY_EDGES,
|
|
15453
15549
|
TRANSFER_EDGES: () => TRANSFER_EDGES,
|
|
15454
15550
|
TRIAGE_EDGES: () => TRIAGE_EDGES,
|
|
@@ -15468,6 +15564,7 @@ __export(src_exports, {
|
|
|
15468
15564
|
detectStance: () => detectStance,
|
|
15469
15565
|
digest: () => digest,
|
|
15470
15566
|
errorSignatureEqual: () => errorSignatureEqual,
|
|
15567
|
+
extractIdentifierTokens: () => extractIdentifierTokens,
|
|
15471
15568
|
genericCanonicalId: () => genericCanonicalId,
|
|
15472
15569
|
identityId: () => identityId,
|
|
15473
15570
|
isCausalProtected: () => isCausalProtected,
|
|
@@ -15493,9 +15590,12 @@ __export(src_exports, {
|
|
|
15493
15590
|
resolveCanonicalId: () => resolveCanonicalId,
|
|
15494
15591
|
sha256: () => sha256,
|
|
15495
15592
|
sha256Short: () => sha256Short,
|
|
15593
|
+
substituteSymbolSummaries: () => substituteSymbolSummaries,
|
|
15496
15594
|
summarizeIngestResult: () => summarizeIngestResult,
|
|
15595
|
+
summaryRejectionReason: () => summaryRejectionReason,
|
|
15497
15596
|
toCloudAttrs: () => toCloudAttrs,
|
|
15498
|
-
validateCastaliaPayload: () => validateCastaliaPayload
|
|
15597
|
+
validateCastaliaPayload: () => validateCastaliaPayload,
|
|
15598
|
+
vetSidecarSummaries: () => vetSidecarSummaries
|
|
15499
15599
|
});
|
|
15500
15600
|
var init_src = __esm({
|
|
15501
15601
|
"../../packages/shared/src/index.ts"() {
|
|
@@ -15504,6 +15604,7 @@ var init_src = __esm({
|
|
|
15504
15604
|
init_identity();
|
|
15505
15605
|
init_wire();
|
|
15506
15606
|
init_edge_rules();
|
|
15607
|
+
init_symbol_intent();
|
|
15507
15608
|
init_hash();
|
|
15508
15609
|
init_error_signature();
|
|
15509
15610
|
init_canonicalize();
|
|
@@ -17246,7 +17347,7 @@ function buildPackageIndex(store) {
|
|
|
17246
17347
|
}
|
|
17247
17348
|
return idx;
|
|
17248
17349
|
}
|
|
17249
|
-
function
|
|
17350
|
+
function escapeRe3(s) {
|
|
17250
17351
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17251
17352
|
}
|
|
17252
17353
|
function matchPackagesInText(text, index) {
|
|
@@ -17256,7 +17357,7 @@ function matchPackagesInText(text, index) {
|
|
|
17256
17357
|
for (const [key, node2] of index) {
|
|
17257
17358
|
if (key.length < MIN_NAME_LEN) continue;
|
|
17258
17359
|
if (!hay.includes(key)) continue;
|
|
17259
|
-
const esc3 =
|
|
17360
|
+
const esc3 = escapeRe3(key);
|
|
17260
17361
|
const bounded = new RegExp(`(?<![\\w@/.\\-])${esc3}(?![\\w])`);
|
|
17261
17362
|
if (!bounded.test(hay)) continue;
|
|
17262
17363
|
const verMatch = new RegExp(`${esc3}\\s*@?\\s*v?(\\d+(?:\\.\\d+){0,2})\\b`).exec(hay);
|
|
@@ -20507,6 +20608,20 @@ var init_oauth = __esm({
|
|
|
20507
20608
|
|
|
20508
20609
|
// ../../packages/cloud-client/src/client.ts
|
|
20509
20610
|
import { randomUUID } from "node:crypto";
|
|
20611
|
+
function sidecarForNodes(sidecar, nodes) {
|
|
20612
|
+
if (!sidecar) return void 0;
|
|
20613
|
+
const present = /* @__PURE__ */ new Set();
|
|
20614
|
+
for (const n of nodes) for (const tok of extractIdentifierTokens(n.description)) present.add(tok);
|
|
20615
|
+
const filtered = {};
|
|
20616
|
+
let count = 0;
|
|
20617
|
+
for (const [symbol2, entry] of Object.entries(sidecar)) {
|
|
20618
|
+
if (present.has(symbol2)) {
|
|
20619
|
+
filtered[symbol2] = entry;
|
|
20620
|
+
count++;
|
|
20621
|
+
}
|
|
20622
|
+
}
|
|
20623
|
+
return count > 0 ? filtered : void 0;
|
|
20624
|
+
}
|
|
20510
20625
|
function toWirePayload(batch, runId) {
|
|
20511
20626
|
const nodes = batch.nodes.map((n) => ({
|
|
20512
20627
|
canonicalId: n.id,
|
|
@@ -20525,7 +20640,8 @@ function toWirePayload(batch, runId) {
|
|
|
20525
20640
|
...typeof e.confidence === "number" ? { confidence: clamp012(e.confidence) } : {}
|
|
20526
20641
|
}
|
|
20527
20642
|
}));
|
|
20528
|
-
|
|
20643
|
+
const symbolSummaries = sidecarForNodes(batch.symbolSummaries, nodes);
|
|
20644
|
+
return { runId, source: "daemon", nodes, edges, ...symbolSummaries ? { symbolSummaries } : {} };
|
|
20529
20645
|
}
|
|
20530
20646
|
function clamp012(x) {
|
|
20531
20647
|
return Math.max(0, Math.min(1, x));
|
|
@@ -23939,21 +24055,32 @@ function isDistinctiveIdentifier(name2) {
|
|
|
23939
24055
|
if (/^[A-Z]/.test(name2) && name2.length >= 4) return true;
|
|
23940
24056
|
return name2.length >= 8;
|
|
23941
24057
|
}
|
|
23942
|
-
function buildSymbolLexicon(store) {
|
|
24058
|
+
function buildSymbolLexicon(store, summariesByBodyHash2) {
|
|
23943
24059
|
const lex = /* @__PURE__ */ new Map();
|
|
24060
|
+
const candidates = [];
|
|
23944
24061
|
for (const [label, kind] of SYMBOL_LABELS) {
|
|
23945
24062
|
for (const n of store.findNodesByLabel(label)) {
|
|
24063
|
+
const bodyHash = typeof n.attrs["bodyHash"] === "string" ? n.attrs["bodyHash"] : void 0;
|
|
24064
|
+
const summary = bodyHash ? summariesByBodyHash2?.get(bodyHash) : void 0;
|
|
23946
24065
|
for (const name2 of [n.description, String(n.attrs["qname"] ?? "")]) {
|
|
23947
|
-
if (name2 && isDistinctiveIdentifier(name2))
|
|
24066
|
+
if (name2 && isDistinctiveIdentifier(name2)) {
|
|
24067
|
+
if (!lex.has(name2)) lex.set(name2, { kind });
|
|
24068
|
+
if (summary) candidates.push([name2, summary]);
|
|
24069
|
+
}
|
|
23948
24070
|
}
|
|
23949
24071
|
}
|
|
23950
24072
|
}
|
|
24073
|
+
for (const [name2, summary] of candidates) {
|
|
24074
|
+
if (summaryRejectionReason(summary, (tok) => lex.has(tok)) === null) {
|
|
24075
|
+
lex.get(name2).summary = summary;
|
|
24076
|
+
}
|
|
24077
|
+
}
|
|
23951
24078
|
return lex;
|
|
23952
24079
|
}
|
|
23953
24080
|
function generalizeSymbols(text, lexicon, level = 1) {
|
|
23954
24081
|
const present = [];
|
|
23955
24082
|
const seen = /* @__PURE__ */ new Set();
|
|
23956
|
-
for (const m of text.matchAll(
|
|
24083
|
+
for (const m of text.matchAll(TOKEN_RE3)) {
|
|
23957
24084
|
const tok = m[0];
|
|
23958
24085
|
if (!seen.has(tok) && lexicon.has(tok)) {
|
|
23959
24086
|
seen.add(tok);
|
|
@@ -23963,17 +24090,19 @@ function generalizeSymbols(text, lexicon, level = 1) {
|
|
|
23963
24090
|
present.sort((a, b) => b.length - a.length);
|
|
23964
24091
|
let out2 = text;
|
|
23965
24092
|
for (const key of present) {
|
|
23966
|
-
const
|
|
23967
|
-
const
|
|
24093
|
+
const entry = lexicon.get(key);
|
|
24094
|
+
const phrase = level === 1 && entry.summary ? entry.summary : KIND_PHRASE[entry.kind][level === 1 ? "l1" : "l2"];
|
|
24095
|
+
const re = new RegExp(`(?<![A-Za-z0-9_$.])${escapeRe4(key)}(?![A-Za-z0-9_$])`, "g");
|
|
23968
24096
|
out2 = out2.replace(re, phrase);
|
|
23969
24097
|
}
|
|
23970
24098
|
return generalize(out2, { level }).text;
|
|
23971
24099
|
}
|
|
23972
|
-
var SYMBOL_LABELS, KIND_PHRASE,
|
|
24100
|
+
var SYMBOL_LABELS, KIND_PHRASE, RE_RESERVED2, escapeRe4, TOKEN_RE3;
|
|
23973
24101
|
var init_generalize_graph = __esm({
|
|
23974
24102
|
"src/generalize-graph.ts"() {
|
|
23975
24103
|
"use strict";
|
|
23976
24104
|
init_src8();
|
|
24105
|
+
init_src();
|
|
23977
24106
|
SYMBOL_LABELS = [
|
|
23978
24107
|
["Function", "function"],
|
|
23979
24108
|
["Method", "method"],
|
|
@@ -23988,9 +24117,9 @@ var init_generalize_graph = __esm({
|
|
|
23988
24117
|
interface: { l1: "an interface", l2: "an interface" },
|
|
23989
24118
|
constant: { l1: "a constant", l2: "a value" }
|
|
23990
24119
|
};
|
|
23991
|
-
|
|
23992
|
-
|
|
23993
|
-
|
|
24120
|
+
RE_RESERVED2 = /[.*+?^${}()|[\]\\]/g;
|
|
24121
|
+
escapeRe4 = (s) => s.replace(RE_RESERVED2, "\\$&");
|
|
24122
|
+
TOKEN_RE3 = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
|
|
23994
24123
|
}
|
|
23995
24124
|
});
|
|
23996
24125
|
|
|
@@ -24095,7 +24224,7 @@ async function dualAugment(opts) {
|
|
|
24095
24224
|
let seedProvenance = "local";
|
|
24096
24225
|
const calls = [];
|
|
24097
24226
|
try {
|
|
24098
|
-
const lexicon = buildSymbolLexicon(store);
|
|
24227
|
+
const lexicon = buildSymbolLexicon(store, opts.summaries);
|
|
24099
24228
|
const hardIds = [.../* @__PURE__ */ new Set([...seedNode ? [seedNode.id] : [], ...localHits.map((h) => h.id)])].filter((nid) => {
|
|
24100
24229
|
const n = seedNode && nid === seedNode.id ? seedNode : store.getNode(nid);
|
|
24101
24230
|
return !!n && isHardBridge(n);
|
|
@@ -25920,6 +26049,177 @@ var init_src10 = __esm({
|
|
|
25920
26049
|
}
|
|
25921
26050
|
});
|
|
25922
26051
|
|
|
26052
|
+
// src/symbol-summaries.ts
|
|
26053
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
26054
|
+
import { join as join6 } from "node:path";
|
|
26055
|
+
function symbolSummariesPath(configDir) {
|
|
26056
|
+
return join6(configDir, "symbol-summaries.json");
|
|
26057
|
+
}
|
|
26058
|
+
function loadSymbolSummaryCache(configDir) {
|
|
26059
|
+
const p = symbolSummariesPath(configDir);
|
|
26060
|
+
if (existsSync7(p)) {
|
|
26061
|
+
try {
|
|
26062
|
+
const raw2 = JSON.parse(readFileSync5(p, "utf8"));
|
|
26063
|
+
if (raw2 && raw2.version === 1 && raw2.entries && typeof raw2.entries === "object") {
|
|
26064
|
+
return { version: 1, entries: raw2.entries };
|
|
26065
|
+
}
|
|
26066
|
+
} catch {
|
|
26067
|
+
}
|
|
26068
|
+
}
|
|
26069
|
+
return { version: 1, entries: {} };
|
|
26070
|
+
}
|
|
26071
|
+
function saveSymbolSummaryCache(configDir, cache) {
|
|
26072
|
+
writeFileSync6(symbolSummariesPath(configDir), JSON.stringify(cache, null, 2), "utf8");
|
|
26073
|
+
}
|
|
26074
|
+
function summariesByBodyHash(cache) {
|
|
26075
|
+
const m = /* @__PURE__ */ new Map();
|
|
26076
|
+
for (const [bodyHash, e] of Object.entries(cache.entries)) {
|
|
26077
|
+
if (!e.rejected && typeof e.summary === "string" && e.summary.trim()) m.set(bodyHash, e.summary);
|
|
26078
|
+
}
|
|
26079
|
+
return m;
|
|
26080
|
+
}
|
|
26081
|
+
function parseSummaryJson(text, expected) {
|
|
26082
|
+
const start2 = text.indexOf("[");
|
|
26083
|
+
const end = text.lastIndexOf("]");
|
|
26084
|
+
if (start2 < 0 || end <= start2) return new Array(expected).fill(null);
|
|
26085
|
+
let arr;
|
|
26086
|
+
try {
|
|
26087
|
+
arr = JSON.parse(text.slice(start2, end + 1));
|
|
26088
|
+
} catch {
|
|
26089
|
+
return new Array(expected).fill(null);
|
|
26090
|
+
}
|
|
26091
|
+
if (!Array.isArray(arr)) return new Array(expected).fill(null);
|
|
26092
|
+
const out2 = [];
|
|
26093
|
+
for (let i2 = 0; i2 < expected; i2++) {
|
|
26094
|
+
const v = arr[i2];
|
|
26095
|
+
out2.push(typeof v === "string" && v.trim() ? v.trim().slice(0, MAX_SYMBOL_SUMMARY_CHARS) : null);
|
|
26096
|
+
}
|
|
26097
|
+
return out2;
|
|
26098
|
+
}
|
|
26099
|
+
function haikuIntentSummarizer(apiKey) {
|
|
26100
|
+
if (!apiKey) return void 0;
|
|
26101
|
+
return async (symbols) => {
|
|
26102
|
+
try {
|
|
26103
|
+
const listing = symbols.map(
|
|
26104
|
+
(s, i2) => `### ${i2 + 1}. kind: ${s.kind}
|
|
26105
|
+
name: ${s.name}
|
|
26106
|
+
${s.snippet ? `\`\`\`
|
|
26107
|
+
${s.snippet}
|
|
26108
|
+
\`\`\`` : "(no source available \u2014 describe from the name)"}`
|
|
26109
|
+
).join("\n\n");
|
|
26110
|
+
const resp = await fetch("https://api.anthropic.com/v1/messages", {
|
|
26111
|
+
method: "POST",
|
|
26112
|
+
headers: {
|
|
26113
|
+
"x-api-key": apiKey,
|
|
26114
|
+
"anthropic-version": "2023-06-01",
|
|
26115
|
+
"content-type": "application/json"
|
|
26116
|
+
},
|
|
26117
|
+
body: JSON.stringify({
|
|
26118
|
+
model: SUMMARY_MODEL,
|
|
26119
|
+
max_tokens: 2e3,
|
|
26120
|
+
messages: [{ role: "user", content: `${SUMMARY_PROMPT}
|
|
26121
|
+
|
|
26122
|
+
SYMBOLS:
|
|
26123
|
+
${listing}` }]
|
|
26124
|
+
})
|
|
26125
|
+
});
|
|
26126
|
+
if (!resp.ok) return symbols.map(() => null);
|
|
26127
|
+
const json2 = await resp.json();
|
|
26128
|
+
return parseSummaryJson(json2.content?.find((c) => c.type === "text")?.text ?? "", symbols.length);
|
|
26129
|
+
} catch {
|
|
26130
|
+
return symbols.map(() => null);
|
|
26131
|
+
}
|
|
26132
|
+
};
|
|
26133
|
+
}
|
|
26134
|
+
function envIntentSummarizer() {
|
|
26135
|
+
if (process.env["ERRATA_SYMBOL_SUMMARIES"] !== "1") return void 0;
|
|
26136
|
+
return haikuIntentSummarizer(process.env["ANTHROPIC_API_KEY"] ?? null);
|
|
26137
|
+
}
|
|
26138
|
+
function readSnippet(workspaceRoot, attrs) {
|
|
26139
|
+
const relPath = attrs["relPath"];
|
|
26140
|
+
const startByte = attrs["startByte"];
|
|
26141
|
+
const endByte = attrs["endByte"];
|
|
26142
|
+
if (typeof relPath !== "string" || typeof startByte !== "number" || typeof endByte !== "number") {
|
|
26143
|
+
return void 0;
|
|
26144
|
+
}
|
|
26145
|
+
try {
|
|
26146
|
+
const buf = readFileSync5(join6(workspaceRoot, ...relPath.split("/")));
|
|
26147
|
+
const slice = buf.subarray(Math.max(0, startByte), Math.min(buf.length, endByte));
|
|
26148
|
+
const text = slice.toString("utf8");
|
|
26149
|
+
return text.length > MAX_SNIPPET_CHARS ? text.slice(0, MAX_SNIPPET_CHARS) : text;
|
|
26150
|
+
} catch {
|
|
26151
|
+
return void 0;
|
|
26152
|
+
}
|
|
26153
|
+
}
|
|
26154
|
+
async function runSymbolSummarySweep(store, workspaceRoot, configDir, summarizer, opts = {}) {
|
|
26155
|
+
const maxSymbols = opts.maxSymbols ?? DEFAULT_MAX_SYMBOLS_PER_SWEEP;
|
|
26156
|
+
const batchSize = Math.max(1, opts.batchSize ?? DEFAULT_BATCH_SIZE);
|
|
26157
|
+
const cache = loadSymbolSummaryCache(configDir);
|
|
26158
|
+
const candidates = [];
|
|
26159
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26160
|
+
for (const [label, kind] of SUMMARY_LABELS) {
|
|
26161
|
+
for (const n of store.findNodesByLabel(label)) {
|
|
26162
|
+
const bodyHash = n.attrs["bodyHash"];
|
|
26163
|
+
if (typeof bodyHash !== "string" || !bodyHash || seen.has(bodyHash)) continue;
|
|
26164
|
+
if (cache.entries[bodyHash]) continue;
|
|
26165
|
+
const name2 = n.description;
|
|
26166
|
+
if (!name2 || !isDistinctiveIdentifier(name2)) continue;
|
|
26167
|
+
seen.add(bodyHash);
|
|
26168
|
+
const snippet = readSnippet(workspaceRoot, n.attrs);
|
|
26169
|
+
candidates.push({ bodyHash, name: name2, kind, ...snippet ? { snippet } : {} });
|
|
26170
|
+
}
|
|
26171
|
+
}
|
|
26172
|
+
const todo = candidates.slice(0, maxSymbols);
|
|
26173
|
+
const remaining = candidates.length - todo.length;
|
|
26174
|
+
if (todo.length === 0) return { generated: 0, rejected: 0, remaining };
|
|
26175
|
+
const lexicon = buildSymbolLexicon(store);
|
|
26176
|
+
const isKnown = (tok) => lexicon.has(tok);
|
|
26177
|
+
let generated = 0;
|
|
26178
|
+
let rejected = 0;
|
|
26179
|
+
for (let i2 = 0; i2 < todo.length; i2 += batchSize) {
|
|
26180
|
+
const batch = todo.slice(i2, i2 + batchSize);
|
|
26181
|
+
const phrases = await summarizer(batch);
|
|
26182
|
+
const now = Date.now();
|
|
26183
|
+
for (let j = 0; j < batch.length; j++) {
|
|
26184
|
+
const sym = batch[j];
|
|
26185
|
+
const phrase = phrases[j];
|
|
26186
|
+
if (phrase == null) continue;
|
|
26187
|
+
if (summaryRejectionReason(phrase, isKnown) === null) {
|
|
26188
|
+
cache.entries[sym.bodyHash] = { summary: phrase, model: SUMMARY_MODEL, createdAt: now };
|
|
26189
|
+
generated++;
|
|
26190
|
+
} else {
|
|
26191
|
+
cache.entries[sym.bodyHash] = { rejected: true, model: SUMMARY_MODEL, createdAt: now };
|
|
26192
|
+
rejected++;
|
|
26193
|
+
}
|
|
26194
|
+
}
|
|
26195
|
+
saveSymbolSummaryCache(configDir, cache);
|
|
26196
|
+
}
|
|
26197
|
+
return { generated, rejected, remaining };
|
|
26198
|
+
}
|
|
26199
|
+
var SUMMARY_LABELS, MAX_SNIPPET_CHARS, DEFAULT_MAX_SYMBOLS_PER_SWEEP, DEFAULT_BATCH_SIZE, SUMMARY_MODEL, SUMMARY_PROMPT;
|
|
26200
|
+
var init_symbol_summaries = __esm({
|
|
26201
|
+
"src/symbol-summaries.ts"() {
|
|
26202
|
+
"use strict";
|
|
26203
|
+
init_src();
|
|
26204
|
+
init_generalize_graph();
|
|
26205
|
+
SUMMARY_LABELS = [
|
|
26206
|
+
["Function", "function"],
|
|
26207
|
+
["Method", "method"],
|
|
26208
|
+
["Class", "class"]
|
|
26209
|
+
];
|
|
26210
|
+
MAX_SNIPPET_CHARS = 1500;
|
|
26211
|
+
DEFAULT_MAX_SYMBOLS_PER_SWEEP = 64;
|
|
26212
|
+
DEFAULT_BATCH_SIZE = 16;
|
|
26213
|
+
SUMMARY_MODEL = "claude-haiku-4-5-20251001";
|
|
26214
|
+
SUMMARY_PROMPT = `For each code symbol below, write ONE short English phrase stating its intent/role, shaped like "a <kind> that <does what>" (e.g. "a function that binds the server's listen port").
|
|
26215
|
+
HARD RULES \u2014 a violating phrase is discarded:
|
|
26216
|
+
- NEVER include any identifier, symbol name, variable, type name, file path, or module name from the code \u2014 describe meaning in plain English words only.
|
|
26217
|
+
- NEVER include quoted strings, literals, numbers copied from the code, or code syntax.
|
|
26218
|
+
- One phrase per symbol, under 200 characters, lowercase start, no trailing period.
|
|
26219
|
+
Output a JSON array of strings, one per symbol in the SAME ORDER (use null for a symbol you cannot describe). Output JSON only, no prose.`;
|
|
26220
|
+
}
|
|
26221
|
+
});
|
|
26222
|
+
|
|
25923
26223
|
// ../../packages/indexer/src/simhash.ts
|
|
25924
26224
|
function fnv1a64(s) {
|
|
25925
26225
|
let h = FNV_OFFSET;
|
|
@@ -26143,9 +26443,9 @@ var init_identity2 = __esm({
|
|
|
26143
26443
|
});
|
|
26144
26444
|
|
|
26145
26445
|
// ../../packages/indexer/src/pipeline.ts
|
|
26146
|
-
import { appendFileSync, readFileSync as
|
|
26446
|
+
import { appendFileSync, readFileSync as readFileSync6, statSync } from "node:fs";
|
|
26147
26447
|
import { readdir } from "node:fs/promises";
|
|
26148
|
-
import { extname, join as
|
|
26448
|
+
import { extname, join as join7, relative as relative2, sep } from "node:path";
|
|
26149
26449
|
import { createHash as createHash3 } from "node:crypto";
|
|
26150
26450
|
import { execFileSync } from "node:child_process";
|
|
26151
26451
|
function nowTs() {
|
|
@@ -26261,7 +26561,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
26261
26561
|
for (const rel of [...changedRelPaths]) {
|
|
26262
26562
|
let h;
|
|
26263
26563
|
try {
|
|
26264
|
-
h = createHash3("sha256").update(
|
|
26564
|
+
h = createHash3("sha256").update(readFileSync6(join7(rootPath, rel))).digest("hex");
|
|
26265
26565
|
} catch {
|
|
26266
26566
|
continue;
|
|
26267
26567
|
}
|
|
@@ -26308,13 +26608,13 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
26308
26608
|
let parsedFiles = 0;
|
|
26309
26609
|
for (const rel of changedRelPaths) {
|
|
26310
26610
|
if (parsedFiles++ > 0) await new Promise((r2) => setImmediate(r2));
|
|
26311
|
-
const abs =
|
|
26611
|
+
const abs = join7(rootPath, ...rel.split("/"));
|
|
26312
26612
|
const ext = extname(abs).toLowerCase();
|
|
26313
26613
|
const provider = providers.find((p) => p.fileExtensions.includes(ext));
|
|
26314
26614
|
if (!provider) continue;
|
|
26315
26615
|
let symbols;
|
|
26316
26616
|
try {
|
|
26317
|
-
symbols = provider.extractSymbols(
|
|
26617
|
+
symbols = provider.extractSymbols(readFileSync6(abs, "utf8"), abs);
|
|
26318
26618
|
} catch {
|
|
26319
26619
|
continue;
|
|
26320
26620
|
}
|
|
@@ -26614,7 +26914,7 @@ async function runIndexer(store, opts) {
|
|
|
26614
26914
|
report.filesSkipped++;
|
|
26615
26915
|
continue;
|
|
26616
26916
|
}
|
|
26617
|
-
source =
|
|
26917
|
+
source = readFileSync6(f.absPath, "utf8");
|
|
26618
26918
|
} catch {
|
|
26619
26919
|
report.filesSkipped++;
|
|
26620
26920
|
continue;
|
|
@@ -26666,7 +26966,7 @@ async function runIndexer(store, opts) {
|
|
|
26666
26966
|
const depth = fileNode.relPath.split("/").length;
|
|
26667
26967
|
if (depth !== 3) continue;
|
|
26668
26968
|
try {
|
|
26669
|
-
const pkg = JSON.parse(
|
|
26969
|
+
const pkg = JSON.parse(readFileSync6(fileNode.absPath, "utf8"));
|
|
26670
26970
|
if (!pkg.name) continue;
|
|
26671
26971
|
const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
|
|
26672
26972
|
const candidates = [
|
|
@@ -27048,7 +27348,7 @@ async function scan(root, current, ignores, providers, out2) {
|
|
|
27048
27348
|
for (const ent of entries) {
|
|
27049
27349
|
if (ignores.has(ent.name)) continue;
|
|
27050
27350
|
if (ent.name.startsWith(".") && ent.name !== ".") continue;
|
|
27051
|
-
const abs =
|
|
27351
|
+
const abs = join7(current, ent.name);
|
|
27052
27352
|
if (ent.isDirectory()) {
|
|
27053
27353
|
await scan(root, abs, ignores, providers, out2);
|
|
27054
27354
|
} else if (ent.isFile()) {
|
|
@@ -27094,7 +27394,7 @@ function gitListFiles(root, ignores, providers) {
|
|
|
27094
27394
|
if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
|
|
27095
27395
|
continue;
|
|
27096
27396
|
}
|
|
27097
|
-
const abs =
|
|
27397
|
+
const abs = join7(root, rel);
|
|
27098
27398
|
let size;
|
|
27099
27399
|
try {
|
|
27100
27400
|
size = statSync(abs).size;
|
|
@@ -27117,7 +27417,7 @@ function upsertFile(store, id, f, workspaceId2) {
|
|
|
27117
27417
|
const now = nowTs();
|
|
27118
27418
|
let contentHash;
|
|
27119
27419
|
try {
|
|
27120
|
-
contentHash = createHash3("sha256").update(
|
|
27420
|
+
contentHash = createHash3("sha256").update(readFileSync6(f.absPath)).digest("hex");
|
|
27121
27421
|
} catch {
|
|
27122
27422
|
}
|
|
27123
27423
|
const node2 = {
|
|
@@ -31479,8 +31779,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
31479
31779
|
|
|
31480
31780
|
// ../../packages/indexer/src/languages/tree-sitter-loader.ts
|
|
31481
31781
|
import { fileURLToPath } from "node:url";
|
|
31482
|
-
import { dirname as dirname4, join as
|
|
31483
|
-
import { existsSync as
|
|
31782
|
+
import { dirname as dirname4, join as join8 } from "node:path";
|
|
31783
|
+
import { existsSync as existsSync8, readdirSync as readdirSync2 } from "node:fs";
|
|
31484
31784
|
import { createRequire as createRequire2 } from "node:module";
|
|
31485
31785
|
function entryDir() {
|
|
31486
31786
|
try {
|
|
@@ -31494,27 +31794,27 @@ function entryDir() {
|
|
|
31494
31794
|
}
|
|
31495
31795
|
function findWasmDir() {
|
|
31496
31796
|
const here = entryDir();
|
|
31497
|
-
const seaWasm =
|
|
31498
|
-
if (
|
|
31797
|
+
const seaWasm = join8(here, "resources", "wasm");
|
|
31798
|
+
if (existsSync8(join8(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
|
|
31499
31799
|
let dir = here;
|
|
31500
31800
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
31501
|
-
const flat =
|
|
31801
|
+
const flat = join8(
|
|
31502
31802
|
dir,
|
|
31503
31803
|
"node_modules",
|
|
31504
31804
|
"@vscode",
|
|
31505
31805
|
"tree-sitter-wasm",
|
|
31506
31806
|
"wasm"
|
|
31507
31807
|
);
|
|
31508
|
-
if (
|
|
31808
|
+
if (existsSync8(join8(flat, "tree-sitter-typescript.wasm"))) return flat;
|
|
31509
31809
|
dir = dirname4(dir);
|
|
31510
31810
|
}
|
|
31511
31811
|
let root = here;
|
|
31512
31812
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
31513
|
-
const pnpmDir =
|
|
31514
|
-
if (
|
|
31813
|
+
const pnpmDir = join8(root, "node_modules", ".pnpm");
|
|
31814
|
+
if (existsSync8(pnpmDir)) {
|
|
31515
31815
|
for (const entry of readdirSync2(pnpmDir)) {
|
|
31516
31816
|
if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
|
|
31517
|
-
const candidate =
|
|
31817
|
+
const candidate = join8(
|
|
31518
31818
|
pnpmDir,
|
|
31519
31819
|
entry,
|
|
31520
31820
|
"node_modules",
|
|
@@ -31522,7 +31822,7 @@ function findWasmDir() {
|
|
|
31522
31822
|
"tree-sitter-wasm",
|
|
31523
31823
|
"wasm"
|
|
31524
31824
|
);
|
|
31525
|
-
if (
|
|
31825
|
+
if (existsSync8(join8(candidate, "tree-sitter-typescript.wasm"))) {
|
|
31526
31826
|
return candidate;
|
|
31527
31827
|
}
|
|
31528
31828
|
}
|
|
@@ -31536,27 +31836,27 @@ function findWasmDir() {
|
|
|
31536
31836
|
}
|
|
31537
31837
|
function findRuntimeDir() {
|
|
31538
31838
|
const here = entryDir();
|
|
31539
|
-
const seaRuntime =
|
|
31540
|
-
if (
|
|
31839
|
+
const seaRuntime = join8(here, "resources", "wasm");
|
|
31840
|
+
if (existsSync8(join8(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
|
|
31541
31841
|
let dir = here;
|
|
31542
31842
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
31543
|
-
const flat =
|
|
31544
|
-
if (
|
|
31843
|
+
const flat = join8(dir, "node_modules", "web-tree-sitter");
|
|
31844
|
+
if (existsSync8(join8(flat, "web-tree-sitter.wasm"))) return flat;
|
|
31545
31845
|
dir = dirname4(dir);
|
|
31546
31846
|
}
|
|
31547
31847
|
let root = here;
|
|
31548
31848
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
31549
|
-
const pnpmDir =
|
|
31550
|
-
if (
|
|
31849
|
+
const pnpmDir = join8(root, "node_modules", ".pnpm");
|
|
31850
|
+
if (existsSync8(pnpmDir)) {
|
|
31551
31851
|
for (const entry of readdirSync2(pnpmDir)) {
|
|
31552
31852
|
if (entry.startsWith("web-tree-sitter@")) {
|
|
31553
|
-
const candidate =
|
|
31853
|
+
const candidate = join8(
|
|
31554
31854
|
pnpmDir,
|
|
31555
31855
|
entry,
|
|
31556
31856
|
"node_modules",
|
|
31557
31857
|
"web-tree-sitter"
|
|
31558
31858
|
);
|
|
31559
|
-
if (
|
|
31859
|
+
if (existsSync8(join8(candidate, "web-tree-sitter.wasm"))) {
|
|
31560
31860
|
return candidate;
|
|
31561
31861
|
}
|
|
31562
31862
|
}
|
|
@@ -31573,7 +31873,7 @@ async function loadWebTreeSitter() {
|
|
|
31573
31873
|
void err2;
|
|
31574
31874
|
}
|
|
31575
31875
|
const here = entryDir();
|
|
31576
|
-
const seaResourceBase =
|
|
31876
|
+
const seaResourceBase = join8(here, "resources", "_resolve.js");
|
|
31577
31877
|
const resourceRequire = createRequire2(seaResourceBase);
|
|
31578
31878
|
return resourceRequire("web-tree-sitter");
|
|
31579
31879
|
}
|
|
@@ -31588,9 +31888,9 @@ async function ensureTreeSitterReady() {
|
|
|
31588
31888
|
await Parser2.init({
|
|
31589
31889
|
locateFile: (name2) => {
|
|
31590
31890
|
if (name2 === "tree-sitter.wasm" || name2 === "web-tree-sitter.wasm") {
|
|
31591
|
-
return
|
|
31891
|
+
return join8(runtime, name2);
|
|
31592
31892
|
}
|
|
31593
|
-
return
|
|
31893
|
+
return join8(grammars, name2);
|
|
31594
31894
|
}
|
|
31595
31895
|
});
|
|
31596
31896
|
})();
|
|
@@ -31602,7 +31902,7 @@ async function loadGrammar(name2) {
|
|
|
31602
31902
|
if (cached2) return cached2;
|
|
31603
31903
|
if (!languageClass) throw new Error("tree-sitter not initialized");
|
|
31604
31904
|
const grammars = findWasmDir();
|
|
31605
|
-
const lang = await languageClass.load(
|
|
31905
|
+
const lang = await languageClass.load(join8(grammars, `${name2}.wasm`));
|
|
31606
31906
|
grammarCache.set(name2, lang);
|
|
31607
31907
|
return lang;
|
|
31608
31908
|
}
|
|
@@ -34504,7 +34804,7 @@ var init_src11 = __esm({
|
|
|
34504
34804
|
// src/reconcile.ts
|
|
34505
34805
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
34506
34806
|
import { readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
34507
|
-
import { join as
|
|
34807
|
+
import { join as join9, relative as relative3, sep as sep2 } from "node:path";
|
|
34508
34808
|
function gitSourceFiles(root) {
|
|
34509
34809
|
let stdout;
|
|
34510
34810
|
try {
|
|
@@ -34519,7 +34819,7 @@ function gitSourceFiles(root) {
|
|
|
34519
34819
|
const out2 = [];
|
|
34520
34820
|
for (const rel of stdout.split("\0")) {
|
|
34521
34821
|
if (!rel || !SOURCE_RE.test(rel)) continue;
|
|
34522
|
-
const abs =
|
|
34822
|
+
const abs = join9(root, rel);
|
|
34523
34823
|
if (IGNORED.test(abs)) continue;
|
|
34524
34824
|
out2.push(abs);
|
|
34525
34825
|
}
|
|
@@ -34534,7 +34834,7 @@ function* walkSource(dir) {
|
|
|
34534
34834
|
}
|
|
34535
34835
|
for (const e of entries) {
|
|
34536
34836
|
const name2 = String(e.name);
|
|
34537
|
-
const full =
|
|
34837
|
+
const full = join9(dir, name2);
|
|
34538
34838
|
if (IGNORED.test(full)) continue;
|
|
34539
34839
|
if (e.isDirectory()) yield* walkSource(full);
|
|
34540
34840
|
else if (SOURCE_RE.test(name2)) yield full;
|
|
@@ -34612,7 +34912,7 @@ __export(mcp_exports, {
|
|
|
34612
34912
|
runTool: () => runTool,
|
|
34613
34913
|
searchGraph: () => searchGraph
|
|
34614
34914
|
});
|
|
34615
|
-
import { existsSync as
|
|
34915
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
|
|
34616
34916
|
import { resolve } from "node:path";
|
|
34617
34917
|
function collectEnrichmentPulls(store, opts = {}) {
|
|
34618
34918
|
const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
|
|
@@ -34725,10 +35025,10 @@ function showNode(store, node2, maxLines) {
|
|
|
34725
35025
|
if (!relPath) return { found: false, reason: "no file owner for node" };
|
|
34726
35026
|
const workspaceRoot = process.cwd();
|
|
34727
35027
|
const absPath = resolve(workspaceRoot, relPath);
|
|
34728
|
-
if (!
|
|
35028
|
+
if (!existsSync9(absPath)) {
|
|
34729
35029
|
return { found: false, reason: `file not found on disk: ${absPath}` };
|
|
34730
35030
|
}
|
|
34731
|
-
const source =
|
|
35031
|
+
const source = readFileSync7(absPath, "utf8");
|
|
34732
35032
|
const attrs = node2.attrs;
|
|
34733
35033
|
let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
|
|
34734
35034
|
let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
|
|
@@ -34941,7 +35241,20 @@ function buildToolContext() {
|
|
|
34941
35241
|
async function runMcpServer(workspaceRoot) {
|
|
34942
35242
|
const paths = workspacePaths(workspaceRoot);
|
|
34943
35243
|
const store = openGraphStore({ path: paths.castalia });
|
|
34944
|
-
|
|
35244
|
+
let summariesMemo = null;
|
|
35245
|
+
const symbolSummaries = () => {
|
|
35246
|
+
const now = Date.now();
|
|
35247
|
+
if (!summariesMemo || now - summariesMemo.at > 6e4) {
|
|
35248
|
+
let map2 = /* @__PURE__ */ new Map();
|
|
35249
|
+
try {
|
|
35250
|
+
map2 = summariesByBodyHash(loadSymbolSummaryCache(paths.configDir));
|
|
35251
|
+
} catch {
|
|
35252
|
+
}
|
|
35253
|
+
summariesMemo = { at: now, map: map2 };
|
|
35254
|
+
}
|
|
35255
|
+
return summariesMemo.map;
|
|
35256
|
+
};
|
|
35257
|
+
const handle2 = createMcpHandler(store, { ...buildToolContext(), symbolSummaries });
|
|
34945
35258
|
process.stdin.setEncoding("utf8");
|
|
34946
35259
|
let buffer = "";
|
|
34947
35260
|
process.stdin.on("data", (chunk) => {
|
|
@@ -34980,6 +35293,7 @@ var init_mcp = __esm({
|
|
|
34980
35293
|
init_src2();
|
|
34981
35294
|
init_src10();
|
|
34982
35295
|
init_paths();
|
|
35296
|
+
init_symbol_summaries();
|
|
34983
35297
|
init_webui();
|
|
34984
35298
|
init_reconcile();
|
|
34985
35299
|
init_agent_signals();
|
|
@@ -35052,7 +35366,14 @@ var init_mcp = __esm({
|
|
|
35052
35366
|
score: h.pageRank,
|
|
35053
35367
|
hops: 0
|
|
35054
35368
|
}));
|
|
35055
|
-
const dual = await dualAugment({
|
|
35369
|
+
const dual = await dualAugment({
|
|
35370
|
+
store,
|
|
35371
|
+
cloud: ctx.cloud,
|
|
35372
|
+
localHits,
|
|
35373
|
+
queryText: query,
|
|
35374
|
+
limit,
|
|
35375
|
+
...ctx.symbolSummaries ? { summaries: ctx.symbolSummaries() } : {}
|
|
35376
|
+
});
|
|
35056
35377
|
if (dual.status === "merged") {
|
|
35057
35378
|
return {
|
|
35058
35379
|
query,
|
|
@@ -35217,7 +35538,8 @@ var init_mcp = __esm({
|
|
|
35217
35538
|
cloud: ctx.cloud,
|
|
35218
35539
|
localHits,
|
|
35219
35540
|
seedNode,
|
|
35220
|
-
limit: args2["limit"] != null ? Number(args2["limit"]) : 20
|
|
35541
|
+
limit: args2["limit"] != null ? Number(args2["limit"]) : 20,
|
|
35542
|
+
...ctx.symbolSummaries ? { summaries: ctx.symbolSummaries() } : {}
|
|
35221
35543
|
});
|
|
35222
35544
|
if (dual.status === "merged") {
|
|
35223
35545
|
return {
|
|
@@ -35732,7 +36054,14 @@ var init_mcp = __esm({
|
|
|
35732
36054
|
score: h.score,
|
|
35733
36055
|
hops: 0
|
|
35734
36056
|
}));
|
|
35735
|
-
const dual = await dualAugment({
|
|
36057
|
+
const dual = await dualAugment({
|
|
36058
|
+
store,
|
|
36059
|
+
cloud: ctx.cloud,
|
|
36060
|
+
localHits,
|
|
36061
|
+
seedNode: node2,
|
|
36062
|
+
limit,
|
|
36063
|
+
...ctx.symbolSummaries ? { summaries: ctx.symbolSummaries() } : {}
|
|
36064
|
+
});
|
|
35736
36065
|
if (dual.status === "merged") {
|
|
35737
36066
|
return {
|
|
35738
36067
|
seedId: id,
|
|
@@ -35923,7 +36252,7 @@ var init_mcp = __esm({
|
|
|
35923
36252
|
inputSchema: { type: "object", properties: {} },
|
|
35924
36253
|
handler: () => {
|
|
35925
36254
|
const path2 = sharedStorePath();
|
|
35926
|
-
if (!
|
|
36255
|
+
if (!existsSync9(path2)) return { count: 0, pending: [] };
|
|
35927
36256
|
const shared = openGraphStore({ path: path2 });
|
|
35928
36257
|
try {
|
|
35929
36258
|
const pending = pendingAbstractions(shared);
|
|
@@ -35954,7 +36283,7 @@ var init_mcp = __esm({
|
|
|
35954
36283
|
},
|
|
35955
36284
|
handler: (args2) => {
|
|
35956
36285
|
const path2 = sharedStorePath();
|
|
35957
|
-
if (!
|
|
36286
|
+
if (!existsSync9(path2)) return { count: 0, routes: [] };
|
|
35958
36287
|
const shared = openGraphStore({ path: path2 });
|
|
35959
36288
|
try {
|
|
35960
36289
|
const result = triageOf(shared, {
|
|
@@ -36339,8 +36668,8 @@ __export(vfile_exports, {
|
|
|
36339
36668
|
resolvePath: () => resolvePath,
|
|
36340
36669
|
segmentsOf: () => segmentsOf
|
|
36341
36670
|
});
|
|
36342
|
-
import { writeFileSync as
|
|
36343
|
-
import { join as
|
|
36671
|
+
import { writeFileSync as writeFileSync7 } from "node:fs";
|
|
36672
|
+
import { join as join10, resolve as resolve2, sep as sep3 } from "node:path";
|
|
36344
36673
|
function segmentsOf(rawPath) {
|
|
36345
36674
|
let p = rawPath.replace(/\\/g, "/");
|
|
36346
36675
|
p = p.replace(/^.*\.errata\/g\//, "").replace(/^\/?g\//, "").replace(/^\/+/, "");
|
|
@@ -36414,14 +36743,14 @@ async function renderVFile(rawPath, store, ctx = {}) {
|
|
|
36414
36743
|
}
|
|
36415
36744
|
async function materializeVFile(rawPath, workspaceRoot, store, ctx = {}) {
|
|
36416
36745
|
const segs = segmentsOf(rawPath);
|
|
36417
|
-
const gRoot =
|
|
36746
|
+
const gRoot = join10(workspaceRoot, ".errata", "g");
|
|
36418
36747
|
const abs = resolve2(gRoot, ...segs.length ? segs : ["index"]);
|
|
36419
36748
|
if (abs !== gRoot && !abs.startsWith(gRoot + sep3)) {
|
|
36420
36749
|
throw new Error(`refusing to materialize outside .errata/g: ${rawPath}`);
|
|
36421
36750
|
}
|
|
36422
36751
|
const text = await renderVFile(rawPath, store, ctx);
|
|
36423
36752
|
ensureParent(abs);
|
|
36424
|
-
|
|
36753
|
+
writeFileSync7(abs, text, "utf8");
|
|
36425
36754
|
return abs;
|
|
36426
36755
|
}
|
|
36427
36756
|
async function materializeOverview(workspaceRoot, store, ctx = {}) {
|
|
@@ -36506,25 +36835,25 @@ the tool surface; the path is the thin, composable channel.
|
|
|
36506
36835
|
|
|
36507
36836
|
// src/outbox.ts
|
|
36508
36837
|
import {
|
|
36509
|
-
existsSync as
|
|
36838
|
+
existsSync as existsSync10,
|
|
36510
36839
|
readdirSync as readdirSync4,
|
|
36511
|
-
readFileSync as
|
|
36840
|
+
readFileSync as readFileSync8,
|
|
36512
36841
|
renameSync,
|
|
36513
36842
|
unlinkSync,
|
|
36514
|
-
writeFileSync as
|
|
36843
|
+
writeFileSync as writeFileSync8
|
|
36515
36844
|
} from "node:fs";
|
|
36516
|
-
import { join as
|
|
36845
|
+
import { join as join11 } from "node:path";
|
|
36517
36846
|
import { createHash as createHash11 } from "node:crypto";
|
|
36518
36847
|
function enqueueOutbox(paths, payload) {
|
|
36519
36848
|
ensureDir(paths.outbox);
|
|
36520
36849
|
const id = createHash11("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
|
|
36521
|
-
const file2 =
|
|
36522
|
-
|
|
36850
|
+
const file2 = join11(paths.outbox, `${Date.now()}-${id}.json`);
|
|
36851
|
+
writeFileSync8(file2, JSON.stringify(payload, null, 2), "utf8");
|
|
36523
36852
|
return file2;
|
|
36524
36853
|
}
|
|
36525
36854
|
async function flushOutbox(paths, client, store) {
|
|
36526
36855
|
ensureDir(paths.outbox);
|
|
36527
|
-
const entries =
|
|
36856
|
+
const entries = existsSync10(paths.outbox) ? readdirSync4(paths.outbox) : [];
|
|
36528
36857
|
let uploaded = 0;
|
|
36529
36858
|
let failed = 0;
|
|
36530
36859
|
const quarantine = (abs, reason) => {
|
|
@@ -36535,10 +36864,10 @@ async function flushOutbox(paths, client, store) {
|
|
|
36535
36864
|
}
|
|
36536
36865
|
};
|
|
36537
36866
|
for (const f of entries.filter((e) => e.endsWith(".json")).sort()) {
|
|
36538
|
-
const abs =
|
|
36867
|
+
const abs = join11(paths.outbox, f);
|
|
36539
36868
|
let payload;
|
|
36540
36869
|
try {
|
|
36541
|
-
payload = JSON.parse(
|
|
36870
|
+
payload = JSON.parse(readFileSync8(abs, "utf8"));
|
|
36542
36871
|
} catch {
|
|
36543
36872
|
failed++;
|
|
36544
36873
|
quarantine(abs, "unparseable JSON");
|
|
@@ -36566,7 +36895,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
36566
36895
|
}
|
|
36567
36896
|
}
|
|
36568
36897
|
}
|
|
36569
|
-
const remainingFiles =
|
|
36898
|
+
const remainingFiles = existsSync10(paths.outbox) ? readdirSync4(paths.outbox).filter((e) => e.endsWith(".json")) : [];
|
|
36570
36899
|
return { uploaded, failed, remaining: remainingFiles.length };
|
|
36571
36900
|
}
|
|
36572
36901
|
var init_outbox = __esm({
|
|
@@ -36585,7 +36914,7 @@ __export(webui_exports, {
|
|
|
36585
36914
|
findFileByPath: () => findFileByPath,
|
|
36586
36915
|
recallForFile: () => recallForFile
|
|
36587
36916
|
});
|
|
36588
|
-
import { join as
|
|
36917
|
+
import { join as join12 } from "node:path";
|
|
36589
36918
|
function fileUriToFsPath(raw2) {
|
|
36590
36919
|
let p = raw2.replace(/^file:\/\//, "").replace(/\\/g, "/");
|
|
36591
36920
|
if (/^\/[A-Za-z]:/.test(p)) p = p.slice(1);
|
|
@@ -36946,7 +37275,7 @@ function buildWebUi(deps) {
|
|
|
36946
37275
|
} catch {
|
|
36947
37276
|
return c.json({});
|
|
36948
37277
|
}
|
|
36949
|
-
const block = readManagedBlockWithHash(
|
|
37278
|
+
const block = readManagedBlockWithHash(join12(deps.paths.root, "AGENTS.md"));
|
|
36950
37279
|
const decision = decideContextInject({
|
|
36951
37280
|
event: String(body2["hook_event_name"] ?? "UserPromptSubmit"),
|
|
36952
37281
|
source: String(body2["source"] ?? ""),
|
|
@@ -37548,12 +37877,12 @@ var init_report_render = __esm({
|
|
|
37548
37877
|
|
|
37549
37878
|
// src/cli.ts
|
|
37550
37879
|
init_src5();
|
|
37551
|
-
import { closeSync as closeSync2, existsSync as
|
|
37552
|
-
import { join as
|
|
37880
|
+
import { closeSync as closeSync2, existsSync as existsSync20, openSync as openSync2, readFileSync as readFileSync19, renameSync as renameSync3, statSync as statSync5 } from "node:fs";
|
|
37881
|
+
import { join as join23 } from "node:path";
|
|
37553
37882
|
import { spawn as spawn3 } from "node:child_process";
|
|
37554
37883
|
|
|
37555
37884
|
// src/daemon.ts
|
|
37556
|
-
import { existsSync as
|
|
37885
|
+
import { existsSync as existsSync16, writeFileSync as writeFileSync13 } from "node:fs";
|
|
37557
37886
|
|
|
37558
37887
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
37559
37888
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -38133,8 +38462,8 @@ init_config();
|
|
|
38133
38462
|
|
|
38134
38463
|
// src/engine.ts
|
|
38135
38464
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
38136
|
-
import { existsSync as
|
|
38137
|
-
import { join as
|
|
38465
|
+
import { existsSync as existsSync15, statSync as statSync4, appendFileSync as appendFileSync2, readdirSync as readdirSync7, renameSync as renameSync2, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "node:fs";
|
|
38466
|
+
import { join as join20, relative as relative6, sep as sep4 } from "node:path";
|
|
38138
38467
|
|
|
38139
38468
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
38140
38469
|
import { stat as statcb } from "fs";
|
|
@@ -39996,8 +40325,8 @@ init_src10();
|
|
|
39996
40325
|
init_review2();
|
|
39997
40326
|
|
|
39998
40327
|
// src/turn.ts
|
|
39999
|
-
import { closeSync, existsSync as
|
|
40000
|
-
import { basename as basename3, dirname as dirname7, join as
|
|
40328
|
+
import { closeSync, existsSync as existsSync11, fstatSync, openSync, readdirSync as readdirSync5, readSync, statSync as statSync3 } from "node:fs";
|
|
40329
|
+
import { basename as basename3, dirname as dirname7, join as join15 } from "node:path";
|
|
40001
40330
|
import { homedir as homedir3 } from "node:os";
|
|
40002
40331
|
function readTail(path2, maxBytes) {
|
|
40003
40332
|
let fd;
|
|
@@ -40106,11 +40435,11 @@ function turnsSince(turns, mark) {
|
|
|
40106
40435
|
return at >= 0 ? turns.slice(at + 1) : turns;
|
|
40107
40436
|
}
|
|
40108
40437
|
function claudeProjectDir(cwd, home = homedir3()) {
|
|
40109
|
-
return
|
|
40438
|
+
return join15(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
|
|
40110
40439
|
}
|
|
40111
40440
|
function recentTranscripts(cwd, opts = {}) {
|
|
40112
40441
|
const dir = claudeProjectDir(cwd, opts.home ?? homedir3());
|
|
40113
|
-
if (!
|
|
40442
|
+
if (!existsSync11(dir)) return [];
|
|
40114
40443
|
let names;
|
|
40115
40444
|
try {
|
|
40116
40445
|
names = readdirSync5(dir);
|
|
@@ -40121,7 +40450,7 @@ function recentTranscripts(cwd, opts = {}) {
|
|
|
40121
40450
|
const refs = [];
|
|
40122
40451
|
for (const name2 of names) {
|
|
40123
40452
|
if (!name2.endsWith(".jsonl")) continue;
|
|
40124
|
-
const path2 =
|
|
40453
|
+
const path2 = join15(dir, name2);
|
|
40125
40454
|
let mtimeMs;
|
|
40126
40455
|
try {
|
|
40127
40456
|
mtimeMs = statSync3(path2).mtimeMs;
|
|
@@ -40136,8 +40465,8 @@ function recentTranscripts(cwd, opts = {}) {
|
|
|
40136
40465
|
}
|
|
40137
40466
|
function subagentTranscripts(mainTranscriptPath, sessionId) {
|
|
40138
40467
|
if (!mainTranscriptPath || !sessionId) return [];
|
|
40139
|
-
const dir =
|
|
40140
|
-
if (!
|
|
40468
|
+
const dir = join15(dirname7(mainTranscriptPath), sessionId, "subagents");
|
|
40469
|
+
if (!existsSync11(dir)) return [];
|
|
40141
40470
|
let names;
|
|
40142
40471
|
try {
|
|
40143
40472
|
names = readdirSync5(dir);
|
|
@@ -40147,7 +40476,7 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
|
|
|
40147
40476
|
const refs = [];
|
|
40148
40477
|
for (const name2 of names) {
|
|
40149
40478
|
if (!name2.endsWith(".jsonl")) continue;
|
|
40150
|
-
const path2 =
|
|
40479
|
+
const path2 = join15(dir, name2);
|
|
40151
40480
|
let mtimeMs;
|
|
40152
40481
|
try {
|
|
40153
40482
|
mtimeMs = statSync3(path2).mtimeMs;
|
|
@@ -40164,7 +40493,7 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
|
|
|
40164
40493
|
init_src();
|
|
40165
40494
|
init_src2();
|
|
40166
40495
|
init_agent_signals();
|
|
40167
|
-
import { readFileSync as
|
|
40496
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
40168
40497
|
var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
|
|
40169
40498
|
var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
|
|
40170
40499
|
var HANDLE_RE = /\[([a-z0-9][\w-]{0,40})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
|
|
@@ -40414,13 +40743,13 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
|
|
|
40414
40743
|
entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
|
|
40415
40744
|
entries.length = HANDLE_MAP_MAX;
|
|
40416
40745
|
}
|
|
40417
|
-
|
|
40746
|
+
writeFileSync9(path2, JSON.stringify(Object.fromEntries(entries)));
|
|
40418
40747
|
} catch {
|
|
40419
40748
|
}
|
|
40420
40749
|
}
|
|
40421
40750
|
function readPrimingHandles(path2) {
|
|
40422
40751
|
try {
|
|
40423
|
-
return JSON.parse(
|
|
40752
|
+
return JSON.parse(readFileSync9(path2, "utf8"));
|
|
40424
40753
|
} catch {
|
|
40425
40754
|
return {};
|
|
40426
40755
|
}
|
|
@@ -40676,6 +41005,7 @@ ${conversation}` }]
|
|
|
40676
41005
|
}
|
|
40677
41006
|
|
|
40678
41007
|
// src/engine.ts
|
|
41008
|
+
init_symbol_summaries();
|
|
40679
41009
|
init_reconcile();
|
|
40680
41010
|
|
|
40681
41011
|
// src/episode.ts
|
|
@@ -40872,11 +41202,11 @@ init_outbox();
|
|
|
40872
41202
|
init_src8();
|
|
40873
41203
|
init_src();
|
|
40874
41204
|
init_src2();
|
|
40875
|
-
import { readFileSync as
|
|
40876
|
-
import { join as
|
|
41205
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
41206
|
+
import { join as join16 } from "node:path";
|
|
40877
41207
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
40878
41208
|
try {
|
|
40879
|
-
return
|
|
41209
|
+
return readFileSync10(join16(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
40880
41210
|
} catch {
|
|
40881
41211
|
return [];
|
|
40882
41212
|
}
|
|
@@ -41168,22 +41498,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
41168
41498
|
}
|
|
41169
41499
|
|
|
41170
41500
|
// src/git-sensor.ts
|
|
41171
|
-
import { existsSync as
|
|
41172
|
-
import { join as
|
|
41501
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, watch as fsWatch } from "node:fs";
|
|
41502
|
+
import { join as join17 } from "node:path";
|
|
41173
41503
|
function readFirstLine(path2) {
|
|
41174
41504
|
try {
|
|
41175
|
-
return
|
|
41505
|
+
return readFileSync11(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
41176
41506
|
} catch {
|
|
41177
41507
|
return null;
|
|
41178
41508
|
}
|
|
41179
41509
|
}
|
|
41180
41510
|
function readGitRefState(gitDir) {
|
|
41181
|
-
const head2 = readFirstLine(
|
|
41511
|
+
const head2 = readFirstLine(join17(gitDir, "HEAD"));
|
|
41182
41512
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
41183
41513
|
const branch = m ? m[1] : null;
|
|
41184
41514
|
let sha2 = null;
|
|
41185
41515
|
if (branch) {
|
|
41186
|
-
sha2 = readFirstLine(
|
|
41516
|
+
sha2 = readFirstLine(join17(gitDir, "refs", "heads", branch));
|
|
41187
41517
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
41188
41518
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
41189
41519
|
sha2 = head2;
|
|
@@ -41191,13 +41521,13 @@ function readGitRefState(gitDir) {
|
|
|
41191
41521
|
return {
|
|
41192
41522
|
branch,
|
|
41193
41523
|
sha: sha2,
|
|
41194
|
-
mergeHeadExists:
|
|
41195
|
-
origHeadExists:
|
|
41524
|
+
mergeHeadExists: existsSync12(join17(gitDir, "MERGE_HEAD")),
|
|
41525
|
+
origHeadExists: existsSync12(join17(gitDir, "ORIG_HEAD"))
|
|
41196
41526
|
};
|
|
41197
41527
|
}
|
|
41198
41528
|
function shaFromPackedRefs(gitDir, ref) {
|
|
41199
41529
|
try {
|
|
41200
|
-
for (const line of
|
|
41530
|
+
for (const line of readFileSync11(join17(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
41201
41531
|
const [sha2, name2] = line.split(/\s+/);
|
|
41202
41532
|
if (name2 === ref && sha2) return sha2;
|
|
41203
41533
|
}
|
|
@@ -41231,7 +41561,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
41231
41561
|
const settle = () => {
|
|
41232
41562
|
if (timer) clearTimeout(timer);
|
|
41233
41563
|
timer = setTimeout(() => {
|
|
41234
|
-
if (
|
|
41564
|
+
if (existsSync12(join17(gitDir, "index.lock"))) {
|
|
41235
41565
|
settle();
|
|
41236
41566
|
return;
|
|
41237
41567
|
}
|
|
@@ -41242,7 +41572,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
41242
41572
|
}, debounceMs);
|
|
41243
41573
|
};
|
|
41244
41574
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
41245
|
-
const p =
|
|
41575
|
+
const p = join17(gitDir, sub);
|
|
41246
41576
|
try {
|
|
41247
41577
|
watchers.push(fsWatch(p, settle));
|
|
41248
41578
|
} catch {
|
|
@@ -41467,21 +41797,21 @@ var TelemetryRecorder = class {
|
|
|
41467
41797
|
|
|
41468
41798
|
// src/skills.ts
|
|
41469
41799
|
import {
|
|
41470
|
-
existsSync as
|
|
41800
|
+
existsSync as existsSync13,
|
|
41471
41801
|
mkdirSync as mkdirSync5,
|
|
41472
|
-
readFileSync as
|
|
41802
|
+
readFileSync as readFileSync12,
|
|
41473
41803
|
readdirSync as readdirSync6,
|
|
41474
41804
|
unlinkSync as unlinkSync2,
|
|
41475
|
-
writeFileSync as
|
|
41805
|
+
writeFileSync as writeFileSync10
|
|
41476
41806
|
} from "node:fs";
|
|
41477
|
-
import { basename as basename4, join as
|
|
41807
|
+
import { basename as basename4, join as join18 } from "node:path";
|
|
41478
41808
|
function skillFileName(id) {
|
|
41479
41809
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
41480
41810
|
}
|
|
41481
41811
|
function readSkillManifest(manifestPath) {
|
|
41482
|
-
if (!
|
|
41812
|
+
if (!existsSync13(manifestPath)) return [];
|
|
41483
41813
|
try {
|
|
41484
|
-
const parsed = JSON.parse(
|
|
41814
|
+
const parsed = JSON.parse(readFileSync12(manifestPath, "utf8"));
|
|
41485
41815
|
return (parsed.skills ?? []).map((s) => ({
|
|
41486
41816
|
title: s.title ?? "",
|
|
41487
41817
|
layer: s.layer ?? "technique",
|
|
@@ -41504,7 +41834,7 @@ async function syncSkills(paths, client, seed) {
|
|
|
41504
41834
|
for (const s of res.skills) {
|
|
41505
41835
|
const fileName = skillFileName(s.id);
|
|
41506
41836
|
keep.add(fileName);
|
|
41507
|
-
|
|
41837
|
+
writeFileSync10(join18(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
41508
41838
|
rows.push({
|
|
41509
41839
|
id: s.id,
|
|
41510
41840
|
title: s.title,
|
|
@@ -41518,13 +41848,13 @@ async function syncSkills(paths, client, seed) {
|
|
|
41518
41848
|
if (!f.endsWith(".md")) continue;
|
|
41519
41849
|
if (keep.has(basename4(f))) continue;
|
|
41520
41850
|
try {
|
|
41521
|
-
unlinkSync2(
|
|
41851
|
+
unlinkSync2(join18(paths.skillsDir, f));
|
|
41522
41852
|
pruned++;
|
|
41523
41853
|
} catch {
|
|
41524
41854
|
}
|
|
41525
41855
|
}
|
|
41526
41856
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
41527
|
-
|
|
41857
|
+
writeFileSync10(
|
|
41528
41858
|
paths.skillsManifest,
|
|
41529
41859
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
41530
41860
|
"utf8"
|
|
@@ -41661,30 +41991,30 @@ var CausalBuffer = class {
|
|
|
41661
41991
|
// src/profile.ts
|
|
41662
41992
|
init_src2();
|
|
41663
41993
|
init_paths();
|
|
41664
|
-
import { existsSync as
|
|
41994
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "node:fs";
|
|
41665
41995
|
import { createHash as createHash12 } from "node:crypto";
|
|
41666
|
-
import { join as
|
|
41996
|
+
import { join as join19 } from "node:path";
|
|
41667
41997
|
function workspaceId(root) {
|
|
41668
41998
|
return "wp_" + createHash12("sha256").update(root).digest("hex").slice(0, 12);
|
|
41669
41999
|
}
|
|
41670
42000
|
function loadProfile(root) {
|
|
41671
42001
|
const p = workspacePaths(root);
|
|
41672
|
-
if (!
|
|
41673
|
-
return JSON.parse(
|
|
42002
|
+
if (!existsSync14(p.workspaceJson)) return null;
|
|
42003
|
+
return JSON.parse(readFileSync13(p.workspaceJson, "utf8"));
|
|
41674
42004
|
}
|
|
41675
42005
|
function saveProfile(root, profile) {
|
|
41676
42006
|
const p = workspacePaths(root);
|
|
41677
42007
|
ensureDir(p.configDir);
|
|
41678
|
-
|
|
42008
|
+
writeFileSync11(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
41679
42009
|
}
|
|
41680
42010
|
function autodetectProfile(root) {
|
|
41681
42011
|
const id = workspaceId(root);
|
|
41682
42012
|
const name2 = root.split(/[\\/]/).filter(Boolean).pop() ?? "workspace";
|
|
41683
42013
|
const p = emptyProfile(id, name2);
|
|
41684
|
-
const pkgPath =
|
|
41685
|
-
if (
|
|
42014
|
+
const pkgPath = join19(root, "package.json");
|
|
42015
|
+
if (existsSync14(pkgPath)) {
|
|
41686
42016
|
try {
|
|
41687
|
-
const pkg = JSON.parse(
|
|
42017
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
|
|
41688
42018
|
p.languages.push("typescript", "javascript");
|
|
41689
42019
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
41690
42020
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -41705,10 +42035,10 @@ function autodetectProfile(root) {
|
|
|
41705
42035
|
} catch {
|
|
41706
42036
|
}
|
|
41707
42037
|
}
|
|
41708
|
-
const pyproject =
|
|
41709
|
-
if (
|
|
42038
|
+
const pyproject = join19(root, "pyproject.toml");
|
|
42039
|
+
if (existsSync14(pyproject)) {
|
|
41710
42040
|
try {
|
|
41711
|
-
const txt =
|
|
42041
|
+
const txt = readFileSync13(pyproject, "utf8");
|
|
41712
42042
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
41713
42043
|
p.languages.push("python");
|
|
41714
42044
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -41719,16 +42049,16 @@ function autodetectProfile(root) {
|
|
|
41719
42049
|
} catch {
|
|
41720
42050
|
}
|
|
41721
42051
|
}
|
|
41722
|
-
const reqs =
|
|
41723
|
-
if (
|
|
42052
|
+
const reqs = join19(root, "requirements.txt");
|
|
42053
|
+
if (existsSync14(reqs)) {
|
|
41724
42054
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
41725
42055
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
41726
42056
|
}
|
|
41727
|
-
if (
|
|
42057
|
+
if (existsSync14(join19(root, "go.mod"))) {
|
|
41728
42058
|
p.languages.push("go");
|
|
41729
42059
|
p.stack.push("go");
|
|
41730
42060
|
}
|
|
41731
|
-
if (
|
|
42061
|
+
if (existsSync14(join19(root, "Cargo.toml"))) {
|
|
41732
42062
|
p.languages.push("rust");
|
|
41733
42063
|
p.stack.push("rust");
|
|
41734
42064
|
}
|
|
@@ -41886,7 +42216,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
41886
42216
|
}
|
|
41887
42217
|
|
|
41888
42218
|
// src/engine.ts
|
|
41889
|
-
var DAEMON_VERSION = true ? "2.0.0-dev.
|
|
42219
|
+
var DAEMON_VERSION = true ? "2.0.0-dev.36" : "2.0.0-alpha.0";
|
|
41890
42220
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
41891
42221
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
41892
42222
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -41896,7 +42226,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
41896
42226
|
function appendIdentityAudit(path2, record2, line) {
|
|
41897
42227
|
if (!record2.accepted && record2.score <= 0) return;
|
|
41898
42228
|
try {
|
|
41899
|
-
if (
|
|
42229
|
+
if (existsSync15(path2) && statSync4(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
41900
42230
|
renameSync2(path2, `${path2}.1`);
|
|
41901
42231
|
}
|
|
41902
42232
|
appendFileSync2(path2, line);
|
|
@@ -41906,14 +42236,14 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
41906
42236
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
41907
42237
|
function loadTurnCursors(path2) {
|
|
41908
42238
|
try {
|
|
41909
|
-
return new Map(Object.entries(JSON.parse(
|
|
42239
|
+
return new Map(Object.entries(JSON.parse(readFileSync14(path2, "utf8"))));
|
|
41910
42240
|
} catch {
|
|
41911
42241
|
return /* @__PURE__ */ new Map();
|
|
41912
42242
|
}
|
|
41913
42243
|
}
|
|
41914
42244
|
function saveTurnCursors(path2, cursors) {
|
|
41915
42245
|
try {
|
|
41916
|
-
|
|
42246
|
+
writeFileSync12(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
|
|
41917
42247
|
} catch {
|
|
41918
42248
|
}
|
|
41919
42249
|
}
|
|
@@ -41935,7 +42265,7 @@ function gitSourceWatchTargets(root) {
|
|
|
41935
42265
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
41936
42266
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
41937
42267
|
);
|
|
41938
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
42268
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join20(root, d) + sep4));
|
|
41939
42269
|
} catch {
|
|
41940
42270
|
}
|
|
41941
42271
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -41947,19 +42277,19 @@ function gitSourceWatchTargets(root) {
|
|
|
41947
42277
|
if (!f.startsWith(prefix)) continue;
|
|
41948
42278
|
const rest2 = f.slice(prefix.length);
|
|
41949
42279
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
41950
|
-
else targets.add(
|
|
42280
|
+
else targets.add(join20(root, f));
|
|
41951
42281
|
}
|
|
41952
42282
|
for (const c of children) {
|
|
41953
|
-
if (IGNORED_PATH.test(
|
|
42283
|
+
if (IGNORED_PATH.test(join20(root, c) + sep4)) continue;
|
|
41954
42284
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
41955
|
-
else targets.add(
|
|
42285
|
+
else targets.add(join20(root, c));
|
|
41956
42286
|
}
|
|
41957
42287
|
};
|
|
41958
42288
|
addUnder("");
|
|
41959
42289
|
if (targets.size > 0) return [...targets];
|
|
41960
42290
|
} catch {
|
|
41961
42291
|
}
|
|
41962
|
-
return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(
|
|
42292
|
+
return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join20(root, String(e.name)) + sep4)).map((e) => join20(root, String(e.name)));
|
|
41963
42293
|
}
|
|
41964
42294
|
function createWorkspaceEngine(opts) {
|
|
41965
42295
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -42111,7 +42441,7 @@ function createWorkspaceEngine(opts) {
|
|
|
42111
42441
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
42112
42442
|
let episodeId2;
|
|
42113
42443
|
if (srcPaths.length > 0) {
|
|
42114
|
-
const abs = srcPaths.map((p) =>
|
|
42444
|
+
const abs = srcPaths.map((p) => join20(opts.workspaceRoot, p));
|
|
42115
42445
|
try {
|
|
42116
42446
|
const r = await runReindexPass(
|
|
42117
42447
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -42142,8 +42472,8 @@ function createWorkspaceEngine(opts) {
|
|
|
42142
42472
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
42143
42473
|
);
|
|
42144
42474
|
};
|
|
42145
|
-
const gitDir =
|
|
42146
|
-
if (
|
|
42475
|
+
const gitDir = join20(opts.workspaceRoot, ".git");
|
|
42476
|
+
if (existsSync15(gitDir)) {
|
|
42147
42477
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
42148
42478
|
void handleGitEvent(ev);
|
|
42149
42479
|
});
|
|
@@ -42209,10 +42539,10 @@ function createWorkspaceEngine(opts) {
|
|
|
42209
42539
|
...pendingUpdate ? { pendingUpdate } : {}
|
|
42210
42540
|
});
|
|
42211
42541
|
doneRender?.();
|
|
42212
|
-
const target =
|
|
42542
|
+
const target = join20(opts.workspaceRoot, "AGENTS.md");
|
|
42213
42543
|
writeManagedBlock(target, { body: body2 });
|
|
42214
42544
|
if (elicit) {
|
|
42215
|
-
writePrimingHandles(
|
|
42545
|
+
writePrimingHandles(join20(paths.configDir, "priming-handles.json"), [
|
|
42216
42546
|
...snapshot.recentProblems.map((r) => r.node),
|
|
42217
42547
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
42218
42548
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -42382,7 +42712,7 @@ function createWorkspaceEngine(opts) {
|
|
|
42382
42712
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
42383
42713
|
});
|
|
42384
42714
|
};
|
|
42385
|
-
const turnCursorPath =
|
|
42715
|
+
const turnCursorPath = join20(paths.configDir, "turn-cursors.json");
|
|
42386
42716
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
42387
42717
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
42388
42718
|
const sessionThreads = /* @__PURE__ */ new Map();
|
|
@@ -42405,7 +42735,7 @@ function createWorkspaceEngine(opts) {
|
|
|
42405
42735
|
const t = Date.now();
|
|
42406
42736
|
let processedTurns = 0;
|
|
42407
42737
|
const elicit = isEdgeElicitationEnabled();
|
|
42408
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
42738
|
+
const handleMap = elicit ? readPrimingHandles(join20(paths.configDir, "priming-handles.json")) : {};
|
|
42409
42739
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
42410
42740
|
const toRel = (abs) => {
|
|
42411
42741
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -42922,7 +43252,21 @@ function createWorkspaceEngine(opts) {
|
|
|
42922
43252
|
return report;
|
|
42923
43253
|
},
|
|
42924
43254
|
async nightly() {
|
|
42925
|
-
|
|
43255
|
+
const report = (await runNightly()).report;
|
|
43256
|
+
const summarizer = opts.intentSummarizer ?? envIntentSummarizer();
|
|
43257
|
+
if (summarizer) {
|
|
43258
|
+
try {
|
|
43259
|
+
const s = await runSymbolSummarySweep(store, opts.workspaceRoot, paths.configDir, summarizer);
|
|
43260
|
+
if (s.generated > 0 || s.rejected > 0) {
|
|
43261
|
+
console.log(
|
|
43262
|
+
`[errata] symbol summaries: +${s.generated}${s.rejected > 0 ? ` (${s.rejected} rejected by no-verbatim check)` : ""}${s.remaining > 0 ? `, ${s.remaining} pending` : ""}`
|
|
43263
|
+
);
|
|
43264
|
+
}
|
|
43265
|
+
} catch (err2) {
|
|
43266
|
+
console.warn("[errata] symbol summary sweep failed:", err2 instanceof Error ? err2.message : err2);
|
|
43267
|
+
}
|
|
43268
|
+
}
|
|
43269
|
+
return report;
|
|
42926
43270
|
},
|
|
42927
43271
|
async embedSettled() {
|
|
42928
43272
|
try {
|
|
@@ -43010,7 +43354,7 @@ function createWorkspaceEngine(opts) {
|
|
|
43010
43354
|
console.log(
|
|
43011
43355
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
43012
43356
|
);
|
|
43013
|
-
const pending =
|
|
43357
|
+
const pending = existsSync15(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
43014
43358
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
43015
43359
|
}
|
|
43016
43360
|
try {
|
|
@@ -43097,7 +43441,7 @@ async function startDaemon(opts) {
|
|
|
43097
43441
|
reviewUrl: () => webUiUrl + "/review"
|
|
43098
43442
|
});
|
|
43099
43443
|
const writeLockFile = (url2) => {
|
|
43100
|
-
|
|
43444
|
+
writeFileSync13(
|
|
43101
43445
|
engine.paths.daemonLock,
|
|
43102
43446
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
43103
43447
|
"utf8"
|
|
@@ -43140,7 +43484,7 @@ async function startDaemon(opts) {
|
|
|
43140
43484
|
);
|
|
43141
43485
|
await engine.stop();
|
|
43142
43486
|
try {
|
|
43143
|
-
if (
|
|
43487
|
+
if (existsSync16(engine.paths.daemonLock)) {
|
|
43144
43488
|
}
|
|
43145
43489
|
} catch {
|
|
43146
43490
|
}
|
|
@@ -43157,16 +43501,16 @@ async function listenServer(fetchFn, port) {
|
|
|
43157
43501
|
|
|
43158
43502
|
// src/registry.ts
|
|
43159
43503
|
init_paths();
|
|
43160
|
-
import { existsSync as
|
|
43161
|
-
import { join as
|
|
43504
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "node:fs";
|
|
43505
|
+
import { join as join21 } from "node:path";
|
|
43162
43506
|
function registryPath() {
|
|
43163
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
43507
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join21(globalDir(), "workspaces.json");
|
|
43164
43508
|
}
|
|
43165
43509
|
function read() {
|
|
43166
43510
|
const p = registryPath();
|
|
43167
|
-
if (!
|
|
43511
|
+
if (!existsSync17(p)) return { version: 1, workspaces: {} };
|
|
43168
43512
|
try {
|
|
43169
|
-
const parsed = JSON.parse(
|
|
43513
|
+
const parsed = JSON.parse(readFileSync15(p, "utf8"));
|
|
43170
43514
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
43171
43515
|
} catch {
|
|
43172
43516
|
return { version: 1, workspaces: {} };
|
|
@@ -43174,7 +43518,7 @@ function read() {
|
|
|
43174
43518
|
}
|
|
43175
43519
|
function write(reg) {
|
|
43176
43520
|
ensureDir(globalDir());
|
|
43177
|
-
|
|
43521
|
+
writeFileSync14(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
43178
43522
|
}
|
|
43179
43523
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
43180
43524
|
const reg = read();
|
|
@@ -43191,7 +43535,7 @@ function pruneMissingWorkspaces() {
|
|
|
43191
43535
|
const reg = read();
|
|
43192
43536
|
const removed = [];
|
|
43193
43537
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
43194
|
-
if (!
|
|
43538
|
+
if (!existsSync17(entry.path)) {
|
|
43195
43539
|
removed.push(entry);
|
|
43196
43540
|
delete reg.workspaces[id];
|
|
43197
43541
|
}
|
|
@@ -43200,13 +43544,13 @@ function pruneMissingWorkspaces() {
|
|
|
43200
43544
|
return removed;
|
|
43201
43545
|
}
|
|
43202
43546
|
function workspaceStatus(entry) {
|
|
43203
|
-
const missing = !
|
|
43547
|
+
const missing = !existsSync17(entry.path);
|
|
43204
43548
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
43205
43549
|
let running = false;
|
|
43206
43550
|
let webUiUrl = null;
|
|
43207
|
-
if (
|
|
43551
|
+
if (existsSync17(lockPath)) {
|
|
43208
43552
|
try {
|
|
43209
|
-
const lock = JSON.parse(
|
|
43553
|
+
const lock = JSON.parse(readFileSync15(lockPath, "utf8"));
|
|
43210
43554
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
43211
43555
|
running = true;
|
|
43212
43556
|
webUiUrl = lock.webUiUrl;
|
|
@@ -43234,7 +43578,7 @@ function pidAlive(pid) {
|
|
|
43234
43578
|
// src/multi.ts
|
|
43235
43579
|
init_dist();
|
|
43236
43580
|
init_src4();
|
|
43237
|
-
import { readFileSync as
|
|
43581
|
+
import { readFileSync as readFileSync18, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
|
|
43238
43582
|
|
|
43239
43583
|
// src/principle-sync.ts
|
|
43240
43584
|
init_src4();
|
|
@@ -43261,8 +43605,8 @@ async function syncPrinciples(store, cloud, opts) {
|
|
|
43261
43605
|
init_reconcile();
|
|
43262
43606
|
|
|
43263
43607
|
// src/lockfile-auto.ts
|
|
43264
|
-
import { existsSync as
|
|
43265
|
-
import { join as
|
|
43608
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
|
|
43609
|
+
import { join as join22 } from "node:path";
|
|
43266
43610
|
|
|
43267
43611
|
// src/package-index.ts
|
|
43268
43612
|
init_src();
|
|
@@ -43526,11 +43870,11 @@ function runLockfilePass(opts) {
|
|
|
43526
43870
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
43527
43871
|
];
|
|
43528
43872
|
for (const c of candidates) {
|
|
43529
|
-
const p =
|
|
43530
|
-
if (!
|
|
43873
|
+
const p = join22(opts.root, c.file);
|
|
43874
|
+
if (!existsSync18(p)) continue;
|
|
43531
43875
|
let sbom;
|
|
43532
43876
|
try {
|
|
43533
|
-
sbom = c.parse(
|
|
43877
|
+
sbom = c.parse(readFileSync16(p, "utf8"));
|
|
43534
43878
|
} catch {
|
|
43535
43879
|
continue;
|
|
43536
43880
|
}
|
|
@@ -43685,6 +44029,27 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
43685
44029
|
}
|
|
43686
44030
|
}
|
|
43687
44031
|
if (nodes.length === 0 && anchorEdges.length === 0) return null;
|
|
44032
|
+
let symbolSummaries;
|
|
44033
|
+
if (opts.lexicon && opts.lexicon.size > 0 && nodes.length > 0) {
|
|
44034
|
+
const lexicon = opts.lexicon;
|
|
44035
|
+
const isKnown = (tok) => lexicon.has(tok);
|
|
44036
|
+
const sidecar = {};
|
|
44037
|
+
let count = 0;
|
|
44038
|
+
outer: for (const n of nodes) {
|
|
44039
|
+
if (!INSTANCE_LABELS.includes(n.label)) continue;
|
|
44040
|
+
for (const tok of extractIdentifierTokens(n.description)) {
|
|
44041
|
+
if (sidecar[tok]) continue;
|
|
44042
|
+
const entry = lexicon.get(tok);
|
|
44043
|
+
if (!entry?.summary) continue;
|
|
44044
|
+
const scrubbed = generalize(entry.summary, { level }).text.trim();
|
|
44045
|
+
if (!scrubbed || summaryRejectionReason(scrubbed, isKnown) !== null) continue;
|
|
44046
|
+
if (count >= MAX_SIDECAR_SYMBOLS) break outer;
|
|
44047
|
+
sidecar[tok] = { kind: entry.kind, summary: scrubbed };
|
|
44048
|
+
count++;
|
|
44049
|
+
}
|
|
44050
|
+
}
|
|
44051
|
+
if (count > 0) symbolSummaries = sidecar;
|
|
44052
|
+
}
|
|
43688
44053
|
const edges = [];
|
|
43689
44054
|
for (const id of seen) {
|
|
43690
44055
|
for (const e of store.outEdges(id, [...INSTANCE_EDGES])) {
|
|
@@ -43699,12 +44064,17 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
43699
44064
|
// co-locates the few Language/Package stubs with the first instance chunk,
|
|
43700
44065
|
// maximizing in-payload endpoint resolution.
|
|
43701
44066
|
nodes: [...contextNodes, ...nodes],
|
|
43702
|
-
edges
|
|
44067
|
+
edges,
|
|
44068
|
+
// Spread-if-present: an absent sidecar keeps `base` — and therefore the
|
|
44069
|
+
// payloadDigest — byte-identical to the pre-sidecar batch (backward compat).
|
|
44070
|
+
...symbolSummaries ? { symbolSummaries } : {}
|
|
43703
44071
|
};
|
|
43704
44072
|
return { ...base, payloadDigest: digest(base), anchorDigests };
|
|
43705
44073
|
}
|
|
43706
44074
|
|
|
43707
44075
|
// src/multi.ts
|
|
44076
|
+
init_generalize_graph();
|
|
44077
|
+
init_symbol_summaries();
|
|
43708
44078
|
init_webui();
|
|
43709
44079
|
|
|
43710
44080
|
// src/consolidate-worker-client.ts
|
|
@@ -43780,7 +44150,7 @@ var ConsolidateWorker = class {
|
|
|
43780
44150
|
init_paths();
|
|
43781
44151
|
|
|
43782
44152
|
// src/lock.ts
|
|
43783
|
-
import { existsSync as
|
|
44153
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
|
|
43784
44154
|
function isProcessAlive(pid) {
|
|
43785
44155
|
if (!pid || pid <= 0) return false;
|
|
43786
44156
|
try {
|
|
@@ -43791,9 +44161,9 @@ function isProcessAlive(pid) {
|
|
|
43791
44161
|
}
|
|
43792
44162
|
}
|
|
43793
44163
|
function readDaemonLock(lockPath) {
|
|
43794
|
-
if (!
|
|
44164
|
+
if (!existsSync19(lockPath)) return null;
|
|
43795
44165
|
try {
|
|
43796
|
-
const lock = JSON.parse(
|
|
44166
|
+
const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
|
|
43797
44167
|
return typeof lock.pid === "number" ? lock : null;
|
|
43798
44168
|
} catch {
|
|
43799
44169
|
return null;
|
|
@@ -44041,7 +44411,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44041
44411
|
records.push(rec);
|
|
44042
44412
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
44043
44413
|
try {
|
|
44044
|
-
|
|
44414
|
+
writeFileSync15(
|
|
44045
44415
|
rec.engine.paths.daemonLock,
|
|
44046
44416
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
44047
44417
|
"utf8"
|
|
@@ -44224,7 +44594,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44224
44594
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
44225
44595
|
try {
|
|
44226
44596
|
ensureDir(globalDir());
|
|
44227
|
-
|
|
44597
|
+
writeFileSync15(
|
|
44228
44598
|
lockPath,
|
|
44229
44599
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
44230
44600
|
"utf8"
|
|
@@ -44233,7 +44603,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44233
44603
|
}
|
|
44234
44604
|
for (const r of records) {
|
|
44235
44605
|
try {
|
|
44236
|
-
|
|
44606
|
+
writeFileSync15(
|
|
44237
44607
|
r.engine.paths.daemonLock,
|
|
44238
44608
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
44239
44609
|
"utf8"
|
|
@@ -44445,8 +44815,15 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44445
44815
|
const res = await client.ingest(context);
|
|
44446
44816
|
uploaded += res.accepted;
|
|
44447
44817
|
}
|
|
44818
|
+
let lexicon;
|
|
44819
|
+
try {
|
|
44820
|
+
const summaries = summariesByBodyHash(loadSymbolSummaryCache(r.engine.paths.configDir));
|
|
44821
|
+
if (summaries.size > 0) lexicon = buildSymbolLexicon(store, summaries);
|
|
44822
|
+
} catch {
|
|
44823
|
+
}
|
|
44448
44824
|
const instances = buildInstanceIngest(store, r.engine.profile, DAEMON_VERSION, ignore, {
|
|
44449
|
-
includePackages: cfg2.consent.contributePackages
|
|
44825
|
+
includePackages: cfg2.consent.contributePackages,
|
|
44826
|
+
...lexicon ? { lexicon } : {}
|
|
44450
44827
|
});
|
|
44451
44828
|
if (instances) {
|
|
44452
44829
|
const res = await client.ingest(instances);
|
|
@@ -44529,7 +44906,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
44529
44906
|
},
|
|
44530
44907
|
async stop() {
|
|
44531
44908
|
try {
|
|
44532
|
-
const cur =
|
|
44909
|
+
const cur = readFileSync18(lockPath, "utf8");
|
|
44533
44910
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
44534
44911
|
} catch {
|
|
44535
44912
|
}
|
|
@@ -44983,21 +45360,21 @@ async function cmdInit() {
|
|
|
44983
45360
|
if (!skipHooks) {
|
|
44984
45361
|
console.log("");
|
|
44985
45362
|
console.log("installing harness hooks...");
|
|
44986
|
-
const { existsSync:
|
|
44987
|
-
const { join:
|
|
45363
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
45364
|
+
const { join: join24 } = await import("node:path");
|
|
44988
45365
|
try {
|
|
44989
45366
|
await installClaudeHooks(port);
|
|
44990
45367
|
} catch (err2) {
|
|
44991
45368
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
44992
45369
|
}
|
|
44993
|
-
if (
|
|
45370
|
+
if (existsSync21(join24(ROOT, ".cursor"))) {
|
|
44994
45371
|
try {
|
|
44995
45372
|
await installCursorMcpConfig();
|
|
44996
45373
|
} catch (err2) {
|
|
44997
45374
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
44998
45375
|
}
|
|
44999
45376
|
}
|
|
45000
|
-
if (
|
|
45377
|
+
if (existsSync21(join24(ROOT, ".codex"))) {
|
|
45001
45378
|
try {
|
|
45002
45379
|
await installCodexHooks(port);
|
|
45003
45380
|
} catch (err2) {
|
|
@@ -45114,8 +45491,8 @@ async function cmdStatus() {
|
|
|
45114
45491
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
45115
45492
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
45116
45493
|
}
|
|
45117
|
-
console.log(` graph db: ${
|
|
45118
|
-
console.log(` event log: ${
|
|
45494
|
+
console.log(` graph db: ${existsSync20(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
45495
|
+
console.log(` event log: ${existsSync20(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
45119
45496
|
const lockPath = globalDaemonLock();
|
|
45120
45497
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
45121
45498
|
console.log(
|
|
@@ -45411,11 +45788,11 @@ async function cmdLogout() {
|
|
|
45411
45788
|
}
|
|
45412
45789
|
async function cmdReview() {
|
|
45413
45790
|
const paths = workspacePaths(ROOT);
|
|
45414
|
-
if (!
|
|
45791
|
+
if (!existsSync20(paths.reviewQueue)) {
|
|
45415
45792
|
console.log("(review queue empty)");
|
|
45416
45793
|
return;
|
|
45417
45794
|
}
|
|
45418
|
-
const queue = JSON.parse(
|
|
45795
|
+
const queue = JSON.parse(readFileSync19(paths.reviewQueue, "utf8"));
|
|
45419
45796
|
if (queue.length === 0) {
|
|
45420
45797
|
console.log("(review queue empty)");
|
|
45421
45798
|
return;
|
|
@@ -46045,7 +46422,7 @@ async function gatherRepo(store, ws) {
|
|
|
46045
46422
|
};
|
|
46046
46423
|
}
|
|
46047
46424
|
async function gatherReportData(generatedAt) {
|
|
46048
|
-
const { existsSync:
|
|
46425
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
46049
46426
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
46050
46427
|
const cfg = loadConfig();
|
|
46051
46428
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -46053,7 +46430,7 @@ async function gatherReportData(generatedAt) {
|
|
|
46053
46430
|
for (const ws of listWorkspaces()) {
|
|
46054
46431
|
if (ws.missing) continue;
|
|
46055
46432
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
46056
|
-
if (!
|
|
46433
|
+
if (!existsSync21(dbPath)) continue;
|
|
46057
46434
|
let store = null;
|
|
46058
46435
|
try {
|
|
46059
46436
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -46084,7 +46461,7 @@ async function gatherReportData(generatedAt) {
|
|
|
46084
46461
|
};
|
|
46085
46462
|
}
|
|
46086
46463
|
async function cmdReport(args2) {
|
|
46087
|
-
const { mkdirSync: mkdirSync6, writeFileSync:
|
|
46464
|
+
const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
46088
46465
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
46089
46466
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
46090
46467
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -46097,8 +46474,8 @@ async function cmdReport(args2) {
|
|
|
46097
46474
|
const outDir = workspacePaths(ROOT).configDir;
|
|
46098
46475
|
mkdirSync6(outDir, { recursive: true });
|
|
46099
46476
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
46100
|
-
for (const f of files)
|
|
46101
|
-
const indexPath =
|
|
46477
|
+
for (const f of files) writeFileSync16(join23(outDir, f.name), f.html, "utf8");
|
|
46478
|
+
const indexPath = join23(outDir, "report.html");
|
|
46102
46479
|
console.log(`report \u2192 ${indexPath}`);
|
|
46103
46480
|
console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
|
|
46104
46481
|
console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
|
|
@@ -46218,15 +46595,15 @@ function hookRelayCommand(port, path2) {
|
|
|
46218
46595
|
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
46219
46596
|
}
|
|
46220
46597
|
async function installClaudeHooks(port) {
|
|
46221
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
46222
|
-
const { join:
|
|
46223
|
-
const dir =
|
|
46224
|
-
if (!
|
|
46225
|
-
const file2 =
|
|
46598
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
46599
|
+
const { join: join24 } = await import("node:path");
|
|
46600
|
+
const dir = join24(ROOT, ".claude");
|
|
46601
|
+
if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
|
|
46602
|
+
const file2 = join24(dir, "settings.json");
|
|
46226
46603
|
let settings = {};
|
|
46227
|
-
if (
|
|
46604
|
+
if (existsSync21(file2)) {
|
|
46228
46605
|
try {
|
|
46229
|
-
settings = JSON.parse(
|
|
46606
|
+
settings = JSON.parse(readFileSync20(file2, "utf8"));
|
|
46230
46607
|
} catch {
|
|
46231
46608
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
46232
46609
|
process.exit(2);
|
|
@@ -46271,21 +46648,21 @@ async function installClaudeHooks(port) {
|
|
|
46271
46648
|
dropErrata(list);
|
|
46272
46649
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
46273
46650
|
}
|
|
46274
|
-
|
|
46651
|
+
writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
46275
46652
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
46276
46653
|
await installClaudeMcpConfig();
|
|
46277
46654
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
46278
46655
|
}
|
|
46279
46656
|
async function installClaudeMcpConfig() {
|
|
46280
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
46281
|
-
const { join:
|
|
46282
|
-
const file2 =
|
|
46657
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
46658
|
+
const { join: join24, dirname: dirname8 } = await import("node:path");
|
|
46659
|
+
const file2 = join24(ROOT, ".mcp.json");
|
|
46283
46660
|
const dir = dirname8(file2);
|
|
46284
|
-
if (!
|
|
46661
|
+
if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
|
|
46285
46662
|
let cfg = {};
|
|
46286
|
-
if (
|
|
46663
|
+
if (existsSync21(file2)) {
|
|
46287
46664
|
try {
|
|
46288
|
-
cfg = JSON.parse(
|
|
46665
|
+
cfg = JSON.parse(readFileSync20(file2, "utf8"));
|
|
46289
46666
|
} catch {
|
|
46290
46667
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
46291
46668
|
process.exit(2);
|
|
@@ -46293,21 +46670,21 @@ async function installClaudeMcpConfig() {
|
|
|
46293
46670
|
}
|
|
46294
46671
|
cfg.mcpServers ??= {};
|
|
46295
46672
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
46296
|
-
|
|
46673
|
+
writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
46297
46674
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
46298
46675
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
46299
46676
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
46300
46677
|
}
|
|
46301
46678
|
async function installCursorMcpConfig() {
|
|
46302
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
46303
|
-
const { join:
|
|
46304
|
-
const dir =
|
|
46305
|
-
if (!
|
|
46306
|
-
const file2 =
|
|
46679
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
46680
|
+
const { join: join24 } = await import("node:path");
|
|
46681
|
+
const dir = join24(ROOT, ".cursor");
|
|
46682
|
+
if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
|
|
46683
|
+
const file2 = join24(dir, "mcp.json");
|
|
46307
46684
|
let cfg = {};
|
|
46308
|
-
if (
|
|
46685
|
+
if (existsSync21(file2)) {
|
|
46309
46686
|
try {
|
|
46310
|
-
cfg = JSON.parse(
|
|
46687
|
+
cfg = JSON.parse(readFileSync20(file2, "utf8"));
|
|
46311
46688
|
} catch {
|
|
46312
46689
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
46313
46690
|
process.exit(2);
|
|
@@ -46315,7 +46692,7 @@ async function installCursorMcpConfig() {
|
|
|
46315
46692
|
}
|
|
46316
46693
|
cfg.mcpServers ??= {};
|
|
46317
46694
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
46318
|
-
|
|
46695
|
+
writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
46319
46696
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
46320
46697
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
46321
46698
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -46323,16 +46700,16 @@ async function installCursorMcpConfig() {
|
|
|
46323
46700
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
46324
46701
|
}
|
|
46325
46702
|
async function installCodexHooks(port) {
|
|
46326
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
46327
|
-
const { join:
|
|
46328
|
-
const dir =
|
|
46329
|
-
if (!
|
|
46330
|
-
const file2 =
|
|
46703
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
46704
|
+
const { join: join24 } = await import("node:path");
|
|
46705
|
+
const dir = join24(ROOT, ".codex");
|
|
46706
|
+
if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
|
|
46707
|
+
const file2 = join24(dir, "config.toml");
|
|
46331
46708
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
46332
46709
|
const END = `# <<< errata hooks`;
|
|
46333
46710
|
let existing = "";
|
|
46334
|
-
if (
|
|
46335
|
-
existing =
|
|
46711
|
+
if (existsSync21(file2)) {
|
|
46712
|
+
existing = readFileSync20(file2, "utf8");
|
|
46336
46713
|
const beginIdx = existing.indexOf(BEGIN);
|
|
46337
46714
|
const endIdx = existing.indexOf(END);
|
|
46338
46715
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -46361,7 +46738,7 @@ ${END}
|
|
|
46361
46738
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
46362
46739
|
|
|
46363
46740
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
46364
|
-
|
|
46741
|
+
writeFileSync16(file2, final, "utf8");
|
|
46365
46742
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
46366
46743
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
46367
46744
|
console.log("");
|
|
@@ -46624,7 +47001,7 @@ async function cmdDash(args2) {
|
|
|
46624
47001
|
await yieldToLoop2();
|
|
46625
47002
|
try {
|
|
46626
47003
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
46627
|
-
const res = bleedRules(
|
|
47004
|
+
const res = bleedRules(join23(r.root, ".claude", "rules"), items);
|
|
46628
47005
|
if (res.written || res.pruned) {
|
|
46629
47006
|
console.log(
|
|
46630
47007
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|