@merittdev/horus 0.21.9 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/horus_source.whl +0 -0
- package/dist/index.cjs +835 -645
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3057,7 +3057,7 @@ var init_version = __esm({
|
|
|
3057
3057
|
"../../packages/core/src/version.ts"() {
|
|
3058
3058
|
"use strict";
|
|
3059
3059
|
init_cjs_shims();
|
|
3060
|
-
HORUS_VERSION = true ? "0.
|
|
3060
|
+
HORUS_VERSION = true ? "0.22.0" : "dev";
|
|
3061
3061
|
PINNED_SOURCE_VERSION = HORUS_VERSION;
|
|
3062
3062
|
SOURCE_PIN_ENFORCED = HORUS_VERSION !== "dev";
|
|
3063
3063
|
EXPECTED_INDEX_CAPABILITY = 2;
|
|
@@ -71988,6 +71988,30 @@ var SourceHttpClient = class {
|
|
|
71988
71988
|
diff(base2, compare) {
|
|
71989
71989
|
return this.request("POST", "/api/diff", { base: base2, compare });
|
|
71990
71990
|
}
|
|
71991
|
+
/**
|
|
71992
|
+
* Shortest relationship path between two symbols across all semantic edges
|
|
71993
|
+
* (calls, imports, extends, implements, uses_type), in both directions.
|
|
71994
|
+
* Broader than a call-only path — answers "how are A and B connected?".
|
|
71995
|
+
* `relations` optionally narrows the edge kinds (e.g. `['calls']`).
|
|
71996
|
+
*/
|
|
71997
|
+
trace(fromSymbol, toSymbol, opts) {
|
|
71998
|
+
const params = new URLSearchParams({ from: fromSymbol, to: toSymbol });
|
|
71999
|
+
if (opts?.maxDepth != null) params.set("max_depth", String(opts.maxDepth));
|
|
72000
|
+
if (opts?.relations?.length) params.set("relations", opts.relations.join(","));
|
|
72001
|
+
return this.request("GET", `/api/trace?${params.toString()}`);
|
|
72002
|
+
}
|
|
72003
|
+
/**
|
|
72004
|
+
* Graph-shape insights: the codebase's hubs (highest-degree symbols),
|
|
72005
|
+
* surprising connections (edges bridging detected communities), and a few
|
|
72006
|
+
* suggested follow-up questions.
|
|
72007
|
+
*/
|
|
72008
|
+
insights(opts) {
|
|
72009
|
+
const params = new URLSearchParams();
|
|
72010
|
+
if (opts?.hubLimit != null) params.set("hub_limit", String(opts.hubLimit));
|
|
72011
|
+
if (opts?.bridgeLimit != null) params.set("bridge_limit", String(opts.bridgeLimit));
|
|
72012
|
+
const qs = params.toString();
|
|
72013
|
+
return this.request("GET", `/api/insights${qs ? `?${qs}` : ""}`);
|
|
72014
|
+
}
|
|
71991
72015
|
async nodeCount() {
|
|
71992
72016
|
const o5 = await this.overview();
|
|
71993
72017
|
return Number(o5.totalNodes) || 0;
|
|
@@ -73483,6 +73507,7 @@ function logsToEvidence(records, query, collectedAt) {
|
|
|
73483
73507
|
// ../../packages/connectors/src/elasticsearch/analyze.ts
|
|
73484
73508
|
init_cjs_shims();
|
|
73485
73509
|
init_src();
|
|
73510
|
+
var UNCODED_SIGNATURE_KEY = "(no code)";
|
|
73486
73511
|
function shortTs(iso) {
|
|
73487
73512
|
if (!iso || iso.length < 16) return iso || "\u2014";
|
|
73488
73513
|
return `${iso.slice(5, 10)} ${iso.slice(11, 16)}`;
|
|
@@ -73522,7 +73547,11 @@ function buildErrorAnalysisBody(q2, field = "event_code", mapping = MERITT_FIELD
|
|
|
73522
73547
|
query: { bool: { filter: filters, must: mustClause } },
|
|
73523
73548
|
aggs: {
|
|
73524
73549
|
by_sig: {
|
|
73525
|
-
|
|
73550
|
+
// `missing` routes docs with no signature-field value into a single
|
|
73551
|
+
// "(no code)" bucket instead of dropping them — so error docs without an
|
|
73552
|
+
// event_code still surface as a signature (with a sample) and the
|
|
73553
|
+
// per-signature counts reconcile with totalErrors (the count/doc split bug).
|
|
73554
|
+
terms: { field: sigTerm, size: 25, missing: UNCODED_SIGNATURE_KEY },
|
|
73526
73555
|
aggs: {
|
|
73527
73556
|
first_seen: { min: { field: mapping.timestampField } },
|
|
73528
73557
|
last_seen: { max: { field: mapping.timestampField } },
|
|
@@ -122297,24 +122326,154 @@ async function runBlastRadius(query, opts) {
|
|
|
122297
122326
|
}
|
|
122298
122327
|
}
|
|
122299
122328
|
|
|
122300
|
-
// ../../packages/cli/src/commands/
|
|
122329
|
+
// ../../packages/cli/src/commands/trace.ts
|
|
122301
122330
|
init_cjs_shims();
|
|
122302
122331
|
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
122303
122332
|
init_src();
|
|
122333
|
+
function confidenceTag(confidence) {
|
|
122334
|
+
if (confidence >= 0.9) return "";
|
|
122335
|
+
if (confidence >= 0.5) return " (~)";
|
|
122336
|
+
return " (?)";
|
|
122337
|
+
}
|
|
122338
|
+
function renderTrace(result) {
|
|
122339
|
+
if (!result.found) {
|
|
122340
|
+
const lines = [result.error ?? "No path found."];
|
|
122341
|
+
for (const n4 of result.notes ?? []) lines.push(import_picocolors28.default.dim(` ${n4}`));
|
|
122342
|
+
return lines.join("\n");
|
|
122343
|
+
}
|
|
122344
|
+
const path = result.path ?? [];
|
|
122345
|
+
const segments = result.segments ?? [];
|
|
122346
|
+
const chain = [path[0]?.name ?? "?"];
|
|
122347
|
+
segments.forEach((seg, i3) => {
|
|
122348
|
+
const tag = confidenceTag(seg.confidence);
|
|
122349
|
+
const next = path[i3 + 1]?.name ?? "?";
|
|
122350
|
+
chain.push(
|
|
122351
|
+
seg.direction === "out" ? `--${seg.relType}${tag}--> ${next}` : `<--${seg.relType}${tag}-- ${next}`
|
|
122352
|
+
);
|
|
122353
|
+
});
|
|
122354
|
+
const hops = result.hops ?? segments.length;
|
|
122355
|
+
const out2 = [`Trace: ${chain.join(" ")} (${hops} hop${hops === 1 ? "" : "s"})`, ""];
|
|
122356
|
+
path.forEach((n4, i3) => {
|
|
122357
|
+
const label = n4.label.charAt(0).toUpperCase() + n4.label.slice(1);
|
|
122358
|
+
out2.push(` ${i3 + 1}. ${n4.name} (${label}) \u2014 ${n4.filePath}:${n4.startLine}`);
|
|
122359
|
+
});
|
|
122360
|
+
for (const n4 of result.notes ?? []) out2.push("", import_picocolors28.default.dim(n4));
|
|
122361
|
+
return out2.join("\n");
|
|
122362
|
+
}
|
|
122363
|
+
async function runTrace(from, to, opts) {
|
|
122364
|
+
try {
|
|
122365
|
+
await loadConfig(opts.config);
|
|
122366
|
+
const host = await ensureOwnSourceHost(process.cwd());
|
|
122367
|
+
if (!host.ok || !host.hostUrl) {
|
|
122368
|
+
const hint = ensureHostReasonHint(host.reason);
|
|
122369
|
+
if (opts.json) {
|
|
122370
|
+
console.log(JSON.stringify({ error: "Source-intelligence host unavailable", hint }, null, 2));
|
|
122371
|
+
} else {
|
|
122372
|
+
console.error(import_picocolors28.default.red("Source-intelligence host unavailable"));
|
|
122373
|
+
console.error(import_picocolors28.default.dim(` ${hint}`));
|
|
122374
|
+
}
|
|
122375
|
+
return 1;
|
|
122376
|
+
}
|
|
122377
|
+
const client = new SourceHttpClient({ baseUrl: host.hostUrl });
|
|
122378
|
+
const relations = opts.relations ? opts.relations.split(",").map((r) => r.trim()).filter(Boolean) : void 0;
|
|
122379
|
+
const result = await client.trace(from, to, {
|
|
122380
|
+
...opts.maxDepth != null ? { maxDepth: opts.maxDepth } : {},
|
|
122381
|
+
...relations ? { relations } : {}
|
|
122382
|
+
});
|
|
122383
|
+
if (opts.json) {
|
|
122384
|
+
console.log(JSON.stringify(result, null, 2));
|
|
122385
|
+
} else {
|
|
122386
|
+
console.log(renderTrace(result));
|
|
122387
|
+
}
|
|
122388
|
+
return result.found ? 0 : 1;
|
|
122389
|
+
} catch (err2) {
|
|
122390
|
+
return failCommand(err2, opts.json);
|
|
122391
|
+
}
|
|
122392
|
+
}
|
|
122393
|
+
|
|
122394
|
+
// ../../packages/cli/src/commands/insights.ts
|
|
122395
|
+
init_cjs_shims();
|
|
122396
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
122397
|
+
init_src();
|
|
122398
|
+
function renderInsights(r) {
|
|
122399
|
+
const out2 = [];
|
|
122400
|
+
out2.push(import_picocolors29.default.bold("Hubs") + import_picocolors29.default.dim(" \u2014 most-connected symbols"));
|
|
122401
|
+
if (r.hubs.length === 0) {
|
|
122402
|
+
out2.push(import_picocolors29.default.dim(" none (empty or unindexed graph)"));
|
|
122403
|
+
} else {
|
|
122404
|
+
for (const h3 of r.hubs) {
|
|
122405
|
+
const label = h3.label.charAt(0).toUpperCase() + h3.label.slice(1);
|
|
122406
|
+
out2.push(
|
|
122407
|
+
` ${String(h3.degree).padStart(3)} ${h3.name} ${import_picocolors29.default.dim(`(${label}) \u2014 ${h3.filePath}:${h3.startLine}`)}`
|
|
122408
|
+
);
|
|
122409
|
+
}
|
|
122410
|
+
}
|
|
122411
|
+
out2.push("");
|
|
122412
|
+
out2.push(import_picocolors29.default.bold("Surprising connections") + import_picocolors29.default.dim(" \u2014 edges bridging communities"));
|
|
122413
|
+
if (r.bridges.length === 0) {
|
|
122414
|
+
out2.push(import_picocolors29.default.dim(" none detected (run community detection first)"));
|
|
122415
|
+
} else {
|
|
122416
|
+
for (const b5 of r.bridges) {
|
|
122417
|
+
out2.push(
|
|
122418
|
+
` ${b5.source} --${b5.relType}--> ${b5.target} ${import_picocolors29.default.dim(`[${b5.sourceCommunity} \u2192 ${b5.targetCommunity}]`)}`
|
|
122419
|
+
);
|
|
122420
|
+
}
|
|
122421
|
+
}
|
|
122422
|
+
if (r.questions.length > 0) {
|
|
122423
|
+
out2.push("");
|
|
122424
|
+
out2.push(import_picocolors29.default.bold("Suggested questions"));
|
|
122425
|
+
for (const q2 of r.questions) out2.push(` ${import_picocolors29.default.dim("\u2022")} ${q2}`);
|
|
122426
|
+
}
|
|
122427
|
+
return out2.join("\n");
|
|
122428
|
+
}
|
|
122429
|
+
async function runInsights(opts) {
|
|
122430
|
+
try {
|
|
122431
|
+
await loadConfig(opts.config);
|
|
122432
|
+
const host = await ensureOwnSourceHost(process.cwd());
|
|
122433
|
+
if (!host.ok || !host.hostUrl) {
|
|
122434
|
+
const hint = ensureHostReasonHint(host.reason);
|
|
122435
|
+
if (opts.json) {
|
|
122436
|
+
console.log(JSON.stringify({ error: "Source-intelligence host unavailable", hint }, null, 2));
|
|
122437
|
+
} else {
|
|
122438
|
+
console.error(import_picocolors29.default.red("Source-intelligence host unavailable"));
|
|
122439
|
+
console.error(import_picocolors29.default.dim(` ${hint}`));
|
|
122440
|
+
}
|
|
122441
|
+
return 1;
|
|
122442
|
+
}
|
|
122443
|
+
const client = new SourceHttpClient({ baseUrl: host.hostUrl });
|
|
122444
|
+
const result = await client.insights({
|
|
122445
|
+
...opts.hubs != null ? { hubLimit: opts.hubs } : {},
|
|
122446
|
+
...opts.bridges != null ? { bridgeLimit: opts.bridges } : {}
|
|
122447
|
+
});
|
|
122448
|
+
if (opts.json) {
|
|
122449
|
+
console.log(JSON.stringify(result, null, 2));
|
|
122450
|
+
} else {
|
|
122451
|
+
console.log(renderInsights(result));
|
|
122452
|
+
}
|
|
122453
|
+
return 0;
|
|
122454
|
+
} catch (err2) {
|
|
122455
|
+
return failCommand(err2, opts.json);
|
|
122456
|
+
}
|
|
122457
|
+
}
|
|
122458
|
+
|
|
122459
|
+
// ../../packages/cli/src/commands/repos.ts
|
|
122460
|
+
init_cjs_shims();
|
|
122461
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
122462
|
+
init_src();
|
|
122304
122463
|
async function runRepos(opts) {
|
|
122305
122464
|
const config2 = await loadConfig(opts.config);
|
|
122306
122465
|
const providers = repoProviders(config2);
|
|
122307
122466
|
if (providers.length === 0) {
|
|
122308
|
-
console.log(
|
|
122467
|
+
console.log(import_picocolors30.default.dim("No repositories configured."));
|
|
122309
122468
|
return 0;
|
|
122310
122469
|
}
|
|
122311
122470
|
const health = await reposHealth(providers);
|
|
122312
122471
|
for (const h3 of health) {
|
|
122313
|
-
const dot = h3.reachable ?
|
|
122314
|
-
const name2 =
|
|
122315
|
-
const hostUrl =
|
|
122316
|
-
const path =
|
|
122317
|
-
const detail = h3.detail ?
|
|
122472
|
+
const dot = h3.reachable ? import_picocolors30.default.green("\u25CF") : import_picocolors30.default.red("\u25CF");
|
|
122473
|
+
const name2 = import_picocolors30.default.bold(h3.repo.padEnd(20));
|
|
122474
|
+
const hostUrl = import_picocolors30.default.cyan(h3.hostUrl.padEnd(30));
|
|
122475
|
+
const path = import_picocolors30.default.dim(h3.path);
|
|
122476
|
+
const detail = h3.detail ? import_picocolors30.default.dim(`(${h3.detail})`) : "";
|
|
122318
122477
|
console.log(` ${dot} ${name2} ${hostUrl} ${path} ${detail}`);
|
|
122319
122478
|
}
|
|
122320
122479
|
return 0;
|
|
@@ -122322,7 +122481,7 @@ async function runRepos(opts) {
|
|
|
122322
122481
|
|
|
122323
122482
|
// ../../packages/cli/src/commands/search.ts
|
|
122324
122483
|
init_cjs_shims();
|
|
122325
|
-
var
|
|
122484
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
122326
122485
|
init_src();
|
|
122327
122486
|
async function runSearch(query, opts) {
|
|
122328
122487
|
try {
|
|
@@ -122341,18 +122500,18 @@ async function search(query, opts) {
|
|
|
122341
122500
|
}
|
|
122342
122501
|
let totalMatches = 0;
|
|
122343
122502
|
for (const result of results) {
|
|
122344
|
-
const statusDot = result.reachable ?
|
|
122503
|
+
const statusDot = result.reachable ? import_picocolors31.default.green("\u25CF") : import_picocolors31.default.red("\u25CF");
|
|
122345
122504
|
console.log("");
|
|
122346
|
-
console.log(`${statusDot} ${
|
|
122505
|
+
console.log(`${statusDot} ${import_picocolors31.default.bold("## " + result.repo)} ${import_picocolors31.default.dim(result.hostUrl)}`);
|
|
122347
122506
|
if (!result.reachable) {
|
|
122348
|
-
console.log(
|
|
122507
|
+
console.log(import_picocolors31.default.dim(" (unreachable)"));
|
|
122349
122508
|
} else if (result.symbols.length === 0) {
|
|
122350
|
-
console.log(
|
|
122509
|
+
console.log(import_picocolors31.default.dim(" (no matches)"));
|
|
122351
122510
|
} else {
|
|
122352
122511
|
for (const sym of result.symbols) {
|
|
122353
|
-
const owner = sym.className ?
|
|
122354
|
-
const line2 = sym.startLine ?
|
|
122355
|
-
console.log(` - ${owner}${
|
|
122512
|
+
const owner = sym.className ? import_picocolors31.default.dim(`${sym.className}.`) : "";
|
|
122513
|
+
const line2 = sym.startLine ? import_picocolors31.default.dim(`:${sym.startLine}`) : "";
|
|
122514
|
+
console.log(` - ${owner}${import_picocolors31.default.bold(sym.name)} ${import_picocolors31.default.dim(sym.filePath)}${line2}`);
|
|
122356
122515
|
}
|
|
122357
122516
|
totalMatches += result.symbols.length;
|
|
122358
122517
|
}
|
|
@@ -122360,7 +122519,7 @@ async function search(query, opts) {
|
|
|
122360
122519
|
console.log("");
|
|
122361
122520
|
const reachableCount = results.filter((r) => r.reachable).length;
|
|
122362
122521
|
console.log(
|
|
122363
|
-
|
|
122522
|
+
import_picocolors31.default.dim(
|
|
122364
122523
|
`${totalMatches} match(es) across ${reachableCount}/${results.length} reachable repo(s) for query: "${query}"`
|
|
122365
122524
|
)
|
|
122366
122525
|
);
|
|
@@ -122369,7 +122528,7 @@ async function search(query, opts) {
|
|
|
122369
122528
|
|
|
122370
122529
|
// ../../packages/cli/src/commands/investigations.ts
|
|
122371
122530
|
init_cjs_shims();
|
|
122372
|
-
var
|
|
122531
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
122373
122532
|
init_src();
|
|
122374
122533
|
|
|
122375
122534
|
// ../../packages/cli/src/lib/format.ts
|
|
@@ -122401,7 +122560,7 @@ function localIdFromCloudRow(row) {
|
|
|
122401
122560
|
function printRow(id, createdAt, title, marker) {
|
|
122402
122561
|
const ts = formatDateTime(createdAt);
|
|
122403
122562
|
const t2 = (title ?? "").length > 60 ? (title ?? "").slice(0, 57) + "..." : title ?? "";
|
|
122404
|
-
console.log(`${id} ${ts} ${t2}${marker !== void 0 ? ` ${
|
|
122563
|
+
console.log(`${id} ${ts} ${t2}${marker !== void 0 ? ` ${import_picocolors32.default.dim(marker)}` : ""}`);
|
|
122405
122564
|
}
|
|
122406
122565
|
async function runInvestigations(opts) {
|
|
122407
122566
|
const json2 = opts.json === true;
|
|
@@ -122429,7 +122588,7 @@ async function runInvestigations(opts) {
|
|
|
122429
122588
|
if (json2) {
|
|
122430
122589
|
console.log(JSON.stringify({ error: localError.message, investigations: [], count: 0 }, null, 2));
|
|
122431
122590
|
}
|
|
122432
|
-
console.error(
|
|
122591
|
+
console.error(import_picocolors32.default.red(localError.message));
|
|
122433
122592
|
return 1;
|
|
122434
122593
|
}
|
|
122435
122594
|
const items = localRows.map((r) => ({
|
|
@@ -122495,18 +122654,18 @@ async function runInvestigations(opts) {
|
|
|
122495
122654
|
if (localRows.length === 0 && cloudOnly === 0 && localError === null) {
|
|
122496
122655
|
console.log('No investigations yet. Run: horus investigate "<hint>"');
|
|
122497
122656
|
} else if (localRows.length > 0) {
|
|
122498
|
-
console.log(
|
|
122657
|
+
console.log(import_picocolors32.default.dim("Replay locally: horus replay <id> \xB7 postmortem: horus postmortem <id>"));
|
|
122499
122658
|
}
|
|
122500
122659
|
if (localError) {
|
|
122501
|
-
console.log(
|
|
122660
|
+
console.log(import_picocolors32.default.dim(`local audit store unavailable \u2014 replay needs it (${localError.message})`));
|
|
122502
122661
|
}
|
|
122503
|
-
if (cloudNote !== null) console.log(
|
|
122662
|
+
if (cloudNote !== null) console.log(import_picocolors32.default.dim(cloudNote));
|
|
122504
122663
|
return 0;
|
|
122505
122664
|
}
|
|
122506
122665
|
|
|
122507
122666
|
// ../../packages/cli/src/commands/lens.ts
|
|
122508
122667
|
init_cjs_shims();
|
|
122509
|
-
var
|
|
122668
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
122510
122669
|
function truncate(s5, n4) {
|
|
122511
122670
|
if (s5 === void 0 || s5 === "") return "";
|
|
122512
122671
|
const flat = s5.replace(/\s+/g, " ").trim();
|
|
@@ -122514,10 +122673,10 @@ function truncate(s5, n4) {
|
|
|
122514
122673
|
}
|
|
122515
122674
|
function printRow2(r) {
|
|
122516
122675
|
const ts = formatDateTime(new Date(r.createdAt));
|
|
122517
|
-
const status =
|
|
122518
|
-
const route2 = r.route ?
|
|
122519
|
-
const errs = r.errorCount > 0 ?
|
|
122520
|
-
const comment = truncate(r.comment, 60) ||
|
|
122676
|
+
const status = import_picocolors33.default.dim(`[${r.status || "?"}]`);
|
|
122677
|
+
const route2 = r.route ? import_picocolors33.default.cyan(r.route) : import_picocolors33.default.dim("(no route)");
|
|
122678
|
+
const errs = r.errorCount > 0 ? import_picocolors33.default.red(`${r.errorCount}err`) : import_picocolors33.default.dim("0err");
|
|
122679
|
+
const comment = truncate(r.comment, 60) || import_picocolors33.default.dim("(no comment)");
|
|
122521
122680
|
console.log(`${r.id} ${ts} ${status} ${route2} ${comment} ${errs}`);
|
|
122522
122681
|
}
|
|
122523
122682
|
async function runLensList(opts) {
|
|
@@ -122536,7 +122695,7 @@ async function runLensList(opts) {
|
|
|
122536
122695
|
const message = err2.message;
|
|
122537
122696
|
if (json2)
|
|
122538
122697
|
console.log(JSON.stringify({ reports: [], count: 0, notes: [message] }, null, 2));
|
|
122539
|
-
console.error(
|
|
122698
|
+
console.error(import_picocolors33.default.red(message));
|
|
122540
122699
|
return 1;
|
|
122541
122700
|
}
|
|
122542
122701
|
if (isUnavailable2(result)) {
|
|
@@ -122545,7 +122704,7 @@ async function runLensList(opts) {
|
|
|
122545
122704
|
JSON.stringify({ reports: [], count: 0, notes: [result.remedy] }, null, 2)
|
|
122546
122705
|
);
|
|
122547
122706
|
} else {
|
|
122548
|
-
console.log(
|
|
122707
|
+
console.log(import_picocolors33.default.yellow(`Lens work queue unavailable \u2014 ${result.remedy}`));
|
|
122549
122708
|
}
|
|
122550
122709
|
return json2 ? 0 : 1;
|
|
122551
122710
|
}
|
|
@@ -122570,10 +122729,10 @@ async function runLensList(opts) {
|
|
|
122570
122729
|
}
|
|
122571
122730
|
for (const r of result.reports) printRow2(r);
|
|
122572
122731
|
console.log(
|
|
122573
|
-
|
|
122732
|
+
import_picocolors33.default.dim(`
|
|
122574
122733
|
${result.reports.length} report(s) \xB7 detail: horus lens show <id>`)
|
|
122575
122734
|
);
|
|
122576
|
-
if (result.notes) for (const n4 of result.notes) console.log(
|
|
122735
|
+
if (result.notes) for (const n4 of result.notes) console.log(import_picocolors33.default.dim(n4));
|
|
122577
122736
|
return 0;
|
|
122578
122737
|
}
|
|
122579
122738
|
async function runLensShow(reportId, opts) {
|
|
@@ -122585,46 +122744,46 @@ async function runLensShow(reportId, opts) {
|
|
|
122585
122744
|
} catch (err2) {
|
|
122586
122745
|
const message = err2.message;
|
|
122587
122746
|
if (json2) console.log(JSON.stringify({ error: message }, null, 2));
|
|
122588
|
-
console.error(
|
|
122747
|
+
console.error(import_picocolors33.default.red(message));
|
|
122589
122748
|
return 1;
|
|
122590
122749
|
}
|
|
122591
122750
|
if (isUnavailable2(detail)) {
|
|
122592
122751
|
if (json2) console.log(JSON.stringify({ error: detail.remedy }, null, 2));
|
|
122593
|
-
else console.log(
|
|
122752
|
+
else console.log(import_picocolors33.default.yellow(`Lens work queue unavailable \u2014 ${detail.remedy}`));
|
|
122594
122753
|
return json2 ? 0 : 1;
|
|
122595
122754
|
}
|
|
122596
122755
|
if (isLensNotFound(detail)) {
|
|
122597
122756
|
const msg = `No Lens report ${reportId} in this workspace.`;
|
|
122598
122757
|
if (json2) console.log(JSON.stringify({ error: msg, notFound: true }, null, 2));
|
|
122599
|
-
else console.log(
|
|
122758
|
+
else console.log(import_picocolors33.default.yellow(msg));
|
|
122600
122759
|
return 1;
|
|
122601
122760
|
}
|
|
122602
122761
|
if (json2) {
|
|
122603
122762
|
console.log(JSON.stringify(detail, null, 2));
|
|
122604
122763
|
return 0;
|
|
122605
122764
|
}
|
|
122606
|
-
console.log(
|
|
122765
|
+
console.log(import_picocolors33.default.bold(`Lens report ${detail.id}`) + ` ${import_picocolors33.default.dim(`[${detail.status}]`)}`);
|
|
122607
122766
|
if (detail.comment)
|
|
122608
|
-
console.log(` ${
|
|
122609
|
-
if (detail.route) console.log(` ${
|
|
122610
|
-
console.log(` ${
|
|
122611
|
-
if (detail.release) console.log(` ${
|
|
122612
|
-
if (detail.gitSha) console.log(` ${
|
|
122767
|
+
console.log(` ${import_picocolors33.default.bold("comment")} ${truncate(detail.comment, 200)}`);
|
|
122768
|
+
if (detail.route) console.log(` ${import_picocolors33.default.bold("route")} ${import_picocolors33.default.cyan(detail.route)}`);
|
|
122769
|
+
console.log(` ${import_picocolors33.default.bold("filed")} ${formatDateTime(new Date(detail.createdAt))}`);
|
|
122770
|
+
if (detail.release) console.log(` ${import_picocolors33.default.bold("release")} ${detail.release}`);
|
|
122771
|
+
if (detail.gitSha) console.log(` ${import_picocolors33.default.bold("gitSha")} ${detail.gitSha}`);
|
|
122613
122772
|
if (detail.topErrorMessage)
|
|
122614
122773
|
console.log(
|
|
122615
|
-
` ${
|
|
122774
|
+
` ${import_picocolors33.default.bold("error")} ${import_picocolors33.default.red(truncate(detail.topErrorMessage, 160))}`
|
|
122616
122775
|
);
|
|
122617
122776
|
if (detail.seed) {
|
|
122618
122777
|
const loc = `${detail.seed.file}${detail.seed.line !== void 0 ? `:${detail.seed.line}` : ""}`;
|
|
122619
|
-
const sym = detail.seed.symbol ?
|
|
122778
|
+
const sym = detail.seed.symbol ? import_picocolors33.default.dim(` (${detail.seed.symbol})`) : "";
|
|
122620
122779
|
console.log(
|
|
122621
|
-
` ${
|
|
122780
|
+
` ${import_picocolors33.default.bold("seed")} ${import_picocolors33.default.green(loc)}${sym} ${import_picocolors33.default.dim("\u2190 raise site to fix")}`
|
|
122622
122781
|
);
|
|
122623
122782
|
}
|
|
122624
122783
|
if (detail.failingRequests.length > 0) {
|
|
122625
|
-
console.log(` ${
|
|
122784
|
+
console.log(` ${import_picocolors33.default.bold("failing")}`);
|
|
122626
122785
|
for (const req of detail.failingRequests) {
|
|
122627
|
-
console.log(` ${req.method} ${req.url} ${
|
|
122786
|
+
console.log(` ${req.method} ${req.url} ${import_picocolors33.default.red(String(req.status ?? "?"))}`);
|
|
122628
122787
|
}
|
|
122629
122788
|
}
|
|
122630
122789
|
return 0;
|
|
@@ -122632,18 +122791,18 @@ async function runLensShow(reportId, opts) {
|
|
|
122632
122791
|
|
|
122633
122792
|
// ../../packages/cli/src/commands/replay.ts
|
|
122634
122793
|
init_cjs_shims();
|
|
122635
|
-
var
|
|
122794
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
122636
122795
|
async function runReplay(id, opts) {
|
|
122637
122796
|
const { db, sql: sql2 } = await openDb();
|
|
122638
122797
|
try {
|
|
122639
122798
|
const row = await getInvestigation(db, id);
|
|
122640
122799
|
if (!row) {
|
|
122641
|
-
console.error(
|
|
122800
|
+
console.error(import_picocolors34.default.red("No investigation found: " + id));
|
|
122642
122801
|
return 1;
|
|
122643
122802
|
}
|
|
122644
122803
|
if (!row.report) {
|
|
122645
122804
|
console.error(
|
|
122646
|
-
|
|
122805
|
+
import_picocolors34.default.red(
|
|
122647
122806
|
"Investigation " + id + " has no stored report (run a newer investigation)."
|
|
122648
122807
|
)
|
|
122649
122808
|
);
|
|
@@ -122656,7 +122815,7 @@ async function runReplay(id, opts) {
|
|
|
122656
122815
|
if (opts.ai && fmt !== "json") {
|
|
122657
122816
|
if (report.aiJudgment && !opts.refreshAi) {
|
|
122658
122817
|
renderStoredAIJudgment(report.aiJudgment);
|
|
122659
|
-
console.log(
|
|
122818
|
+
console.log(import_picocolors34.default.dim("[ai] Stored judgment replayed. Use --refresh-ai to regenerate."));
|
|
122660
122819
|
} else {
|
|
122661
122820
|
const narrativeInput = buildNarrativeInput(report);
|
|
122662
122821
|
const { provider } = await buildNarrativeProvider({
|
|
@@ -122669,17 +122828,17 @@ async function runReplay(id, opts) {
|
|
|
122669
122828
|
);
|
|
122670
122829
|
if (!fromProvider && degraded) {
|
|
122671
122830
|
if (validationErrors?.length) {
|
|
122672
|
-
console.error(
|
|
122831
|
+
console.error(import_picocolors34.default.yellow("[ai] structured validation incomplete \u2014 showing raw AI narrative"));
|
|
122673
122832
|
}
|
|
122674
122833
|
console.log("");
|
|
122675
|
-
console.log(
|
|
122676
|
-
console.log(
|
|
122677
|
-
if (output.what?.trim()) console.log(
|
|
122678
|
-
if (output.why?.trim()) console.log(
|
|
122834
|
+
console.log(import_picocolors34.default.dim("\u2500".repeat(60)));
|
|
122835
|
+
console.log(import_picocolors34.default.bold("AI narrative ") + import_picocolors34.default.yellow("(unstructured \u2014 not validated)"));
|
|
122836
|
+
if (output.what?.trim()) console.log(import_picocolors34.default.bold("\nWhat:"), output.what.trim());
|
|
122837
|
+
if (output.why?.trim()) console.log(import_picocolors34.default.bold("\nWhy:"), output.why.trim());
|
|
122679
122838
|
} else if (!fromProvider) {
|
|
122680
|
-
console.error(
|
|
122839
|
+
console.error(import_picocolors34.default.yellow("[ai] Provider unavailable \u2014 deterministic output shown above."));
|
|
122681
122840
|
if (validationErrors?.length) {
|
|
122682
|
-
console.error(
|
|
122841
|
+
console.error(import_picocolors34.default.dim(` ${validationErrors[0]}`));
|
|
122683
122842
|
}
|
|
122684
122843
|
} else {
|
|
122685
122844
|
const stored = narrativeOutputToStoredJudgment(output, "anthropic");
|
|
@@ -122723,7 +122882,7 @@ async function runOwner(query, opts) {
|
|
|
122723
122882
|
init_cjs_shims();
|
|
122724
122883
|
var import_node_fs23 = require("fs");
|
|
122725
122884
|
var import_node_path25 = require("path");
|
|
122726
|
-
var
|
|
122885
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
122727
122886
|
async function runPostmortem(id, opts) {
|
|
122728
122887
|
const log = opts.write ?? ((line2) => console.log(line2));
|
|
122729
122888
|
let sql2;
|
|
@@ -122737,11 +122896,11 @@ async function runPostmortem(id, opts) {
|
|
|
122737
122896
|
const { db } = conn;
|
|
122738
122897
|
const row = await getInvestigation(db, id);
|
|
122739
122898
|
if (!row) {
|
|
122740
|
-
log(
|
|
122899
|
+
log(import_picocolors35.default.red("No investigation found: " + id));
|
|
122741
122900
|
return 1;
|
|
122742
122901
|
}
|
|
122743
122902
|
if (!row.report) {
|
|
122744
|
-
log(
|
|
122903
|
+
log(import_picocolors35.default.red("Investigation " + id + " has no stored report."));
|
|
122745
122904
|
return 1;
|
|
122746
122905
|
}
|
|
122747
122906
|
report = migrateReport(row.report);
|
|
@@ -122835,23 +122994,23 @@ _AI summary unavailable: ${validationErrors?.[0] ?? "provider error"}_
|
|
|
122835
122994
|
if (opts.output) {
|
|
122836
122995
|
const outputPath = (0, import_node_path25.resolve)(opts.output);
|
|
122837
122996
|
if ((0, import_node_fs23.existsSync)(outputPath) && !opts.force) {
|
|
122838
|
-
log(
|
|
122839
|
-
log(
|
|
122997
|
+
log(import_picocolors35.default.red("\u2717") + " " + outputPath + " already exists");
|
|
122998
|
+
log(import_picocolors35.default.dim(" pass --force to overwrite"));
|
|
122840
122999
|
return 1;
|
|
122841
123000
|
}
|
|
122842
123001
|
try {
|
|
122843
123002
|
(0, import_node_fs23.writeFileSync)(outputPath, content, "utf8");
|
|
122844
123003
|
} catch (err2) {
|
|
122845
|
-
log(
|
|
123004
|
+
log(import_picocolors35.default.red("\u2717 Could not write " + outputPath + ": ") + err2.message);
|
|
122846
123005
|
return 1;
|
|
122847
123006
|
}
|
|
122848
|
-
log(
|
|
123007
|
+
log(import_picocolors35.default.green("\u2713") + " Saved postmortem to " + outputPath);
|
|
122849
123008
|
} else {
|
|
122850
123009
|
log(content);
|
|
122851
123010
|
}
|
|
122852
123011
|
} catch (err2) {
|
|
122853
123012
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
122854
|
-
log(
|
|
123013
|
+
log(import_picocolors35.default.red("postmortem failed: " + message));
|
|
122855
123014
|
return 1;
|
|
122856
123015
|
} finally {
|
|
122857
123016
|
if (sql2) {
|
|
@@ -122863,7 +123022,7 @@ _AI summary unavailable: ${validationErrors?.[0] ?? "provider error"}_
|
|
|
122863
123022
|
|
|
122864
123023
|
// ../../packages/cli/src/commands/score.ts
|
|
122865
123024
|
init_cjs_shims();
|
|
122866
|
-
var
|
|
123025
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
122867
123026
|
init_src();
|
|
122868
123027
|
var SCORE_AI_CONTRACT = `Provide a clearly separated AI score explanation with:
|
|
122869
123028
|
|
|
@@ -122883,11 +123042,11 @@ async function runScore(id, opts) {
|
|
|
122883
123042
|
try {
|
|
122884
123043
|
const row = await getInvestigation(db, id);
|
|
122885
123044
|
if (!row) {
|
|
122886
|
-
console.error(
|
|
123045
|
+
console.error(import_picocolors36.default.red("No investigation found: " + id));
|
|
122887
123046
|
return 1;
|
|
122888
123047
|
}
|
|
122889
123048
|
if (!row.report) {
|
|
122890
|
-
console.error(
|
|
123049
|
+
console.error(import_picocolors36.default.red("Investigation " + id + " has no stored report."));
|
|
122891
123050
|
return 1;
|
|
122892
123051
|
}
|
|
122893
123052
|
const s5 = scoreInvestigation(migrateReport(row.report));
|
|
@@ -122908,7 +123067,7 @@ async function runScore(id, opts) {
|
|
|
122908
123067
|
});
|
|
122909
123068
|
console.log("\n" + renderInterpretation(result));
|
|
122910
123069
|
if (!result.ok) {
|
|
122911
|
-
console.error(
|
|
123070
|
+
console.error(import_picocolors36.default.yellow(`[ai] ${result.warning}`));
|
|
122912
123071
|
}
|
|
122913
123072
|
}
|
|
122914
123073
|
}
|
|
@@ -122942,7 +123101,7 @@ async function runScores(opts) {
|
|
|
122942
123101
|
if (json2) {
|
|
122943
123102
|
console.log(JSON.stringify({ error: err2.message, scores: [], count: 0 }, null, 2));
|
|
122944
123103
|
}
|
|
122945
|
-
console.error(
|
|
123104
|
+
console.error(import_picocolors36.default.red(err2.message));
|
|
122946
123105
|
return 1;
|
|
122947
123106
|
}
|
|
122948
123107
|
if (json2) {
|
|
@@ -122983,7 +123142,7 @@ async function runScores(opts) {
|
|
|
122983
123142
|
|
|
122984
123143
|
// ../../packages/cli/src/commands/ask.ts
|
|
122985
123144
|
init_cjs_shims();
|
|
122986
|
-
var
|
|
123145
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
122987
123146
|
init_src();
|
|
122988
123147
|
function renderAnswer(report, directive, opts) {
|
|
122989
123148
|
const answer = answerQuestion(report, directive);
|
|
@@ -122996,13 +123155,13 @@ function renderAnswer(report, directive, opts) {
|
|
|
122996
123155
|
if (!opts.json && report.aiJudgment) {
|
|
122997
123156
|
const j3 = report.aiJudgment;
|
|
122998
123157
|
console.log("");
|
|
122999
|
-
console.log(
|
|
123000
|
-
console.log(
|
|
123158
|
+
console.log(import_picocolors37.default.dim("\u2500".repeat(60)));
|
|
123159
|
+
console.log(import_picocolors37.default.dim(`Stored AI judgment (${j3.provider}, ${j3.generatedAt}):`));
|
|
123001
123160
|
if (j3.rootCauseAssessment) {
|
|
123002
|
-
console.log(
|
|
123003
|
-
console.log(
|
|
123161
|
+
console.log(import_picocolors37.default.bold("Root cause (AI):"), j3.rootCauseAssessment.summary);
|
|
123162
|
+
console.log(import_picocolors37.default.dim(`Uncertainty: ${j3.rootCauseAssessment.uncertainty}`));
|
|
123004
123163
|
} else {
|
|
123005
|
-
console.log(
|
|
123164
|
+
console.log(import_picocolors37.default.bold("AI Why:"), j3.why);
|
|
123006
123165
|
}
|
|
123007
123166
|
}
|
|
123008
123167
|
return 0;
|
|
@@ -123125,24 +123284,24 @@ function renderCodeAnswer(directive, symbols, ctx) {
|
|
|
123125
123284
|
const top = symbols[0];
|
|
123126
123285
|
if (!top) return;
|
|
123127
123286
|
console.log("");
|
|
123128
|
-
console.log(
|
|
123129
|
-
console.log(` ${
|
|
123130
|
-
if (top.signature) console.log(` ${
|
|
123287
|
+
console.log(import_picocolors37.default.bold(directive));
|
|
123288
|
+
console.log(` ${import_picocolors37.default.green("\u2192")} ${import_picocolors37.default.bold(top.name)} ${import_picocolors37.default.dim(symbolLocation(top))}`);
|
|
123289
|
+
if (top.signature) console.log(` ${import_picocolors37.default.dim(top.signature)}`);
|
|
123131
123290
|
if (ctx?.snippet) {
|
|
123132
123291
|
for (const line2 of ctx.snippet.split("\n").slice(0, 3)) {
|
|
123133
|
-
console.log(
|
|
123292
|
+
console.log(import_picocolors37.default.dim(" " + line2));
|
|
123134
123293
|
}
|
|
123135
123294
|
}
|
|
123136
123295
|
const others = symbols.slice(1);
|
|
123137
123296
|
if (others.length > 0) {
|
|
123138
123297
|
console.log("");
|
|
123139
|
-
console.log(
|
|
123298
|
+
console.log(import_picocolors37.default.dim(" Other matches:"));
|
|
123140
123299
|
for (const s5 of others) {
|
|
123141
|
-
console.log(` - ${s5.name} ${
|
|
123300
|
+
console.log(` - ${s5.name} ${import_picocolors37.default.dim(symbolLocation(s5))}`);
|
|
123142
123301
|
}
|
|
123143
123302
|
}
|
|
123144
123303
|
console.log("");
|
|
123145
|
-
console.log(
|
|
123304
|
+
console.log(import_picocolors37.default.dim(" (fresh source lookup \u2014 re-queried the source host)"));
|
|
123146
123305
|
}
|
|
123147
123306
|
async function answerFromSource(directive, opts) {
|
|
123148
123307
|
let code;
|
|
@@ -123194,8 +123353,8 @@ async function runAsk(id, directive, opts) {
|
|
|
123194
123353
|
const session = authedClient();
|
|
123195
123354
|
if (!session) {
|
|
123196
123355
|
console.error(
|
|
123197
|
-
|
|
123198
|
-
`This repo is linked to Horus Cloud but you are not logged in. Run ${
|
|
123356
|
+
import_picocolors37.default.red(
|
|
123357
|
+
`This repo is linked to Horus Cloud but you are not logged in. Run ${import_picocolors37.default.bold("horus login")} first.`
|
|
123199
123358
|
)
|
|
123200
123359
|
);
|
|
123201
123360
|
return 1;
|
|
@@ -123204,15 +123363,15 @@ async function runAsk(id, directive, opts) {
|
|
|
123204
123363
|
const report = await fetchInvestigationReportFromCloud(session.client, cloudCfg, id);
|
|
123205
123364
|
if (report) return renderAnswer(report, directive, opts);
|
|
123206
123365
|
console.error(
|
|
123207
|
-
|
|
123208
|
-
`Investigation ${id} has no saved report locally or in Horus Cloud. Run ${
|
|
123366
|
+
import_picocolors37.default.red(
|
|
123367
|
+
`Investigation ${id} has no saved report locally or in Horus Cloud. Run ${import_picocolors37.default.bold("horus investigate")} first.`
|
|
123209
123368
|
)
|
|
123210
123369
|
);
|
|
123211
123370
|
return 1;
|
|
123212
123371
|
} catch (err2) {
|
|
123213
123372
|
if (err2 instanceof CloudError && err2.status === 404) {
|
|
123214
123373
|
console.error(
|
|
123215
|
-
|
|
123374
|
+
import_picocolors37.default.red(
|
|
123216
123375
|
`No investigation found for "${id}" locally or in Horus Cloud. Use the id printed at the top of \`horus investigate\` output.`
|
|
123217
123376
|
)
|
|
123218
123377
|
);
|
|
@@ -123226,21 +123385,21 @@ async function runAsk(id, directive, opts) {
|
|
|
123226
123385
|
case "found":
|
|
123227
123386
|
return renderAnswer(local.report, directive, opts);
|
|
123228
123387
|
case "no-report":
|
|
123229
|
-
console.error(
|
|
123388
|
+
console.error(import_picocolors37.default.red("Investigation " + id + " has no stored report."));
|
|
123230
123389
|
return 1;
|
|
123231
123390
|
case "error":
|
|
123232
|
-
console.error(
|
|
123391
|
+
console.error(import_picocolors37.default.red(local.message));
|
|
123233
123392
|
return 1;
|
|
123234
123393
|
case "not-found":
|
|
123235
123394
|
default:
|
|
123236
|
-
console.error(
|
|
123395
|
+
console.error(import_picocolors37.default.red("No investigation found: " + id));
|
|
123237
123396
|
return 1;
|
|
123238
123397
|
}
|
|
123239
123398
|
}
|
|
123240
123399
|
|
|
123241
123400
|
// ../../packages/cli/src/commands/onboard.ts
|
|
123242
123401
|
init_cjs_shims();
|
|
123243
|
-
var
|
|
123402
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
123244
123403
|
init_src();
|
|
123245
123404
|
var ONBOARD_AI_CONTRACT = `Provide a clearly separated AI onboarding guide with:
|
|
123246
123405
|
|
|
@@ -123269,7 +123428,7 @@ async function runOnboard(area, opts) {
|
|
|
123269
123428
|
try {
|
|
123270
123429
|
renv = resolveEnvironment(config2, { project: opts.repo });
|
|
123271
123430
|
} catch (err2) {
|
|
123272
|
-
console.error(
|
|
123431
|
+
console.error(import_picocolors38.default.red(err2.message));
|
|
123273
123432
|
return 1;
|
|
123274
123433
|
}
|
|
123275
123434
|
const repo = { name: renv.project, path: renv.path };
|
|
@@ -123277,7 +123436,7 @@ async function runOnboard(area, opts) {
|
|
|
123277
123436
|
const health = await code.health();
|
|
123278
123437
|
if (!health.ok) {
|
|
123279
123438
|
console.error(
|
|
123280
|
-
|
|
123439
|
+
import_picocolors38.default.red("Source-intelligence host unreachable \u2014 run: horus init")
|
|
123281
123440
|
);
|
|
123282
123441
|
return 1;
|
|
123283
123442
|
}
|
|
@@ -123310,7 +123469,7 @@ async function runOnboard(area, opts) {
|
|
|
123310
123469
|
});
|
|
123311
123470
|
console.log("\n" + renderInterpretation(result));
|
|
123312
123471
|
if (!result.ok) {
|
|
123313
|
-
console.error(
|
|
123472
|
+
console.error(import_picocolors38.default.yellow(`[ai] ${result.warning}`));
|
|
123314
123473
|
}
|
|
123315
123474
|
}
|
|
123316
123475
|
}
|
|
@@ -123319,14 +123478,14 @@ async function runOnboard(area, opts) {
|
|
|
123319
123478
|
}
|
|
123320
123479
|
return 0;
|
|
123321
123480
|
} catch (err2) {
|
|
123322
|
-
console.error(
|
|
123481
|
+
console.error(import_picocolors38.default.red(err2.message));
|
|
123323
123482
|
return 1;
|
|
123324
123483
|
}
|
|
123325
123484
|
}
|
|
123326
123485
|
|
|
123327
123486
|
// ../../packages/cli/src/commands/memory.ts
|
|
123328
123487
|
init_cjs_shims();
|
|
123329
|
-
var
|
|
123488
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
123330
123489
|
var import_promises2 = require("readline/promises");
|
|
123331
123490
|
init_src();
|
|
123332
123491
|
|
|
@@ -123692,7 +123851,7 @@ function resolveProject(config2, repo) {
|
|
|
123692
123851
|
}
|
|
123693
123852
|
if (!project) {
|
|
123694
123853
|
console.error(
|
|
123695
|
-
|
|
123854
|
+
import_picocolors39.default.red("Could not resolve a project \u2014 pass --repo <name> or run inside a repo.")
|
|
123696
123855
|
);
|
|
123697
123856
|
return null;
|
|
123698
123857
|
}
|
|
@@ -123716,7 +123875,7 @@ async function withStore(url, fn2) {
|
|
|
123716
123875
|
}
|
|
123717
123876
|
}
|
|
123718
123877
|
console.error(
|
|
123719
|
-
|
|
123878
|
+
import_picocolors39.default.yellow("Linked to Horus Cloud but not logged in \u2014 memory stays local only. Run `horus login`.")
|
|
123720
123879
|
);
|
|
123721
123880
|
}
|
|
123722
123881
|
const { db, sql: sql2 } = await openDb(url);
|
|
@@ -123800,7 +123959,7 @@ function renderStoredItems(items) {
|
|
|
123800
123959
|
);
|
|
123801
123960
|
if (r.item.origin === "cloud") {
|
|
123802
123961
|
const who = r.item.authorName ? `teammate ${r.item.authorName}` : "a teammate";
|
|
123803
|
-
lines.push(` - ${
|
|
123962
|
+
lines.push(` - ${import_picocolors39.default.dim(`shared by ${who} (team)`)}`);
|
|
123804
123963
|
}
|
|
123805
123964
|
}
|
|
123806
123965
|
return lines.join("\n");
|
|
@@ -123832,14 +123991,14 @@ async function runMemoryShow(scope, opts) {
|
|
|
123832
123991
|
console.log(renderMemoryView(view));
|
|
123833
123992
|
console.log("");
|
|
123834
123993
|
console.log(renderStoredItems(stored));
|
|
123835
|
-
for (const s5 of nextSteps) console.log(
|
|
123994
|
+
for (const s5 of nextSteps) console.log(import_picocolors39.default.dim(" Suggested next: ") + formatRouteStep(s5));
|
|
123836
123995
|
}
|
|
123837
123996
|
return 0;
|
|
123838
123997
|
} finally {
|
|
123839
123998
|
await sql2.end();
|
|
123840
123999
|
}
|
|
123841
124000
|
} catch (err2) {
|
|
123842
|
-
console.error(
|
|
124001
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
123843
124002
|
return 1;
|
|
123844
124003
|
}
|
|
123845
124004
|
}
|
|
@@ -123847,19 +124006,19 @@ async function runMemoryAdd(claim, opts) {
|
|
|
123847
124006
|
try {
|
|
123848
124007
|
const text2 = (claim ?? "").trim();
|
|
123849
124008
|
if (text2 === "") {
|
|
123850
|
-
console.error(
|
|
124009
|
+
console.error(import_picocolors39.default.red("A non-empty claim is required."));
|
|
123851
124010
|
return 1;
|
|
123852
124011
|
}
|
|
123853
124012
|
const kind = opts.kind ?? "code-fact";
|
|
123854
124013
|
if (!MEMORY_KINDS.includes(kind)) {
|
|
123855
|
-
console.error(
|
|
124014
|
+
console.error(import_picocolors39.default.red(`Unknown --kind "${opts.kind}" (one of: ${MEMORY_KINDS.join(", ")}).`));
|
|
123856
124015
|
return 1;
|
|
123857
124016
|
}
|
|
123858
124017
|
let confidence = DEFAULT_ADD_CONFIDENCE;
|
|
123859
124018
|
if (opts.confidence !== void 0) {
|
|
123860
124019
|
const c4 = Number(opts.confidence);
|
|
123861
124020
|
if (!Number.isFinite(c4) || c4 < 0 || c4 > 1) {
|
|
123862
|
-
console.error(
|
|
124021
|
+
console.error(import_picocolors39.default.red("--confidence must be a number between 0 and 1."));
|
|
123863
124022
|
return 1;
|
|
123864
124023
|
}
|
|
123865
124024
|
confidence = c4;
|
|
@@ -123892,7 +124051,7 @@ async function runMemoryAdd(claim, opts) {
|
|
|
123892
124051
|
);
|
|
123893
124052
|
} else {
|
|
123894
124053
|
console.log(
|
|
123895
|
-
|
|
124054
|
+
import_picocolors39.default.green(`Added memory item ${created.id} (${created.kind}, scope: ${created.scope}).`)
|
|
123896
124055
|
);
|
|
123897
124056
|
}
|
|
123898
124057
|
await bestEffortUpsert(buildVectorIndex(config2, project), {
|
|
@@ -123905,10 +124064,10 @@ async function runMemoryAdd(claim, opts) {
|
|
|
123905
124064
|
});
|
|
123906
124065
|
} catch (err2) {
|
|
123907
124066
|
if (err2 instanceof MemorySecretError) {
|
|
123908
|
-
console.error(
|
|
124067
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
123909
124068
|
return 1;
|
|
123910
124069
|
}
|
|
123911
|
-
console.error(
|
|
124070
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
123912
124071
|
return 1;
|
|
123913
124072
|
}
|
|
123914
124073
|
}
|
|
@@ -123928,7 +124087,7 @@ async function runMemoryConfirm(investigationId, opts) {
|
|
|
123928
124087
|
try {
|
|
123929
124088
|
const id = (investigationId ?? "").trim();
|
|
123930
124089
|
if (id === "") {
|
|
123931
|
-
console.error(
|
|
124090
|
+
console.error(import_picocolors39.default.red("An investigation id is required."));
|
|
123932
124091
|
return 1;
|
|
123933
124092
|
}
|
|
123934
124093
|
const config2 = await loadConfig(opts.config);
|
|
@@ -123938,7 +124097,7 @@ async function runMemoryConfirm(investigationId, opts) {
|
|
|
123938
124097
|
try {
|
|
123939
124098
|
const investigation = await getInvestigation(db, id);
|
|
123940
124099
|
if (investigation === null) {
|
|
123941
|
-
console.error(
|
|
124100
|
+
console.error(import_picocolors39.default.red(`Investigation not found: ${id}`));
|
|
123942
124101
|
return 1;
|
|
123943
124102
|
}
|
|
123944
124103
|
const report = investigation.report ?? null;
|
|
@@ -123992,7 +124151,7 @@ async function runMemoryConfirm(investigationId, opts) {
|
|
|
123992
124151
|
);
|
|
123993
124152
|
} else {
|
|
123994
124153
|
console.log(
|
|
123995
|
-
|
|
124154
|
+
import_picocolors39.default.green(
|
|
123996
124155
|
`Confirmed outcome stored as ${created.id} (private) and linked to investigation ${id}.`
|
|
123997
124156
|
)
|
|
123998
124157
|
);
|
|
@@ -124009,10 +124168,10 @@ async function runMemoryConfirm(investigationId, opts) {
|
|
|
124009
124168
|
}
|
|
124010
124169
|
} catch (err2) {
|
|
124011
124170
|
if (err2 instanceof MemorySecretError) {
|
|
124012
|
-
console.error(
|
|
124171
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124013
124172
|
return 1;
|
|
124014
124173
|
}
|
|
124015
|
-
console.error(
|
|
124174
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124016
124175
|
return 1;
|
|
124017
124176
|
}
|
|
124018
124177
|
}
|
|
@@ -124020,7 +124179,7 @@ async function setStatusLeaf(id, status, verb, opts) {
|
|
|
124020
124179
|
try {
|
|
124021
124180
|
const memId = (id ?? "").trim();
|
|
124022
124181
|
if (memId === "") {
|
|
124023
|
-
console.error(
|
|
124182
|
+
console.error(import_picocolors39.default.red("A memory item id is required."));
|
|
124024
124183
|
return 1;
|
|
124025
124184
|
}
|
|
124026
124185
|
const config2 = await loadConfig(opts.config);
|
|
@@ -124029,12 +124188,12 @@ async function setStatusLeaf(id, status, verb, opts) {
|
|
|
124029
124188
|
if (opts.json) {
|
|
124030
124189
|
console.log(JSON.stringify({ ok: true, id: memId, status }, null, 2));
|
|
124031
124190
|
} else {
|
|
124032
|
-
console.log(
|
|
124191
|
+
console.log(import_picocolors39.default.green(`${verb} ${memId} (status: ${status}).`));
|
|
124033
124192
|
}
|
|
124034
124193
|
return 0;
|
|
124035
124194
|
});
|
|
124036
124195
|
} catch (err2) {
|
|
124037
|
-
console.error(
|
|
124196
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124038
124197
|
return 1;
|
|
124039
124198
|
}
|
|
124040
124199
|
}
|
|
@@ -124079,13 +124238,13 @@ async function runMemoryList(opts) {
|
|
|
124079
124238
|
return 0;
|
|
124080
124239
|
});
|
|
124081
124240
|
} catch (err2) {
|
|
124082
|
-
console.error(
|
|
124241
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124083
124242
|
return 1;
|
|
124084
124243
|
}
|
|
124085
124244
|
}
|
|
124086
124245
|
function parseRel(rel) {
|
|
124087
124246
|
if (rel === void 0 || !MEMORY_RELS2.includes(rel)) {
|
|
124088
|
-
console.error(
|
|
124247
|
+
console.error(import_picocolors39.default.red(`--rel must be one of: ${MEMORY_RELS2.join(", ")}.`));
|
|
124089
124248
|
return null;
|
|
124090
124249
|
}
|
|
124091
124250
|
return rel;
|
|
@@ -124095,7 +124254,7 @@ async function runMemoryLink(a2, b5, opts) {
|
|
|
124095
124254
|
const fromId = (a2 ?? "").trim();
|
|
124096
124255
|
const toId = (b5 ?? "").trim();
|
|
124097
124256
|
if (fromId === "" || toId === "") {
|
|
124098
|
-
console.error(
|
|
124257
|
+
console.error(import_picocolors39.default.red("Two memory item ids are required: `memory link <a> <b> --rel <rel>`."));
|
|
124099
124258
|
return 1;
|
|
124100
124259
|
}
|
|
124101
124260
|
const rel = parseRel(opts.rel);
|
|
@@ -124118,13 +124277,13 @@ async function runMemoryLink(a2, b5, opts) {
|
|
|
124118
124277
|
);
|
|
124119
124278
|
} else {
|
|
124120
124279
|
console.log(
|
|
124121
|
-
|
|
124280
|
+
import_picocolors39.default.green(`Linked ${link.fromMemoryId} ${import_picocolors39.default.bold(link.rel)} ${link.toRef} (${link.id}).`)
|
|
124122
124281
|
);
|
|
124123
124282
|
}
|
|
124124
124283
|
return 0;
|
|
124125
124284
|
});
|
|
124126
124285
|
} catch (err2) {
|
|
124127
|
-
console.error(
|
|
124286
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124128
124287
|
return 1;
|
|
124129
124288
|
}
|
|
124130
124289
|
}
|
|
@@ -124133,7 +124292,7 @@ async function runMemoryUnlink(a2, b5, opts) {
|
|
|
124133
124292
|
const fromId = (a2 ?? "").trim();
|
|
124134
124293
|
const toId = (b5 ?? "").trim();
|
|
124135
124294
|
if (fromId === "" || toId === "") {
|
|
124136
|
-
console.error(
|
|
124295
|
+
console.error(import_picocolors39.default.red("Two memory item ids are required: `memory unlink <a> <b> --rel <rel>`."));
|
|
124137
124296
|
return 1;
|
|
124138
124297
|
}
|
|
124139
124298
|
const rel = parseRel(opts.rel);
|
|
@@ -124149,19 +124308,19 @@ async function runMemoryUnlink(a2, b5, opts) {
|
|
|
124149
124308
|
if (opts.json) {
|
|
124150
124309
|
console.log(JSON.stringify({ ok: true, removed, rel, from: fromId, to: toId }, null, 2));
|
|
124151
124310
|
} else if (removed === 0) {
|
|
124152
|
-
console.log(
|
|
124311
|
+
console.log(import_picocolors39.default.dim(`No ${rel} link from ${fromId} to ${toId} \u2014 nothing removed.`));
|
|
124153
124312
|
} else {
|
|
124154
|
-
console.log(
|
|
124313
|
+
console.log(import_picocolors39.default.green(`Unlinked ${fromId} ${import_picocolors39.default.bold(rel)} ${toId} (${removed} edge removed).`));
|
|
124155
124314
|
}
|
|
124156
124315
|
return 0;
|
|
124157
124316
|
});
|
|
124158
124317
|
} catch (err2) {
|
|
124159
|
-
console.error(
|
|
124318
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124160
124319
|
return 1;
|
|
124161
124320
|
}
|
|
124162
124321
|
}
|
|
124163
124322
|
function renderProposal(p5) {
|
|
124164
|
-
return ` ${
|
|
124323
|
+
return ` ${import_picocolors39.default.dim(`[${p5.detection}]`)} ${p5.fromMemoryId} ${import_picocolors39.default.bold(p5.rel)} ${p5.toMemoryId} ${import_picocolors39.default.dim(`\u2014 ${p5.reason}`)}`;
|
|
124165
124324
|
}
|
|
124166
124325
|
async function runMemoryDetect(opts) {
|
|
124167
124326
|
try {
|
|
@@ -124188,11 +124347,11 @@ async function runMemoryDetect(opts) {
|
|
|
124188
124347
|
if (opts.json) {
|
|
124189
124348
|
console.log(JSON.stringify({ ok: true, dryRun: true, proposed: proposals.length, applied: 0, edges: proposals }, null, 2));
|
|
124190
124349
|
} else if (proposals.length === 0) {
|
|
124191
|
-
console.log(
|
|
124350
|
+
console.log(import_picocolors39.default.dim("No memory\u2192memory edges proposed."));
|
|
124192
124351
|
} else {
|
|
124193
|
-
console.log(
|
|
124352
|
+
console.log(import_picocolors39.default.bold(`Proposed ${proposals.length} edge(s) ${import_picocolors39.default.dim("(dry run \u2014 nothing written)")}:`));
|
|
124194
124353
|
for (const p5 of proposals) console.log(renderProposal(p5));
|
|
124195
|
-
console.log(
|
|
124354
|
+
console.log(import_picocolors39.default.dim("Re-run without --dry-run to persist these edges."));
|
|
124196
124355
|
}
|
|
124197
124356
|
return 0;
|
|
124198
124357
|
}
|
|
@@ -124209,19 +124368,19 @@ async function runMemoryDetect(opts) {
|
|
|
124209
124368
|
}
|
|
124210
124369
|
);
|
|
124211
124370
|
applied += 1;
|
|
124212
|
-
if (!opts.json) console.log(`${
|
|
124371
|
+
if (!opts.json) console.log(`${import_picocolors39.default.green("\u2713")}${renderProposal(p5)}`);
|
|
124213
124372
|
}
|
|
124214
124373
|
if (opts.json) {
|
|
124215
124374
|
console.log(JSON.stringify({ ok: true, dryRun: false, proposed: proposals.length, applied, edges: proposals }, null, 2));
|
|
124216
124375
|
} else if (applied === 0) {
|
|
124217
|
-
console.log(
|
|
124376
|
+
console.log(import_picocolors39.default.dim("No memory\u2192memory edges proposed."));
|
|
124218
124377
|
} else {
|
|
124219
|
-
console.log(
|
|
124378
|
+
console.log(import_picocolors39.default.green(`Applied ${applied} detected edge(s).`));
|
|
124220
124379
|
}
|
|
124221
124380
|
return 0;
|
|
124222
124381
|
});
|
|
124223
124382
|
} catch (err2) {
|
|
124224
|
-
console.error(
|
|
124383
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124225
124384
|
return 1;
|
|
124226
124385
|
}
|
|
124227
124386
|
}
|
|
@@ -124252,7 +124411,7 @@ async function runMemorySync(opts) {
|
|
|
124252
124411
|
const json2 = opts.json === true;
|
|
124253
124412
|
const fail = (msg) => {
|
|
124254
124413
|
if (json2) console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
124255
|
-
else console.error(
|
|
124414
|
+
else console.error(import_picocolors39.default.red(msg));
|
|
124256
124415
|
return 1;
|
|
124257
124416
|
};
|
|
124258
124417
|
const root = repoRootOrCwd(opts.cwd);
|
|
@@ -124304,19 +124463,19 @@ async function runMemorySync(opts) {
|
|
|
124304
124463
|
2
|
|
124305
124464
|
)
|
|
124306
124465
|
);
|
|
124307
|
-
else console.log(
|
|
124466
|
+
else console.log(import_picocolors39.default.dim("No local memory items to sync."));
|
|
124308
124467
|
return 0;
|
|
124309
124468
|
}
|
|
124310
124469
|
if (!json2) {
|
|
124311
124470
|
console.log(
|
|
124312
|
-
|
|
124313
|
-
`Will sync ${inputs.length} memory item(s), ${linkInputs.length} link(s), ${auditInputs.length} audit row(s) to ${target} ${
|
|
124471
|
+
import_picocolors39.default.bold(
|
|
124472
|
+
`Will sync ${inputs.length} memory item(s), ${linkInputs.length} link(s), ${auditInputs.length} audit row(s) to ${target} ${import_picocolors39.default.dim("(cloud)")}:`
|
|
124314
124473
|
)
|
|
124315
124474
|
);
|
|
124316
124475
|
for (const it2 of items.slice(0, 20)) {
|
|
124317
|
-
console.log(` ${
|
|
124476
|
+
console.log(` ${import_picocolors39.default.dim(it2.id.slice(0, 8))} ${import_picocolors39.default.dim(`[${it2.kind}]`)} ${it2.claim.slice(0, 70)}`);
|
|
124318
124477
|
}
|
|
124319
|
-
if (items.length > 20) console.log(
|
|
124478
|
+
if (items.length > 20) console.log(import_picocolors39.default.dim(` \u2026and ${items.length - 20} more`));
|
|
124320
124479
|
}
|
|
124321
124480
|
if (opts.dryRun) {
|
|
124322
124481
|
if (json2)
|
|
@@ -124327,13 +124486,13 @@ async function runMemorySync(opts) {
|
|
|
124327
124486
|
2
|
|
124328
124487
|
)
|
|
124329
124488
|
);
|
|
124330
|
-
else console.log(
|
|
124489
|
+
else console.log(import_picocolors39.default.dim("Dry run \u2014 nothing uploaded. Re-run without --dry-run to sync."));
|
|
124331
124490
|
return 0;
|
|
124332
124491
|
}
|
|
124333
124492
|
if (!opts.yes && !json2) {
|
|
124334
124493
|
if (!process.stdin.isTTY) {
|
|
124335
124494
|
console.error(
|
|
124336
|
-
|
|
124495
|
+
import_picocolors39.default.yellow(`Re-run with ${import_picocolors39.default.bold("--yes")} to sync, or ${import_picocolors39.default.bold("--dry-run")} to preview only.`)
|
|
124337
124496
|
);
|
|
124338
124497
|
return 1;
|
|
124339
124498
|
}
|
|
@@ -124341,7 +124500,7 @@ async function runMemorySync(opts) {
|
|
|
124341
124500
|
try {
|
|
124342
124501
|
const answer = (await rl.question(`Sync ${inputs.length} memory item(s) to ${target}? (y/N) `)).trim().toLowerCase();
|
|
124343
124502
|
if (answer !== "y" && answer !== "yes") {
|
|
124344
|
-
console.log(
|
|
124503
|
+
console.log(import_picocolors39.default.dim("Aborted. Nothing synced."));
|
|
124345
124504
|
return 0;
|
|
124346
124505
|
}
|
|
124347
124506
|
} finally {
|
|
@@ -124357,11 +124516,11 @@ async function runMemorySync(opts) {
|
|
|
124357
124516
|
try {
|
|
124358
124517
|
const res = await session.client.syncMemoryItems(cfg.project.id, { items: batch });
|
|
124359
124518
|
synced += res.items?.length ?? batch.length;
|
|
124360
|
-
if (!json2) console.log(`${
|
|
124519
|
+
if (!json2) console.log(`${import_picocolors39.default.green("\u2713")} synced ${batch.length} item(s)`);
|
|
124361
124520
|
} catch (err2) {
|
|
124362
124521
|
failed += batch.length;
|
|
124363
124522
|
if (json2) reportCloudError(err2);
|
|
124364
|
-
else console.error(`${
|
|
124523
|
+
else console.error(`${import_picocolors39.default.red("\u2717")} ${err2.message}`);
|
|
124365
124524
|
}
|
|
124366
124525
|
}
|
|
124367
124526
|
for (let i3 = 0; i3 < linkInputs.length; i3 += MEMORY_SYNC_EDGE_BATCH_MAX) {
|
|
@@ -124369,11 +124528,11 @@ async function runMemorySync(opts) {
|
|
|
124369
124528
|
try {
|
|
124370
124529
|
const res = await session.client.syncMemoryItems(cfg.project.id, { links: batch });
|
|
124371
124530
|
syncedLinks += res.links?.total ?? batch.length;
|
|
124372
|
-
if (!json2) console.log(`${
|
|
124531
|
+
if (!json2) console.log(`${import_picocolors39.default.green("\u2713")} synced ${batch.length} link(s)`);
|
|
124373
124532
|
} catch (err2) {
|
|
124374
124533
|
failed += batch.length;
|
|
124375
124534
|
if (json2) reportCloudError(err2);
|
|
124376
|
-
else console.error(`${
|
|
124535
|
+
else console.error(`${import_picocolors39.default.red("\u2717")} ${err2.message}`);
|
|
124377
124536
|
}
|
|
124378
124537
|
}
|
|
124379
124538
|
for (let i3 = 0; i3 < auditInputs.length; i3 += MEMORY_SYNC_EDGE_BATCH_MAX) {
|
|
@@ -124381,11 +124540,11 @@ async function runMemorySync(opts) {
|
|
|
124381
124540
|
try {
|
|
124382
124541
|
const res = await session.client.syncMemoryItems(cfg.project.id, { audit: batch });
|
|
124383
124542
|
syncedAudit += res.audit?.total ?? batch.length;
|
|
124384
|
-
if (!json2) console.log(`${
|
|
124543
|
+
if (!json2) console.log(`${import_picocolors39.default.green("\u2713")} synced ${batch.length} audit row(s)`);
|
|
124385
124544
|
} catch (err2) {
|
|
124386
124545
|
failed += batch.length;
|
|
124387
124546
|
if (json2) reportCloudError(err2);
|
|
124388
|
-
else console.error(`${
|
|
124547
|
+
else console.error(`${import_picocolors39.default.red("\u2717")} ${err2.message}`);
|
|
124389
124548
|
}
|
|
124390
124549
|
}
|
|
124391
124550
|
if (json2) {
|
|
@@ -124407,10 +124566,10 @@ async function runMemorySync(opts) {
|
|
|
124407
124566
|
} else {
|
|
124408
124567
|
console.log("");
|
|
124409
124568
|
console.log(
|
|
124410
|
-
`${
|
|
124569
|
+
`${import_picocolors39.default.bold("Memory sync complete:")} ${import_picocolors39.default.green(`${synced} item(s)`)}, ${import_picocolors39.default.green(`${syncedLinks} link(s)`)}, ${import_picocolors39.default.green(`${syncedAudit} audit row(s)`)}, ` + (failed ? import_picocolors39.default.red(`${failed} failed`) : "0 failed") + "."
|
|
124411
124570
|
);
|
|
124412
124571
|
console.log(
|
|
124413
|
-
|
|
124572
|
+
import_picocolors39.default.dim("Local data was not modified. Re-running is safe \u2014 items/links dedupe by client id, audit is append-only. Vectors never sync.")
|
|
124414
124573
|
);
|
|
124415
124574
|
}
|
|
124416
124575
|
return failed > 0 ? 1 : 0;
|
|
@@ -124432,7 +124591,7 @@ async function runMemoryPromote(id, opts) {
|
|
|
124432
124591
|
const json2 = opts.json === true;
|
|
124433
124592
|
const fail = (msg) => {
|
|
124434
124593
|
if (json2) console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
124435
|
-
else console.error(
|
|
124594
|
+
else console.error(import_picocolors39.default.red(msg));
|
|
124436
124595
|
return 1;
|
|
124437
124596
|
};
|
|
124438
124597
|
const memId = (id ?? "").trim();
|
|
@@ -124462,7 +124621,7 @@ async function runMemoryPromote(id, opts) {
|
|
|
124462
124621
|
}
|
|
124463
124622
|
if (row.origin === "cloud") {
|
|
124464
124623
|
if (json2) console.log(JSON.stringify({ ok: true, id: memId, alreadyTeam: true }, null, 2));
|
|
124465
|
-
else console.log(
|
|
124624
|
+
else console.log(import_picocolors39.default.dim(`${memId} is already a team item \u2014 nothing to promote.`));
|
|
124466
124625
|
return 0;
|
|
124467
124626
|
}
|
|
124468
124627
|
const res = await session.client.promoteTeamMemory(cfg.project.id, {
|
|
@@ -124495,7 +124654,7 @@ async function runMemoryPromote(id, opts) {
|
|
|
124495
124654
|
);
|
|
124496
124655
|
} else {
|
|
124497
124656
|
console.log(
|
|
124498
|
-
|
|
124657
|
+
import_picocolors39.default.green(`Promoted ${memId} to team memory (${cfg.project.slug}) \u2014 now visible to teammates.`)
|
|
124499
124658
|
);
|
|
124500
124659
|
}
|
|
124501
124660
|
return 0;
|
|
@@ -124519,7 +124678,7 @@ async function runMemoryPull(opts) {
|
|
|
124519
124678
|
const json2 = opts.json === true;
|
|
124520
124679
|
const fail = (msg) => {
|
|
124521
124680
|
if (json2) console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
124522
|
-
else console.error(
|
|
124681
|
+
else console.error(import_picocolors39.default.red(msg));
|
|
124523
124682
|
return 1;
|
|
124524
124683
|
};
|
|
124525
124684
|
const root = repoRootOrCwd(opts.cwd);
|
|
@@ -124564,7 +124723,7 @@ async function runMemoryPull(opts) {
|
|
|
124564
124723
|
JSON.stringify({ ok: true, offline: true, stale: true, cached: cached2.length, note }, null, 2)
|
|
124565
124724
|
);
|
|
124566
124725
|
} else {
|
|
124567
|
-
console.log(
|
|
124726
|
+
console.log(import_picocolors39.default.yellow(`Offline \u2014 serving ${cached2.length} cached team item(s) (${note}).`));
|
|
124568
124727
|
}
|
|
124569
124728
|
return 0;
|
|
124570
124729
|
}
|
|
@@ -124611,11 +124770,11 @@ async function runMemoryPull(opts) {
|
|
|
124611
124770
|
);
|
|
124612
124771
|
} else {
|
|
124613
124772
|
console.log(
|
|
124614
|
-
|
|
124773
|
+
import_picocolors39.default.green(
|
|
124615
124774
|
`Pulled ${upserted} team memory item(s)` + (removed ? `, dropped ${removed} stale` : "") + "."
|
|
124616
124775
|
)
|
|
124617
124776
|
);
|
|
124618
|
-
console.log(
|
|
124777
|
+
console.log(import_picocolors39.default.dim("Team items are read-only locally \u2014 re-promote to change one. Vectors stay local."));
|
|
124619
124778
|
}
|
|
124620
124779
|
return 0;
|
|
124621
124780
|
} catch (err2) {
|
|
@@ -124643,7 +124802,7 @@ async function runMemoryAccuracy(opts) {
|
|
|
124643
124802
|
let source;
|
|
124644
124803
|
if (opts.source !== void 0) {
|
|
124645
124804
|
if (!isOutcomeSource(opts.source)) {
|
|
124646
|
-
console.error(
|
|
124805
|
+
console.error(import_picocolors39.default.red(`Unknown --source "${opts.source}" (one of: feedback, confirm).`));
|
|
124647
124806
|
return 1;
|
|
124648
124807
|
}
|
|
124649
124808
|
source = opts.source;
|
|
@@ -124656,7 +124815,7 @@ async function runMemoryAccuracy(opts) {
|
|
|
124656
124815
|
const parsed = new Date(opts.since);
|
|
124657
124816
|
if (Number.isNaN(parsed.getTime())) {
|
|
124658
124817
|
console.error(
|
|
124659
|
-
|
|
124818
|
+
import_picocolors39.default.red("--since must be a parseable date (e.g. 2026-06-01 or an ISO timestamp).")
|
|
124660
124819
|
);
|
|
124661
124820
|
return 1;
|
|
124662
124821
|
}
|
|
@@ -124664,7 +124823,7 @@ async function runMemoryAccuracy(opts) {
|
|
|
124664
124823
|
window2 = `since ${parsed.toISOString().slice(0, 10)}`;
|
|
124665
124824
|
} else if (opts.days !== void 0) {
|
|
124666
124825
|
if (!Number.isFinite(opts.days) || opts.days <= 0) {
|
|
124667
|
-
console.error(
|
|
124826
|
+
console.error(import_picocolors39.default.red("--days must be a positive number."));
|
|
124668
124827
|
return 1;
|
|
124669
124828
|
}
|
|
124670
124829
|
since = new Date(Date.now() - opts.days * MS_PER_DAY2);
|
|
@@ -124702,22 +124861,22 @@ async function runMemoryAccuracy(opts) {
|
|
|
124702
124861
|
);
|
|
124703
124862
|
} else {
|
|
124704
124863
|
const pct2 = (n4) => `${(n4 * 100).toFixed(0)}%`;
|
|
124705
|
-
console.log(
|
|
124864
|
+
console.log(import_picocolors39.default.bold(`Investigation accuracy \u2014 ${project}`) + import_picocolors39.default.dim(` \xB7 window: ${window2}`));
|
|
124706
124865
|
if (summary.evaluated === 0) {
|
|
124707
124866
|
console.log(
|
|
124708
|
-
|
|
124867
|
+
import_picocolors39.default.dim(
|
|
124709
124868
|
`No outcome labels in this window (${window2}). Confirm an investigation (\`horus memory confirm <id>\`) or leave feedback (\`horus feedback <id> --resolved yes|partly|no\`) to add to the eval set` + (opts.all ? "." : ", or pass --all to include older labels.")
|
|
124710
124869
|
)
|
|
124711
124870
|
);
|
|
124712
124871
|
} else {
|
|
124713
124872
|
console.log(
|
|
124714
|
-
` Pointed at the cause: ${
|
|
124873
|
+
` Pointed at the cause: ${import_picocolors39.default.green(pct2(summary.accuracy))} ` + import_picocolors39.default.dim(`(weighted ${pct2(summary.weightedScore)}) over ${summary.evaluated} investigation(s)`)
|
|
124715
124874
|
);
|
|
124716
124875
|
console.log(
|
|
124717
|
-
` Verdicts: ${
|
|
124876
|
+
` Verdicts: ${import_picocolors39.default.green(`${summary.counts.yes} yes`)}, ${import_picocolors39.default.yellow(`${summary.counts.partly} partly`)}, ${import_picocolors39.default.red(`${summary.counts.no} no`)}`
|
|
124718
124877
|
);
|
|
124719
124878
|
console.log(
|
|
124720
|
-
|
|
124879
|
+
import_picocolors39.default.dim(
|
|
124721
124880
|
` Source: ${summary.bySource.confirm} confirm, ${summary.bySource.feedback} feedback \xB7 ${summary.attestations} total attestation(s)`
|
|
124722
124881
|
)
|
|
124723
124882
|
);
|
|
@@ -124728,14 +124887,14 @@ async function runMemoryAccuracy(opts) {
|
|
|
124728
124887
|
await sql2.end();
|
|
124729
124888
|
}
|
|
124730
124889
|
} catch (err2) {
|
|
124731
|
-
console.error(
|
|
124890
|
+
console.error(import_picocolors39.default.red(err2.message));
|
|
124732
124891
|
return 1;
|
|
124733
124892
|
}
|
|
124734
124893
|
}
|
|
124735
124894
|
|
|
124736
124895
|
// ../../packages/cli/src/commands/simulate.ts
|
|
124737
124896
|
init_cjs_shims();
|
|
124738
|
-
var
|
|
124897
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
124739
124898
|
init_src();
|
|
124740
124899
|
async function runSimulate(scenarioId, opts) {
|
|
124741
124900
|
try {
|
|
@@ -124746,7 +124905,7 @@ async function runSimulate(scenarioId, opts) {
|
|
|
124746
124905
|
const scenario = getScenario(scenarioId);
|
|
124747
124906
|
if (scenario === null) {
|
|
124748
124907
|
console.error(
|
|
124749
|
-
|
|
124908
|
+
import_picocolors40.default.red(
|
|
124750
124909
|
`Unknown scenario: "${scenarioId}". Run horus simulate to list available scenarios.`
|
|
124751
124910
|
)
|
|
124752
124911
|
);
|
|
@@ -124757,14 +124916,14 @@ async function runSimulate(scenarioId, opts) {
|
|
|
124757
124916
|
try {
|
|
124758
124917
|
renv = resolveEnvironment(config2, { project: opts.repo });
|
|
124759
124918
|
} catch (err2) {
|
|
124760
|
-
console.error(
|
|
124919
|
+
console.error(import_picocolors40.default.red(err2.message));
|
|
124761
124920
|
return 1;
|
|
124762
124921
|
}
|
|
124763
124922
|
const code = codeForRepo(config2, renv.project);
|
|
124764
124923
|
const health = await code.health();
|
|
124765
124924
|
if (!health.ok) {
|
|
124766
124925
|
console.error(
|
|
124767
|
-
|
|
124926
|
+
import_picocolors40.default.red("Source-intelligence host unreachable \u2014 run: horus init")
|
|
124768
124927
|
);
|
|
124769
124928
|
return 1;
|
|
124770
124929
|
}
|
|
@@ -124781,14 +124940,14 @@ async function runSimulate(scenarioId, opts) {
|
|
|
124781
124940
|
}
|
|
124782
124941
|
return 0;
|
|
124783
124942
|
} catch (err2) {
|
|
124784
|
-
console.error(
|
|
124943
|
+
console.error(import_picocolors40.default.red(err2.message));
|
|
124785
124944
|
return 1;
|
|
124786
124945
|
}
|
|
124787
124946
|
}
|
|
124788
124947
|
|
|
124789
124948
|
// ../../packages/cli/src/commands/logs.ts
|
|
124790
124949
|
init_cjs_shims();
|
|
124791
|
-
var
|
|
124950
|
+
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
124792
124951
|
init_src();
|
|
124793
124952
|
var LOGS_AI_CONTRACT = `Provide a clearly separated AI evidence narration with:
|
|
124794
124953
|
|
|
@@ -124835,9 +124994,9 @@ function parseWhere(raw) {
|
|
|
124835
124994
|
}
|
|
124836
124995
|
var whereLabel = (where) => where.map((w4) => `${w4.field}=${w4.value}`).join(", ");
|
|
124837
124996
|
function levelColor(level, text2) {
|
|
124838
|
-
if (level === "error" || level === "fatal") return
|
|
124839
|
-
if (level === "warn") return
|
|
124840
|
-
return
|
|
124997
|
+
if (level === "error" || level === "fatal") return import_picocolors41.default.red(text2);
|
|
124998
|
+
if (level === "warn") return import_picocolors41.default.yellow(text2);
|
|
124999
|
+
return import_picocolors41.default.dim(text2);
|
|
124841
125000
|
}
|
|
124842
125001
|
function matchServiceLabel(requested, candidates) {
|
|
124843
125002
|
if (candidates.includes(requested)) return { kind: "unique", matched: requested };
|
|
@@ -124853,7 +125012,7 @@ async function runLogs(service, opts) {
|
|
|
124853
125012
|
try {
|
|
124854
125013
|
where = parseWhere(opts.where);
|
|
124855
125014
|
} catch (err2) {
|
|
124856
|
-
console.error(
|
|
125015
|
+
console.error(import_picocolors41.default.red(err2.message));
|
|
124857
125016
|
return 1;
|
|
124858
125017
|
}
|
|
124859
125018
|
const hasWhere = where.length > 0;
|
|
@@ -124863,13 +125022,13 @@ async function runLogs(service, opts) {
|
|
|
124863
125022
|
try {
|
|
124864
125023
|
renv = resolveEnvironment(config2, { env: opts.env });
|
|
124865
125024
|
} catch (err2) {
|
|
124866
|
-
console.error(
|
|
125025
|
+
console.error(import_picocolors41.default.red(err2.message));
|
|
124867
125026
|
return 1;
|
|
124868
125027
|
}
|
|
124869
125028
|
const logs = logsForEnv(renv);
|
|
124870
125029
|
if (logs === null) {
|
|
124871
125030
|
console.error(
|
|
124872
|
-
|
|
125031
|
+
import_picocolors41.default.red(
|
|
124873
125032
|
`No Elasticsearch connector configured for ${renv.project}/${renv.env} (set ES_URL / ES_USERNAME / ES_PASSWORD)`
|
|
124874
125033
|
)
|
|
124875
125034
|
);
|
|
@@ -124877,7 +125036,7 @@ async function runLogs(service, opts) {
|
|
|
124877
125036
|
}
|
|
124878
125037
|
const health = await logs.health();
|
|
124879
125038
|
if (!health.ok) {
|
|
124880
|
-
console.error(
|
|
125039
|
+
console.error(import_picocolors41.default.red(`Elasticsearch unreachable: ${health.detail}`));
|
|
124881
125040
|
return 1;
|
|
124882
125041
|
}
|
|
124883
125042
|
const resolvedService = service ?? renv.connectors.elasticsearch?.serviceName;
|
|
@@ -124890,21 +125049,21 @@ async function runLogs(service, opts) {
|
|
|
124890
125049
|
requiresEventCode: aggregatesEventCode
|
|
124891
125050
|
});
|
|
124892
125051
|
for (const w4 of compat.issues.filter((i3) => i3.severity === "warning")) {
|
|
124893
|
-
console.warn(
|
|
125052
|
+
console.warn(import_picocolors41.default.yellow(`[warn] ${w4.field}: ${w4.message}`));
|
|
124894
125053
|
}
|
|
124895
125054
|
const errors2 = compat.issues.filter((i3) => i3.severity === "error");
|
|
124896
125055
|
if (errors2.length > 0) {
|
|
124897
|
-
console.error(
|
|
125056
|
+
console.error(import_picocolors41.default.red("Elasticsearch field mapping is incompatible with the index:"));
|
|
124898
125057
|
for (const e of errors2) {
|
|
124899
|
-
console.error(
|
|
125058
|
+
console.error(import_picocolors41.default.red(` ${e.field}: ${e.message}`));
|
|
124900
125059
|
}
|
|
124901
125060
|
console.error(
|
|
124902
|
-
|
|
125061
|
+
import_picocolors41.default.dim("Fix fields.* overrides in your connector config or choose the correct preset.")
|
|
124903
125062
|
);
|
|
124904
125063
|
return 1;
|
|
124905
125064
|
}
|
|
124906
125065
|
} catch {
|
|
124907
|
-
console.warn(
|
|
125066
|
+
console.warn(import_picocolors41.default.dim("[warn] Elasticsearch compatibility check unavailable \u2014 proceeding."));
|
|
124908
125067
|
}
|
|
124909
125068
|
const from = sinceToIso(opts.since) ?? new Date(Date.now() - 7 * 864e5).toISOString();
|
|
124910
125069
|
const fromDisplay = from.slice(0, 16).replace("T", " ");
|
|
@@ -124960,12 +125119,12 @@ async function runLogs(service, opts) {
|
|
|
124960
125119
|
return 0;
|
|
124961
125120
|
}
|
|
124962
125121
|
console.error(
|
|
124963
|
-
|
|
125122
|
+
import_picocolors41.default.dim(
|
|
124964
125123
|
`logs: ${renv.project}/${renv.env}` + (resolvedService ? ` \xB7 service ${resolvedService}` : "") + ` \xB7 from ${fromDisplay} UTC \xB7 level ${rawLevel ?? "all"}` + (hasWhere ? ` \xB7 where ${whereLabel(where)}` : "") + (opts.grep ? ` \xB7 grep "${opts.grep}"` : "") + (rawLevel === "error" && !hasWhere ? " (error+ only \u2014 use --all-levels for info/debug)" : "")
|
|
124965
125124
|
)
|
|
124966
125125
|
);
|
|
124967
125126
|
if (records.length === 0) {
|
|
124968
|
-
console.log(
|
|
125127
|
+
console.log(import_picocolors41.default.dim("No logs matched."));
|
|
124969
125128
|
return 0;
|
|
124970
125129
|
}
|
|
124971
125130
|
for (const r of records) {
|
|
@@ -124975,12 +125134,12 @@ async function runLogs(service, opts) {
|
|
|
124975
125134
|
const line2 = `${ts} ${lvl} ${comp} ${r.message.slice(0, 120)}`;
|
|
124976
125135
|
console.log(levelColor(r.level, line2));
|
|
124977
125136
|
for (const { key, value } of extractContextFields(r)) {
|
|
124978
|
-
console.log(
|
|
125137
|
+
console.log(import_picocolors41.default.dim(` ${key}: ${value.slice(0, 200)}`));
|
|
124979
125138
|
}
|
|
124980
125139
|
}
|
|
124981
125140
|
if (truncated) {
|
|
124982
125141
|
console.error(
|
|
124983
|
-
|
|
125142
|
+
import_picocolors41.default.yellow(
|
|
124984
125143
|
`[warn] showing the first ${limit} record(s) \u2014 results may be truncated. Narrow with --where/--since/--level or raise --limit (max 1000).`
|
|
124985
125144
|
)
|
|
124986
125145
|
);
|
|
@@ -125023,22 +125182,22 @@ async function runLogs(service, opts) {
|
|
|
125023
125182
|
return 0;
|
|
125024
125183
|
}
|
|
125025
125184
|
console.log(
|
|
125026
|
-
|
|
125185
|
+
import_picocolors41.default.bold(`Top ${field}`) + import_picocolors41.default.dim(
|
|
125027
125186
|
` \u2014 ${renv.project}/${renv.env}` + (resolvedService ? ` \xB7 service ${resolvedService}` : "") + (opts.grep ? ` \xB7 grep "${opts.grep}"` : "") + (hasWhere ? ` \xB7 where ${whereLabel(where)}` : "")
|
|
125028
125187
|
)
|
|
125029
125188
|
);
|
|
125030
|
-
console.log(
|
|
125189
|
+
console.log(import_picocolors41.default.dim(` index: ${indexPattern} \xB7 from: ${fromDisplay} UTC \xB7 severity: error+`));
|
|
125031
125190
|
console.log("");
|
|
125032
125191
|
if (buckets.length === 0) {
|
|
125033
|
-
console.log(
|
|
125034
|
-
console.log(
|
|
125192
|
+
console.log(import_picocolors41.default.dim(` No error logs with field "${field}" in the window.`));
|
|
125193
|
+
console.log(import_picocolors41.default.dim(` Tip: ensure "${field}" is an aggregatable (keyword) field.`));
|
|
125035
125194
|
return 0;
|
|
125036
125195
|
}
|
|
125037
125196
|
for (const b5 of buckets) {
|
|
125038
|
-
console.log(` ${
|
|
125197
|
+
console.log(` ${import_picocolors41.default.red(String(b5.count).padStart(6))} ${b5.key}`);
|
|
125039
125198
|
}
|
|
125040
125199
|
console.log("");
|
|
125041
|
-
console.log(
|
|
125200
|
+
console.log(import_picocolors41.default.dim(` ${buckets.length} distinct ${field} value(s) shown (top by error count).`));
|
|
125042
125201
|
return 0;
|
|
125043
125202
|
}
|
|
125044
125203
|
let analysis = await logs.analyzeErrors({
|
|
@@ -125108,46 +125267,50 @@ async function runLogs(service, opts) {
|
|
|
125108
125267
|
return 0;
|
|
125109
125268
|
}
|
|
125110
125269
|
console.log(
|
|
125111
|
-
|
|
125270
|
+
import_picocolors41.default.bold(`Error analysis`) + import_picocolors41.default.dim(
|
|
125112
125271
|
` \u2014 ${renv.project}/${renv.env}` + (scopeService ? ` \xB7 service ${scopeService}` : "") + (opts.grep ? ` \xB7 grep "${opts.grep}"` : "") + (hasWhere ? ` \xB7 where ${whereLabel(where)}` : "")
|
|
125113
125272
|
)
|
|
125114
125273
|
);
|
|
125115
|
-
console.log(
|
|
125274
|
+
console.log(import_picocolors41.default.dim(` index: ${indexPattern} \xB7 from: ${fromDisplay} UTC \xB7 severity: error+`));
|
|
125116
125275
|
if (broadeningNote) {
|
|
125117
|
-
console.log(
|
|
125276
|
+
console.log(import_picocolors41.default.yellow(` ${broadeningNote}`));
|
|
125118
125277
|
}
|
|
125119
125278
|
console.log(
|
|
125120
|
-
` ${analysis.totalErrors} error(s) \xB7 ${analysis.signatures.length} signature(s) \xB7 ${
|
|
125279
|
+
` ${analysis.totalErrors} error(s) \xB7 ${analysis.signatures.length} signature(s) \xB7 ${import_picocolors41.default.yellow(String(analysis.newSignatures.length))} new`
|
|
125121
125280
|
);
|
|
125122
125281
|
console.log("");
|
|
125123
125282
|
if (analysis.signatures.length === 0) {
|
|
125124
|
-
console.log(import_picocolors39.default.dim(" No error-level logs in the window."));
|
|
125125
125283
|
console.log(
|
|
125126
|
-
|
|
125284
|
+
import_picocolors41.default.dim(
|
|
125285
|
+
analysis.totalErrors > 0 ? ` ${analysis.totalErrors} error-level log(s) matched, but none could be grouped into a signature (missing the code field). Try --raw to see the lines.` : " No error-level logs in the window."
|
|
125286
|
+
)
|
|
125287
|
+
);
|
|
125288
|
+
console.log(
|
|
125289
|
+
import_picocolors41.default.dim(
|
|
125127
125290
|
` Searched: ${scopeService ? `service "${scopeService}"` : "all services"} \xB7 index: ${indexPattern} \xB7 from: ${fromDisplay} UTC`
|
|
125128
125291
|
)
|
|
125129
125292
|
);
|
|
125130
|
-
console.log(
|
|
125293
|
+
console.log(import_picocolors41.default.dim(` Tip: use --since to widen the window (e.g. --since 30d).`));
|
|
125131
125294
|
return 0;
|
|
125132
125295
|
}
|
|
125133
125296
|
for (const s5 of analysis.signatures) {
|
|
125134
125297
|
const tags = [];
|
|
125135
|
-
if (s5.isNew) tags.push(
|
|
125298
|
+
if (s5.isNew) tags.push(import_picocolors41.default.red("NEW"));
|
|
125136
125299
|
else if (s5.ratio !== void 0 && Number.isFinite(s5.ratio) && s5.ratio >= 1.5) {
|
|
125137
|
-
tags.push(
|
|
125300
|
+
tags.push(import_picocolors41.default.yellow(`spike x${s5.ratio.toFixed(1)}`));
|
|
125138
125301
|
}
|
|
125139
|
-
const svc = s5.services.length > 0 ?
|
|
125302
|
+
const svc = s5.services.length > 0 ? import_picocolors41.default.dim(` \xB7 ${s5.services.slice(0, 3).join(", ")}`) : "";
|
|
125140
125303
|
const tagStr = tags.length > 0 ? ` [${tags.join(", ")}]` : "";
|
|
125141
125304
|
console.log(
|
|
125142
|
-
` ${
|
|
125305
|
+
` ${import_picocolors41.default.red(String(s5.count).padStart(6))} ${import_picocolors41.default.bold(s5.key.padEnd(14).slice(0, 14))} ` + import_picocolors41.default.dim(`first ${shortTs(s5.firstSeen)} \xB7 last ${shortTs(s5.lastSeen)}`) + svc + tagStr
|
|
125143
125306
|
);
|
|
125144
125307
|
}
|
|
125145
125308
|
if (analysis.affectedServices.length > 0) {
|
|
125146
125309
|
console.log("");
|
|
125147
|
-
console.log(` ${
|
|
125310
|
+
console.log(` ${import_picocolors41.default.bold("Affected services:")} ${analysis.affectedServices.join(", ")}`);
|
|
125148
125311
|
}
|
|
125149
125312
|
console.log("");
|
|
125150
|
-
console.log(
|
|
125313
|
+
console.log(import_picocolors41.default.dim(" (use --raw to see individual log lines)"));
|
|
125151
125314
|
if (opts.ai) {
|
|
125152
125315
|
const result = await renderAiInterpretation({
|
|
125153
125316
|
command: "logs",
|
|
@@ -125166,19 +125329,19 @@ async function runLogs(service, opts) {
|
|
|
125166
125329
|
});
|
|
125167
125330
|
console.log("\n" + renderInterpretation(result));
|
|
125168
125331
|
if (!result.ok) {
|
|
125169
|
-
console.error(
|
|
125332
|
+
console.error(import_picocolors41.default.yellow(`[ai] ${result.warning}`));
|
|
125170
125333
|
}
|
|
125171
125334
|
}
|
|
125172
125335
|
return 0;
|
|
125173
125336
|
} catch (err2) {
|
|
125174
|
-
console.error(
|
|
125337
|
+
console.error(import_picocolors41.default.red(err2.message));
|
|
125175
125338
|
return 1;
|
|
125176
125339
|
}
|
|
125177
125340
|
}
|
|
125178
125341
|
|
|
125179
125342
|
// ../../packages/cli/src/commands/metrics.ts
|
|
125180
125343
|
init_cjs_shims();
|
|
125181
|
-
var
|
|
125344
|
+
var import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
125182
125345
|
init_src();
|
|
125183
125346
|
var METRICS_AI_CONTRACT = `Provide a clearly separated AI evidence narration with:
|
|
125184
125347
|
|
|
@@ -125224,10 +125387,10 @@ function anomalyColor(anomaly) {
|
|
|
125224
125387
|
case "latency-spike":
|
|
125225
125388
|
case "error-rate-change":
|
|
125226
125389
|
case "throughput-drop":
|
|
125227
|
-
return
|
|
125390
|
+
return import_picocolors42.default.red;
|
|
125228
125391
|
case "queue-growth":
|
|
125229
125392
|
case "change":
|
|
125230
|
-
return
|
|
125393
|
+
return import_picocolors42.default.yellow;
|
|
125231
125394
|
default:
|
|
125232
125395
|
return (s5) => s5;
|
|
125233
125396
|
}
|
|
@@ -125256,7 +125419,7 @@ async function runMetrics(hint, opts) {
|
|
|
125256
125419
|
const metrics = metricsProviderFromConfig(config2);
|
|
125257
125420
|
if (metrics === null) {
|
|
125258
125421
|
console.error(
|
|
125259
|
-
|
|
125422
|
+
import_picocolors42.default.red(
|
|
125260
125423
|
"Grafana not configured \u2014 set GRAFANA_URL + GRAFANA_USER + GRAFANA_PASSWORD"
|
|
125261
125424
|
)
|
|
125262
125425
|
);
|
|
@@ -125264,7 +125427,7 @@ async function runMetrics(hint, opts) {
|
|
|
125264
125427
|
}
|
|
125265
125428
|
const health = await metrics.health();
|
|
125266
125429
|
if (!health.ok) {
|
|
125267
|
-
console.error(
|
|
125430
|
+
console.error(import_picocolors42.default.red(`Grafana unreachable: ${health.detail}`));
|
|
125268
125431
|
return 1;
|
|
125269
125432
|
}
|
|
125270
125433
|
const stepNum = opts.step !== void 0 ? Number(opts.step) : void 0;
|
|
@@ -125293,14 +125456,14 @@ async function runMetrics(hint, opts) {
|
|
|
125293
125456
|
return 0;
|
|
125294
125457
|
}
|
|
125295
125458
|
if (series.length === 0) {
|
|
125296
|
-
console.log(
|
|
125459
|
+
console.log(import_picocolors42.default.dim("No series returned."));
|
|
125297
125460
|
return 0;
|
|
125298
125461
|
}
|
|
125299
125462
|
for (const s5 of series) {
|
|
125300
125463
|
const summary = summarize(s5);
|
|
125301
125464
|
const label = labelStr(s5.labels);
|
|
125302
125465
|
console.log(
|
|
125303
|
-
` ${
|
|
125466
|
+
` ${import_picocolors42.default.cyan(label || "(no labels)")} last=${import_picocolors42.default.bold(fmtNum(summary.last))} avg=${fmtNum(summary.avg)}`
|
|
125304
125467
|
);
|
|
125305
125468
|
}
|
|
125306
125469
|
return 0;
|
|
@@ -125315,36 +125478,36 @@ async function runMetrics(hint, opts) {
|
|
|
125315
125478
|
if (findings2.length === 0) {
|
|
125316
125479
|
if (hint !== void 0) {
|
|
125317
125480
|
const tokens = extractHintTokens(hint);
|
|
125318
|
-
console.log(
|
|
125481
|
+
console.log(import_picocolors42.default.dim(`No panels matched hint "${hint}".`));
|
|
125319
125482
|
if (tokens.length > 0) {
|
|
125320
|
-
console.log(
|
|
125483
|
+
console.log(import_picocolors42.default.dim(` Searched for panels containing: ${tokens.join(", ")}`));
|
|
125321
125484
|
}
|
|
125322
125485
|
console.log(
|
|
125323
|
-
|
|
125324
|
-
` Tip: run ${
|
|
125486
|
+
import_picocolors42.default.dim(
|
|
125487
|
+
` Tip: run ${import_picocolors42.default.bold("horus metrics")} (no hint) to see all available panels, then use a panel title or keyword directly.`
|
|
125325
125488
|
)
|
|
125326
125489
|
);
|
|
125327
125490
|
} else {
|
|
125328
|
-
console.log(
|
|
125491
|
+
console.log(import_picocolors42.default.dim("No panels found in configured Grafana dashboards."));
|
|
125329
125492
|
}
|
|
125330
125493
|
return 0;
|
|
125331
125494
|
}
|
|
125332
125495
|
const hintSuffix = hint !== void 0 ? ` (hint: "${hint}")` : "";
|
|
125333
125496
|
const matchSources = hint !== void 0 ? [...new Set(findings2.map((f5) => f5.matchSource).filter(Boolean))] : [];
|
|
125334
|
-
const matchSuffix = matchSources.length > 0 ?
|
|
125497
|
+
const matchSuffix = matchSources.length > 0 ? import_picocolors42.default.dim(` [matched via ${matchSources.join(", ")}]`) : "";
|
|
125335
125498
|
console.log(
|
|
125336
|
-
|
|
125499
|
+
import_picocolors42.default.bold(
|
|
125337
125500
|
`Grafana metrics${hintSuffix} \u2014 ${findings2.length} series across panels`
|
|
125338
125501
|
) + matchSuffix
|
|
125339
125502
|
);
|
|
125340
125503
|
console.log(
|
|
125341
|
-
|
|
125504
|
+
import_picocolors42.default.dim(
|
|
125342
125505
|
` window: ${new Date(from * 1e3).toISOString()} \u2013 ${new Date(to * 1e3).toISOString()}`
|
|
125343
125506
|
)
|
|
125344
125507
|
);
|
|
125345
125508
|
console.log("");
|
|
125346
125509
|
if (flagged.length === 0) {
|
|
125347
|
-
console.log(
|
|
125510
|
+
console.log(import_picocolors42.default.green(" No anomalies detected."));
|
|
125348
125511
|
} else {
|
|
125349
125512
|
for (const f5 of flagged) {
|
|
125350
125513
|
const color = anomalyColor(f5.anomaly);
|
|
@@ -125353,14 +125516,14 @@ async function runMetrics(hint, opts) {
|
|
|
125353
125516
|
const lblStr = labelStr(f5.labels);
|
|
125354
125517
|
console.log(
|
|
125355
125518
|
color(
|
|
125356
|
-
` ${label.padEnd(22)} ${f5.panelTitle.padEnd(40).slice(0, 40)} ${fmtNum(f5.baselineAvg)} -> ${fmtNum(f5.currentAvg)} (${ratioStr})` + (lblStr !== "" ? ` ${
|
|
125519
|
+
` ${label.padEnd(22)} ${f5.panelTitle.padEnd(40).slice(0, 40)} ${fmtNum(f5.baselineAvg)} -> ${fmtNum(f5.currentAvg)} (${ratioStr})` + (lblStr !== "" ? ` ${import_picocolors42.default.dim(lblStr)}` : "")
|
|
125357
125520
|
)
|
|
125358
125521
|
);
|
|
125359
125522
|
}
|
|
125360
125523
|
}
|
|
125361
125524
|
if (ok.length > 0) {
|
|
125362
125525
|
console.log("");
|
|
125363
|
-
console.log(
|
|
125526
|
+
console.log(import_picocolors42.default.dim(` ${ok.length} panel series with no anomaly.`));
|
|
125364
125527
|
}
|
|
125365
125528
|
if (opts.ai) {
|
|
125366
125529
|
const result = await renderAiInterpretation({
|
|
@@ -125375,19 +125538,19 @@ async function runMetrics(hint, opts) {
|
|
|
125375
125538
|
});
|
|
125376
125539
|
console.log("\n" + renderInterpretation(result));
|
|
125377
125540
|
if (!result.ok) {
|
|
125378
|
-
console.error(
|
|
125541
|
+
console.error(import_picocolors42.default.yellow(`[ai] ${result.warning}`));
|
|
125379
125542
|
}
|
|
125380
125543
|
}
|
|
125381
125544
|
return 0;
|
|
125382
125545
|
} catch (err2) {
|
|
125383
|
-
console.error(
|
|
125546
|
+
console.error(import_picocolors42.default.red(err2.message));
|
|
125384
125547
|
return 1;
|
|
125385
125548
|
}
|
|
125386
125549
|
}
|
|
125387
125550
|
|
|
125388
125551
|
// ../../packages/cli/src/commands/state.ts
|
|
125389
125552
|
init_cjs_shims();
|
|
125390
|
-
var
|
|
125553
|
+
var import_picocolors43 = __toESM(require_picocolors(), 1);
|
|
125391
125554
|
init_src();
|
|
125392
125555
|
var STATE_AI_CONTRACT = `Provide a clearly separated AI evidence narration with:
|
|
125393
125556
|
|
|
@@ -125414,13 +125577,13 @@ async function runState(opts) {
|
|
|
125414
125577
|
try {
|
|
125415
125578
|
renv = resolveEnvironment(config2, { env: opts.env });
|
|
125416
125579
|
} catch (err2) {
|
|
125417
|
-
console.error(
|
|
125580
|
+
console.error(import_picocolors43.default.red(err2.message));
|
|
125418
125581
|
return 1;
|
|
125419
125582
|
}
|
|
125420
125583
|
const mongo = mongoForEnv(renv);
|
|
125421
125584
|
if (mongo === null) {
|
|
125422
125585
|
console.error(
|
|
125423
|
-
|
|
125586
|
+
import_picocolors43.default.red(
|
|
125424
125587
|
`No MongoDB connector configured for ${renv.project}/${renv.env} (set the project's Mongo URL env var).`
|
|
125425
125588
|
)
|
|
125426
125589
|
);
|
|
@@ -125428,7 +125591,7 @@ async function runState(opts) {
|
|
|
125428
125591
|
}
|
|
125429
125592
|
const health = await mongo.health();
|
|
125430
125593
|
if (!health.ok) {
|
|
125431
|
-
console.error(
|
|
125594
|
+
console.error(import_picocolors43.default.red(`MongoDB unreachable: ${health.detail}`));
|
|
125432
125595
|
await mongo.close();
|
|
125433
125596
|
return 1;
|
|
125434
125597
|
}
|
|
@@ -125454,38 +125617,38 @@ async function runState(opts) {
|
|
|
125454
125617
|
);
|
|
125455
125618
|
return 0;
|
|
125456
125619
|
}
|
|
125457
|
-
const discoveryNote = analysis.autoDiscovered ?
|
|
125620
|
+
const discoveryNote = analysis.autoDiscovered ? import_picocolors43.default.dim(` (${analysis.collections.length} collections, auto-discovered)`) : "";
|
|
125458
125621
|
console.log(
|
|
125459
|
-
|
|
125622
|
+
import_picocolors43.default.bold("State analysis") + import_picocolors43.default.dim(` \u2014 ${renv.project}/${renv.env} \xB7 db ${analysis.database}`) + discoveryNote
|
|
125460
125623
|
);
|
|
125461
125624
|
console.log("");
|
|
125462
125625
|
let signals = 0;
|
|
125463
125626
|
for (const c4 of analysis.collections) {
|
|
125464
125627
|
const flags2 = [];
|
|
125465
125628
|
if (c4.isStale === true) {
|
|
125466
|
-
flags2.push(
|
|
125629
|
+
flags2.push(import_picocolors43.default.yellow(`stale (last ${c4.dateField}, ~${Math.round(c4.ageHours ?? 0)}h)`));
|
|
125467
125630
|
}
|
|
125468
125631
|
for (const a2 of c4.anomalies) {
|
|
125469
|
-
flags2.push(
|
|
125632
|
+
flags2.push(import_picocolors43.default.red(`${a2.count}\xD7 "${a2.value}"`));
|
|
125470
125633
|
signals += 1;
|
|
125471
125634
|
}
|
|
125472
125635
|
if (c4.isStale === true) signals += 1;
|
|
125473
|
-
const head = ` ${
|
|
125474
|
-
console.log(flags2.length > 0 ? `${head} ${flags2.join(" ")}` :
|
|
125636
|
+
const head = ` ${import_picocolors43.default.bold(c4.collection.padEnd(18).slice(0, 18))} ${import_picocolors43.default.dim(String(c4.count).padStart(8) + " docs")}`;
|
|
125637
|
+
console.log(flags2.length > 0 ? `${head} ${flags2.join(" ")}` : import_picocolors43.default.dim(head));
|
|
125475
125638
|
}
|
|
125476
125639
|
console.log("");
|
|
125477
125640
|
if (analysis.collections.length === 0) {
|
|
125478
125641
|
console.log(
|
|
125479
|
-
|
|
125642
|
+
import_picocolors43.default.yellow(" No collections discovered in this database.") + import_picocolors43.default.dim(" Verify the database name in your MongoDB connector config.")
|
|
125480
125643
|
);
|
|
125481
125644
|
} else {
|
|
125482
125645
|
const scope = analysis.autoDiscovered ? "collection(s)" : "allowlisted collection(s)";
|
|
125483
125646
|
console.log(
|
|
125484
|
-
signals > 0 ? ` ${
|
|
125647
|
+
signals > 0 ? ` ${import_picocolors43.default.bold(String(signals))} state signal(s) across ${analysis.collections.length} ${scope}` : import_picocolors43.default.dim(` No state anomalies across ${analysis.collections.length} ${scope}.`)
|
|
125485
125648
|
);
|
|
125486
125649
|
if (analysis.autoDiscovered) {
|
|
125487
125650
|
console.log(
|
|
125488
|
-
|
|
125651
|
+
import_picocolors43.default.dim(
|
|
125489
125652
|
` Tip: add a "collections" list to your MongoDB connector config to restrict analysis.`
|
|
125490
125653
|
)
|
|
125491
125654
|
);
|
|
@@ -125503,7 +125666,7 @@ async function runState(opts) {
|
|
|
125503
125666
|
});
|
|
125504
125667
|
console.log("\n" + renderInterpretation(result));
|
|
125505
125668
|
if (!result.ok) {
|
|
125506
|
-
console.error(
|
|
125669
|
+
console.error(import_picocolors43.default.yellow(`[ai] ${result.warning}`));
|
|
125507
125670
|
}
|
|
125508
125671
|
}
|
|
125509
125672
|
return 0;
|
|
@@ -125511,20 +125674,20 @@ async function runState(opts) {
|
|
|
125511
125674
|
await mongo.close();
|
|
125512
125675
|
}
|
|
125513
125676
|
} catch (err2) {
|
|
125514
|
-
console.error(
|
|
125677
|
+
console.error(import_picocolors43.default.red(err2.message));
|
|
125515
125678
|
return 1;
|
|
125516
125679
|
}
|
|
125517
125680
|
}
|
|
125518
125681
|
|
|
125519
125682
|
// ../../packages/cli/src/commands/init.ts
|
|
125520
125683
|
init_cjs_shims();
|
|
125521
|
-
var
|
|
125684
|
+
var import_picocolors46 = __toESM(require_picocolors(), 1);
|
|
125522
125685
|
var import_node_path27 = require("path");
|
|
125523
125686
|
init_src();
|
|
125524
125687
|
|
|
125525
125688
|
// ../../packages/cli/src/commands/init-prereqs.ts
|
|
125526
125689
|
init_cjs_shims();
|
|
125527
|
-
var
|
|
125690
|
+
var import_picocolors44 = __toESM(require_picocolors(), 1);
|
|
125528
125691
|
init_src();
|
|
125529
125692
|
async function checkPrerequisites(opts = {}) {
|
|
125530
125693
|
const write = opts.write ?? ((line2) => console.log(line2));
|
|
@@ -125538,9 +125701,9 @@ async function checkPrerequisites(opts = {}) {
|
|
|
125538
125701
|
} catch {
|
|
125539
125702
|
}
|
|
125540
125703
|
if (backendVersion === null) {
|
|
125541
|
-
write(` ${
|
|
125704
|
+
write(` ${import_picocolors44.default.red("\u25CF")} Horus source-intelligence backend not found`);
|
|
125542
125705
|
write(
|
|
125543
|
-
|
|
125706
|
+
import_picocolors44.default.dim(
|
|
125544
125707
|
` install it (Python 3.11+ required):
|
|
125545
125708
|
curl -fsSL https://horus.sh/install.sh | bash
|
|
125546
125709
|
ensure ~/.local/bin is on your PATH`
|
|
@@ -125549,10 +125712,10 @@ async function checkPrerequisites(opts = {}) {
|
|
|
125549
125712
|
} else if (SOURCE_PIN_ENFORCED && backendVersion !== PINNED_SOURCE_VERSION) {
|
|
125550
125713
|
status.backendPresent = true;
|
|
125551
125714
|
write(
|
|
125552
|
-
` ${
|
|
125715
|
+
` ${import_picocolors44.default.yellow("\u25CF")} Horus source-intelligence backend version mismatch` + import_picocolors44.default.dim(` (installed: ${backendVersion}, required: ${PINNED_SOURCE_VERSION})`)
|
|
125553
125716
|
);
|
|
125554
125717
|
write(
|
|
125555
|
-
|
|
125718
|
+
import_picocolors44.default.dim(
|
|
125556
125719
|
` update it:
|
|
125557
125720
|
horus update`
|
|
125558
125721
|
)
|
|
@@ -125561,7 +125724,7 @@ async function checkPrerequisites(opts = {}) {
|
|
|
125561
125724
|
status.backendPresent = true;
|
|
125562
125725
|
status.backendVersionOk = true;
|
|
125563
125726
|
write(
|
|
125564
|
-
` ${
|
|
125727
|
+
` ${import_picocolors44.default.green("\u25CF")} Horus source-intelligence backend ` + import_picocolors44.default.dim(`(${backendVersion})`)
|
|
125565
125728
|
);
|
|
125566
125729
|
}
|
|
125567
125730
|
return status;
|
|
@@ -125571,7 +125734,7 @@ async function checkPrerequisites(opts = {}) {
|
|
|
125571
125734
|
init_cjs_shims();
|
|
125572
125735
|
var import_node_fs24 = require("fs");
|
|
125573
125736
|
var import_node_path26 = require("path");
|
|
125574
|
-
var
|
|
125737
|
+
var import_picocolors45 = __toESM(require_picocolors(), 1);
|
|
125575
125738
|
init_src();
|
|
125576
125739
|
|
|
125577
125740
|
// ../../packages/stitcher/src/index.ts
|
|
@@ -125692,27 +125855,27 @@ function extractQueueGraph(input) {
|
|
|
125692
125855
|
}
|
|
125693
125856
|
}
|
|
125694
125857
|
const producers = [];
|
|
125695
|
-
for (const
|
|
125696
|
-
const loopVarEnums = loopVarEnumsFor(
|
|
125697
|
-
for (const m5 of
|
|
125858
|
+
for (const pc66 of input.producerClasses) {
|
|
125859
|
+
const loopVarEnums = loopVarEnumsFor(pc66.content);
|
|
125860
|
+
for (const m5 of pc66.content.matchAll(INJECT_QUEUE_RE)) {
|
|
125698
125861
|
const queue = m5[1] ?? "";
|
|
125699
|
-
if (queue) producers.push({ queue, symbol:
|
|
125862
|
+
if (queue) producers.push({ queue, symbol: pc66.name, file: pc66.filePath });
|
|
125700
125863
|
}
|
|
125701
|
-
for (const m5 of
|
|
125864
|
+
for (const m5 of pc66.content.matchAll(NEW_BULL_RE)) {
|
|
125702
125865
|
if (m5[2] !== "Queue") continue;
|
|
125703
125866
|
const queues2 = resolveArg(m5[3] ?? "", constMap, enums, loopVarEnums);
|
|
125704
125867
|
for (const queue of queues2) {
|
|
125705
125868
|
producers.push({
|
|
125706
125869
|
queue,
|
|
125707
|
-
symbol: (m5[1] ??
|
|
125708
|
-
file:
|
|
125870
|
+
symbol: (m5[1] ?? pc66.name) || baseName(pc66.filePath),
|
|
125871
|
+
file: pc66.filePath
|
|
125709
125872
|
});
|
|
125710
125873
|
}
|
|
125711
125874
|
}
|
|
125712
|
-
for (const m5 of
|
|
125875
|
+
for (const m5 of pc66.content.matchAll(QUEUE_NAME_CONST_RE)) {
|
|
125713
125876
|
const ident = m5[1] ?? "";
|
|
125714
125877
|
const queue = m5[2] ?? "";
|
|
125715
|
-
if (queue) producers.push({ queue, symbol: ident || baseName(
|
|
125878
|
+
if (queue) producers.push({ queue, symbol: ident || baseName(pc66.filePath), file: pc66.filePath });
|
|
125716
125879
|
}
|
|
125717
125880
|
}
|
|
125718
125881
|
const workers = [];
|
|
@@ -126032,11 +126195,11 @@ async function stitchQueueMap(hostUrl, label) {
|
|
|
126032
126195
|
try {
|
|
126033
126196
|
const summary = await stitch(source, db, { project: label });
|
|
126034
126197
|
console.log(
|
|
126035
|
-
|
|
126198
|
+
import_picocolors45.default.dim(`[${label}] `) + `Stitched ${summary.edges} queue edge(s) across ${summary.queues} queue(s) \u2014 ${summary.producers} producer(s), ${summary.workers} worker(s).`
|
|
126036
126199
|
);
|
|
126037
126200
|
} catch (err2) {
|
|
126038
126201
|
console.log(
|
|
126039
|
-
|
|
126202
|
+
import_picocolors45.default.dim(`[${label}] `) + `Queue map skipped (degraded): ${err2.message}. Stitched 0 queue edge(s).`
|
|
126040
126203
|
);
|
|
126041
126204
|
} finally {
|
|
126042
126205
|
await sql2.end();
|
|
@@ -126118,8 +126281,8 @@ async function buildKnowledgeIndex(root, config2, label, configuredProject, opts
|
|
|
126118
126281
|
if (opts.importKb) {
|
|
126119
126282
|
const res = importKnowledgeBaseFile((0, import_node_path26.resolve)(opts.importKb), { root, project: label });
|
|
126120
126283
|
const total = res.manifest ? Object.values(res.manifest.counts).reduce((a2, b5) => a2 + b5, 0) : 0;
|
|
126121
|
-
console.log(
|
|
126122
|
-
if (res.warnings.length) console.log(
|
|
126284
|
+
console.log(import_picocolors45.default.dim(` project knowledge: imported ${total} item(s) from ${opts.importKb}`));
|
|
126285
|
+
if (res.warnings.length) console.log(import_picocolors45.default.dim(` (${res.warnings.length} import warning(s))`));
|
|
126123
126286
|
return;
|
|
126124
126287
|
}
|
|
126125
126288
|
const changedMode = opts.changed === true && opts.full !== true;
|
|
@@ -126127,7 +126290,7 @@ async function buildKnowledgeIndex(root, config2, label, configuredProject, opts
|
|
|
126127
126290
|
const changes = collectLocalChanges({ cwd: root });
|
|
126128
126291
|
const n4 = changes.kind === "local-changes" ? changes.changedFiles.length : 0;
|
|
126129
126292
|
console.log(
|
|
126130
|
-
|
|
126293
|
+
import_picocolors45.default.dim(
|
|
126131
126294
|
` project knowledge: fast refresh (${n4} changed file(s)) \u2014 the source graph is NOT reanalyzed (use \`horus init --reindex\` for that)`
|
|
126132
126295
|
)
|
|
126133
126296
|
);
|
|
@@ -126162,10 +126325,10 @@ async function buildKnowledgeIndex(root, config2, label, configuredProject, opts
|
|
|
126162
126325
|
snapshot.dataFlows.length ? `${snapshot.dataFlows.length} flow(s)` : null
|
|
126163
126326
|
].filter(Boolean);
|
|
126164
126327
|
console.log(
|
|
126165
|
-
|
|
126328
|
+
import_picocolors45.default.dim(` project knowledge: ${counts.join(", ")} \u2192 .horus/index/`)
|
|
126166
126329
|
);
|
|
126167
126330
|
} catch (err2) {
|
|
126168
|
-
console.log(
|
|
126331
|
+
console.log(import_picocolors45.default.dim(` project knowledge skipped: ${err2.message}`));
|
|
126169
126332
|
}
|
|
126170
126333
|
}
|
|
126171
126334
|
async function runIndex(opts) {
|
|
@@ -126195,7 +126358,7 @@ async function runIndex(opts) {
|
|
|
126195
126358
|
let spawned = false;
|
|
126196
126359
|
let driftedHost;
|
|
126197
126360
|
if (opts.reindex === true) {
|
|
126198
|
-
console.log(
|
|
126361
|
+
console.log(import_picocolors45.default.dim(" --reindex: stopping the host and removing .horus/source for a full re-analysis\u2026"));
|
|
126199
126362
|
await killSpawnedHost(root);
|
|
126200
126363
|
(0, import_node_fs24.rmSync)((0, import_node_path26.join)(root, ".horus", "source"), { recursive: true, force: true });
|
|
126201
126364
|
}
|
|
@@ -126212,51 +126375,51 @@ async function runIndex(opts) {
|
|
|
126212
126375
|
}
|
|
126213
126376
|
if (!hostUrl && driftedHost) {
|
|
126214
126377
|
console.log(
|
|
126215
|
-
|
|
126378
|
+
import_picocolors45.default.yellow(
|
|
126216
126379
|
`Host at ${driftedHost.url} runs backend v${driftedHost.version} (pinned ${PINNED_SOURCE_VERSION}) \u2014 restarting it with the pinned backend`
|
|
126217
126380
|
)
|
|
126218
126381
|
);
|
|
126219
126382
|
await killSpawnedHost(root);
|
|
126220
126383
|
}
|
|
126221
126384
|
if (hostUrl) {
|
|
126222
|
-
console.log(
|
|
126385
|
+
console.log(import_picocolors45.default.dim(`Reusing source-intelligence host for ${label} at ${hostUrl}`));
|
|
126223
126386
|
} else {
|
|
126224
126387
|
spawned = true;
|
|
126225
|
-
console.log(
|
|
126388
|
+
console.log(import_picocolors45.default.bold(`Indexing ${label}`) + import_picocolors45.default.dim(` (${root})`));
|
|
126226
126389
|
if (!await sourceAvailable()) {
|
|
126227
|
-
console.error(
|
|
126390
|
+
console.error(import_picocolors45.default.red("horus-source not found on PATH. Install it: curl -fsSL https://horus.sh/install.sh | bash"));
|
|
126228
126391
|
return 1;
|
|
126229
126392
|
}
|
|
126230
126393
|
try {
|
|
126231
126394
|
await assertSourceVersionPinned();
|
|
126232
126395
|
} catch (err2) {
|
|
126233
|
-
console.error(
|
|
126396
|
+
console.error(import_picocolors45.default.red(` ${err2.message}`));
|
|
126234
126397
|
return 1;
|
|
126235
126398
|
}
|
|
126236
126399
|
const staleReason = isAnalyzed(root) ? indexNeedsReanalyze(root) : null;
|
|
126237
126400
|
if (!isAnalyzed(root) || staleReason) {
|
|
126238
126401
|
console.log(
|
|
126239
|
-
|
|
126402
|
+
import_picocolors45.default.dim(
|
|
126240
126403
|
staleReason ? ` existing index is stale (${staleReason}) \u2014 re-analyzing with source-intelligence backend\u2026` : " analyzing with source-intelligence backend (first time \u2014 this can take a while)\u2026"
|
|
126241
126404
|
)
|
|
126242
126405
|
);
|
|
126243
126406
|
try {
|
|
126244
126407
|
await analyzeRepo(root);
|
|
126245
126408
|
} catch (err2) {
|
|
126246
|
-
console.error(
|
|
126409
|
+
console.error(import_picocolors45.default.red(` source analysis failed: ${err2.message}`));
|
|
126247
126410
|
return 1;
|
|
126248
126411
|
}
|
|
126249
126412
|
const incomplete = isAnalyzed(root) ? indexNeedsReanalyze(root) : "no index was produced";
|
|
126250
126413
|
if (incomplete) {
|
|
126251
126414
|
console.error(
|
|
126252
|
-
|
|
126415
|
+
import_picocolors45.default.red(
|
|
126253
126416
|
` source analysis did not finish (${incomplete}) \u2014 the structural index is missing or broken. Re-run \`horus init\` to rebuild it.`
|
|
126254
126417
|
)
|
|
126255
126418
|
);
|
|
126256
126419
|
return 1;
|
|
126257
126420
|
}
|
|
126258
126421
|
} else {
|
|
126259
|
-
console.log(
|
|
126422
|
+
console.log(import_picocolors45.default.dim(" already analyzed"));
|
|
126260
126423
|
}
|
|
126261
126424
|
const priorPort = parseHostPort(configuredHost ?? "") ?? parseHostPort(readSourceHostUrl(root) ?? "");
|
|
126262
126425
|
await killSpawnedHost(root);
|
|
@@ -126275,7 +126438,7 @@ async function runIndex(opts) {
|
|
|
126275
126438
|
}
|
|
126276
126439
|
hostUrl = `http://127.0.0.1:${port}`;
|
|
126277
126440
|
console.log(
|
|
126278
|
-
|
|
126441
|
+
import_picocolors45.default.dim(
|
|
126279
126442
|
attempt === 0 ? ` starting source-intelligence host on port ${port}\u2026` : ` port contended \u2014 retrying on ${port}\u2026`
|
|
126280
126443
|
)
|
|
126281
126444
|
);
|
|
@@ -126291,7 +126454,7 @@ async function runIndex(opts) {
|
|
|
126291
126454
|
}
|
|
126292
126455
|
if (!started) {
|
|
126293
126456
|
console.error(
|
|
126294
|
-
|
|
126457
|
+
import_picocolors45.default.red(` Source-intelligence host did not become healthy \u2014 see ${root}/.horus/source-host.log`)
|
|
126295
126458
|
);
|
|
126296
126459
|
return 1;
|
|
126297
126460
|
}
|
|
@@ -126299,20 +126462,20 @@ async function runIndex(opts) {
|
|
|
126299
126462
|
if (!hostUrl) return 1;
|
|
126300
126463
|
if (!await hostServesRepo(hostUrl, root)) {
|
|
126301
126464
|
console.error(
|
|
126302
|
-
|
|
126465
|
+
import_picocolors45.default.red(
|
|
126303
126466
|
` Source-intelligence host at ${hostUrl} is serving a DIFFERENT repository \u2014 refusing to index foreign code. Retry, or stop the stale host: horus stop`
|
|
126304
126467
|
)
|
|
126305
126468
|
);
|
|
126306
126469
|
return 1;
|
|
126307
126470
|
}
|
|
126308
126471
|
if (indexEmbeddingsPending(root)) {
|
|
126309
|
-
console.log(
|
|
126472
|
+
console.log(import_picocolors45.default.dim(" index ready (semantic search warming up)"));
|
|
126310
126473
|
}
|
|
126311
126474
|
try {
|
|
126312
126475
|
await stitchQueueMap(hostUrl, label);
|
|
126313
126476
|
} catch (err2) {
|
|
126314
126477
|
console.log(
|
|
126315
|
-
|
|
126478
|
+
import_picocolors45.default.dim(`[${label}] `) + `Queue map skipped (degraded): ${err2.message}. Stitched 0 queue edge(s).`
|
|
126316
126479
|
);
|
|
126317
126480
|
}
|
|
126318
126481
|
await buildKnowledgeIndex(root, config2, label, configuredProject, opts, hostUrl);
|
|
@@ -126329,10 +126492,10 @@ async function runIndex(opts) {
|
|
|
126329
126492
|
const configPath = writeLocalConfig(root, file);
|
|
126330
126493
|
registerProject(name2, root, configPath);
|
|
126331
126494
|
ensureProjectGitignore(root);
|
|
126332
|
-
console.log(`${
|
|
126333
|
-
console.log(
|
|
126495
|
+
console.log(`${import_picocolors45.default.green("\u2713")} Indexed ${import_picocolors45.default.bold(name2)} \u2014 host ${hostUrl}`);
|
|
126496
|
+
console.log(import_picocolors45.default.dim(` ${configPath}`));
|
|
126334
126497
|
console.log(
|
|
126335
|
-
|
|
126498
|
+
import_picocolors45.default.dim(
|
|
126336
126499
|
` investigate: horus investigate "<hint>" (from this repo)`
|
|
126337
126500
|
)
|
|
126338
126501
|
);
|
|
@@ -126348,19 +126511,19 @@ async function runIndex(opts) {
|
|
|
126348
126511
|
writeLocalConfig(root, file);
|
|
126349
126512
|
registerProject(label, root, existingPath);
|
|
126350
126513
|
ensureProjectGitignore(root);
|
|
126351
|
-
console.log(`${
|
|
126352
|
-
console.log(
|
|
126514
|
+
console.log(`${import_picocolors45.default.green("\u2713")} Indexed ${import_picocolors45.default.bold(label)} \u2014 source host registered at ${hostUrl}`);
|
|
126515
|
+
console.log(import_picocolors45.default.dim(` ${existingPath}`));
|
|
126353
126516
|
} else {
|
|
126354
|
-
console.log(`${
|
|
126517
|
+
console.log(`${import_picocolors45.default.green("\u2713")} Indexed ${import_picocolors45.default.bold(label)} ${import_picocolors45.default.dim("(queue map refreshed)")}`);
|
|
126355
126518
|
}
|
|
126356
126519
|
} else {
|
|
126357
126520
|
console.log(
|
|
126358
|
-
`${
|
|
126521
|
+
`${import_picocolors45.default.green("\u2713")} Indexed ${import_picocolors45.default.bold(label)} ${import_picocolors45.default.dim("(queue map refreshed)")}`
|
|
126359
126522
|
);
|
|
126360
126523
|
}
|
|
126361
126524
|
return 0;
|
|
126362
126525
|
} catch (err2) {
|
|
126363
|
-
console.error(
|
|
126526
|
+
console.error(import_picocolors45.default.red(err2.message));
|
|
126364
126527
|
return 1;
|
|
126365
126528
|
}
|
|
126366
126529
|
}
|
|
@@ -126368,7 +126531,7 @@ async function runIndex(opts) {
|
|
|
126368
126531
|
// ../../packages/cli/src/commands/init.ts
|
|
126369
126532
|
async function runInit(opts) {
|
|
126370
126533
|
try {
|
|
126371
|
-
console.log(
|
|
126534
|
+
console.log(import_picocolors46.default.bold("\nHorus init\n"));
|
|
126372
126535
|
await checkPrerequisites({ ...opts.config !== void 0 ? { config: opts.config } : {} });
|
|
126373
126536
|
console.log("");
|
|
126374
126537
|
const cwd = process.cwd();
|
|
@@ -126382,10 +126545,10 @@ async function runInit(opts) {
|
|
|
126382
126545
|
const code = writeConfigOnly(root, opts, void 0);
|
|
126383
126546
|
if (code === 0) {
|
|
126384
126547
|
console.log(
|
|
126385
|
-
|
|
126548
|
+
import_picocolors46.default.dim(" indexing skipped \u2014 no source-intelligence backend found. Install it:")
|
|
126386
126549
|
);
|
|
126387
|
-
console.log(
|
|
126388
|
-
console.log(
|
|
126550
|
+
console.log(import_picocolors46.default.dim(" curl -fsSL https://horus.sh/install.sh | bash"));
|
|
126551
|
+
console.log(import_picocolors46.default.dim(" then re-run `horus init` to index this repo"));
|
|
126389
126552
|
}
|
|
126390
126553
|
return code;
|
|
126391
126554
|
}
|
|
@@ -126401,7 +126564,7 @@ async function runInit(opts) {
|
|
|
126401
126564
|
path: root
|
|
126402
126565
|
});
|
|
126403
126566
|
} catch (err2) {
|
|
126404
|
-
console.error(
|
|
126567
|
+
console.error(import_picocolors46.default.red(err2.message));
|
|
126405
126568
|
return 1;
|
|
126406
126569
|
}
|
|
126407
126570
|
}
|
|
@@ -126422,57 +126585,57 @@ function writeConfigOnly(root, opts, hostUrl) {
|
|
|
126422
126585
|
const configPath = writeLocalConfig(root, file);
|
|
126423
126586
|
registerProject(name2, root, configPath);
|
|
126424
126587
|
ensureProjectGitignore(root);
|
|
126425
|
-
console.log(`${
|
|
126426
|
-
console.log(
|
|
126427
|
-
console.log(
|
|
126588
|
+
console.log(`${import_picocolors46.default.green("\u2713")} Initialized Horus project ${import_picocolors46.default.bold(name2)}`);
|
|
126589
|
+
console.log(import_picocolors46.default.dim(` config: ${configPath}`));
|
|
126590
|
+
console.log(import_picocolors46.default.dim(` next: horus investigate "<hint>" (from this repo)`));
|
|
126428
126591
|
console.log(
|
|
126429
|
-
|
|
126592
|
+
import_picocolors46.default.dim(" add runtime connectors with `horus connect <type>` (elasticsearch/mongodb/grafana/...) \u2014 credentials are encrypted, never hand-edited into config.json")
|
|
126430
126593
|
);
|
|
126431
126594
|
console.log(
|
|
126432
|
-
|
|
126595
|
+
import_picocolors46.default.dim(" .horus/ is gitignored \u2014 local config and runtime state stay out of version control")
|
|
126433
126596
|
);
|
|
126434
126597
|
return 0;
|
|
126435
126598
|
} catch (err2) {
|
|
126436
|
-
console.error(
|
|
126599
|
+
console.error(import_picocolors46.default.red(err2.message));
|
|
126437
126600
|
return 1;
|
|
126438
126601
|
}
|
|
126439
126602
|
}
|
|
126440
126603
|
|
|
126441
126604
|
// ../../packages/cli/src/commands/projects.ts
|
|
126442
126605
|
init_cjs_shims();
|
|
126443
|
-
var
|
|
126606
|
+
var import_picocolors47 = __toESM(require_picocolors(), 1);
|
|
126444
126607
|
init_src();
|
|
126445
126608
|
async function runProjects() {
|
|
126446
126609
|
const reg = readRegistry();
|
|
126447
126610
|
const names = Object.keys(reg.projects).sort();
|
|
126448
126611
|
if (names.length === 0) {
|
|
126449
126612
|
console.log(
|
|
126450
|
-
|
|
126613
|
+
import_picocolors47.default.dim("No registered projects. Run `horus init` inside a repo.")
|
|
126451
126614
|
);
|
|
126452
126615
|
return 0;
|
|
126453
126616
|
}
|
|
126454
|
-
console.log(
|
|
126617
|
+
console.log(import_picocolors47.default.bold("Registered Horus projects"));
|
|
126455
126618
|
console.log("");
|
|
126456
126619
|
for (const name2 of names) {
|
|
126457
126620
|
const entry = reg.projects[name2];
|
|
126458
126621
|
if (entry === void 0) continue;
|
|
126459
|
-
console.log(` ${
|
|
126622
|
+
console.log(` ${import_picocolors47.default.bold(name2.padEnd(22))} ${import_picocolors47.default.dim(entry.root)}`);
|
|
126460
126623
|
}
|
|
126461
126624
|
console.log("");
|
|
126462
|
-
console.log(
|
|
126625
|
+
console.log(import_picocolors47.default.dim(' cd <repo> && horus investigate "<hint>" (or: horus investigate --config <path>)'));
|
|
126463
126626
|
return 0;
|
|
126464
126627
|
}
|
|
126465
126628
|
|
|
126466
126629
|
// ../../packages/cli/src/commands/connect.ts
|
|
126467
126630
|
init_cjs_shims();
|
|
126468
126631
|
var import_node_readline = require("readline");
|
|
126469
|
-
var
|
|
126632
|
+
var import_picocolors49 = __toESM(require_picocolors(), 1);
|
|
126470
126633
|
init_src();
|
|
126471
126634
|
|
|
126472
126635
|
// ../../packages/cli/src/commands/connect-ai.ts
|
|
126473
126636
|
init_cjs_shims();
|
|
126474
126637
|
var import_node_child_process10 = require("child_process");
|
|
126475
|
-
var
|
|
126638
|
+
var import_picocolors48 = __toESM(require_picocolors(), 1);
|
|
126476
126639
|
init_src();
|
|
126477
126640
|
function cliInstalled(id) {
|
|
126478
126641
|
const r = (0, import_node_child_process10.spawnSync)(id, ["--version"], { stdio: "ignore", timeout: 2e3 });
|
|
@@ -126501,13 +126664,13 @@ async function runConnectAi(opts) {
|
|
|
126501
126664
|
const root = findRepoRoot(cwd) ?? cwd;
|
|
126502
126665
|
const configPath = discoverLocalConfig(cwd) ?? localConfigPath(root);
|
|
126503
126666
|
const installed = LOCAL_PROVIDER_IDS.filter((id) => cliInstalled(id));
|
|
126504
|
-
console.log(
|
|
126667
|
+
console.log(import_picocolors48.default.bold("\nAI providers"));
|
|
126505
126668
|
console.log(
|
|
126506
|
-
|
|
126669
|
+
import_picocolors48.default.dim(
|
|
126507
126670
|
` Local CLIs on PATH: ${installed.length > 0 ? installed.join(", ") : "none detected"}`
|
|
126508
126671
|
)
|
|
126509
126672
|
);
|
|
126510
|
-
console.log(
|
|
126673
|
+
console.log(import_picocolors48.default.dim(" Cloud: anthropic (Anthropic Claude API \u2014 used by `investigate --ai`)\n"));
|
|
126511
126674
|
let provider = opts.provider;
|
|
126512
126675
|
if (provider === void 0) {
|
|
126513
126676
|
if (isInteractive()) {
|
|
@@ -126518,7 +126681,7 @@ async function runConnectAi(opts) {
|
|
|
126518
126681
|
}
|
|
126519
126682
|
}
|
|
126520
126683
|
if (!AI_PROVIDERS.includes(provider)) {
|
|
126521
|
-
console.error(
|
|
126684
|
+
console.error(import_picocolors48.default.red(`Unknown AI provider: ${provider}`) + import_picocolors48.default.dim(`
|
|
126522
126685
|
supported: ${AI_PROVIDERS.join(", ")}`));
|
|
126523
126686
|
return 1;
|
|
126524
126687
|
}
|
|
@@ -126531,7 +126694,7 @@ async function runConnectAi(opts) {
|
|
|
126531
126694
|
}
|
|
126532
126695
|
if (!apiKey) {
|
|
126533
126696
|
console.error(
|
|
126534
|
-
|
|
126697
|
+
import_picocolors48.default.red("No API key provided.") + import_picocolors48.default.dim("\n Pass --api-key sk-ant-\u2026 or set ANTHROPIC_API_KEY and re-run.")
|
|
126535
126698
|
);
|
|
126536
126699
|
return 1;
|
|
126537
126700
|
}
|
|
@@ -126539,28 +126702,28 @@ async function runConnectAi(opts) {
|
|
|
126539
126702
|
const probe2 = await probeAnthropic(apiKey);
|
|
126540
126703
|
if (!probe2.ok) {
|
|
126541
126704
|
console.error(`
|
|
126542
|
-
${
|
|
126543
|
-
console.error(
|
|
126705
|
+
${import_picocolors48.default.red("\u2717 Anthropic key check failed:")} ${probe2.detail}`);
|
|
126706
|
+
console.error(import_picocolors48.default.dim(" Fix the key and retry, or pass --no-test to skip."));
|
|
126544
126707
|
return 1;
|
|
126545
126708
|
}
|
|
126546
126709
|
console.log(`
|
|
126547
|
-
${
|
|
126710
|
+
${import_picocolors48.default.green("\u2713")} anthropic ${import_picocolors48.default.dim(`(${probe2.detail})`)}`);
|
|
126548
126711
|
}
|
|
126549
126712
|
if (opts.model) aiBlock["anthropic"] = { model: opts.model };
|
|
126550
126713
|
storedKey = apiKey;
|
|
126551
126714
|
} else {
|
|
126552
126715
|
if (!installed.includes(provider)) {
|
|
126553
126716
|
console.error(
|
|
126554
|
-
|
|
126717
|
+
import_picocolors48.default.red(`${provider} CLI not found on PATH.`) + import_picocolors48.default.dim(`
|
|
126555
126718
|
Install it first, or choose anthropic.`)
|
|
126556
126719
|
);
|
|
126557
126720
|
return 1;
|
|
126558
126721
|
}
|
|
126559
126722
|
const desc2 = DEFAULT_LOCAL_PROVIDER_REGISTRY.get(provider);
|
|
126560
126723
|
console.log(`
|
|
126561
|
-
${
|
|
126724
|
+
${import_picocolors48.default.green("\u2713")} ${desc2?.displayName ?? provider} ${import_picocolors48.default.dim("detected on PATH")}`);
|
|
126562
126725
|
console.log(
|
|
126563
|
-
|
|
126726
|
+
import_picocolors48.default.dim(
|
|
126564
126727
|
" Note: `investigate --ai` currently uses the Anthropic API for narrative.\n Local-CLI narrative generation is recorded as your preference for future use."
|
|
126565
126728
|
)
|
|
126566
126729
|
);
|
|
@@ -126578,15 +126741,15 @@ ${import_picocolors46.default.green("\u2713")} ${desc2?.displayName ?? provider}
|
|
|
126578
126741
|
});
|
|
126579
126742
|
}
|
|
126580
126743
|
console.log(`
|
|
126581
|
-
${
|
|
126582
|
-
console.log(
|
|
126744
|
+
${import_picocolors48.default.green("\u2713")} ${import_picocolors48.default.bold("ai")} provider saved \u2192 ${import_picocolors48.default.dim(configPath)}`);
|
|
126745
|
+
console.log(import_picocolors48.default.dim(` provider: ${provider}`));
|
|
126583
126746
|
if (storedKey && secretsPathStr) {
|
|
126584
|
-
console.log(
|
|
126747
|
+
console.log(import_picocolors48.default.dim(` anthropic key: ${redactKey(storedKey)} \u2192 ${secretsPathStr} (gitignored)`));
|
|
126585
126748
|
}
|
|
126586
|
-
console.log(
|
|
126749
|
+
console.log(import_picocolors48.default.dim(' run: horus investigate "<hint>" --ai'));
|
|
126587
126750
|
return 0;
|
|
126588
126751
|
} catch (err2) {
|
|
126589
|
-
console.error(
|
|
126752
|
+
console.error(import_picocolors48.default.red(err2 instanceof Error ? err2.message : String(err2)));
|
|
126590
126753
|
return 1;
|
|
126591
126754
|
}
|
|
126592
126755
|
}
|
|
@@ -126618,7 +126781,7 @@ async function runConnect(type, opts) {
|
|
|
126618
126781
|
}
|
|
126619
126782
|
if (!SUPPORTED.includes(type)) {
|
|
126620
126783
|
console.error(
|
|
126621
|
-
|
|
126784
|
+
import_picocolors49.default.red(`Unknown connector type: ${type}`) + import_picocolors49.default.dim(`
|
|
126622
126785
|
supported: ${SUPPORTED.join(", ")}, ai`)
|
|
126623
126786
|
);
|
|
126624
126787
|
return 1;
|
|
@@ -126631,9 +126794,9 @@ async function runConnect(type, opts) {
|
|
|
126631
126794
|
const filled = await fillInteractive(connectorType, opts);
|
|
126632
126795
|
if (missingRequired(connectorType, filled)) {
|
|
126633
126796
|
console.error(
|
|
126634
|
-
|
|
126797
|
+
import_picocolors49.default.red(`Missing required field(s) for ${connectorType} \u2014 nothing saved.`) + import_picocolors49.default.dim(
|
|
126635
126798
|
`
|
|
126636
|
-
Re-run ${
|
|
126799
|
+
Re-run ${import_picocolors49.default.bold(`horus connect ${connectorType}`)} and fill every prompt, or pass them as flags (e.g. --secret for the token).`
|
|
126637
126800
|
)
|
|
126638
126801
|
);
|
|
126639
126802
|
return 1;
|
|
@@ -126670,13 +126833,13 @@ async function runConnect(type, opts) {
|
|
|
126670
126833
|
if (!probeResult.ok) {
|
|
126671
126834
|
console.error(
|
|
126672
126835
|
`
|
|
126673
|
-
${
|
|
126836
|
+
${import_picocolors49.default.red(`\u2717 Could not reach ${connectorType}:`)} ${probeResult.detail}` + import_picocolors49.default.dim("\n Fix the connection and retry, or pass --no-test to skip.")
|
|
126674
126837
|
);
|
|
126675
126838
|
return 1;
|
|
126676
126839
|
}
|
|
126677
126840
|
console.log(
|
|
126678
126841
|
`
|
|
126679
|
-
${
|
|
126842
|
+
${import_picocolors49.default.green("\u2713")} ${connectorType} reachable ${import_picocolors49.default.dim(`(${probeResult.detail})`)}`
|
|
126680
126843
|
);
|
|
126681
126844
|
}
|
|
126682
126845
|
const envName = resolveEnvName(configPath, filled.env);
|
|
@@ -126696,38 +126859,38 @@ ${import_picocolors47.default.green("\u2713")} ${connectorType} reachable ${impo
|
|
|
126696
126859
|
try {
|
|
126697
126860
|
keyResult = ensureMasterKey();
|
|
126698
126861
|
} catch (err2) {
|
|
126699
|
-
console.error(
|
|
126862
|
+
console.error(import_picocolors49.default.red(err2.message));
|
|
126700
126863
|
return 1;
|
|
126701
126864
|
}
|
|
126702
126865
|
for (const [field, value] of secretPatch) {
|
|
126703
126866
|
writeConnectorSecret(root, envName, connectorType, field, value, keyResult.key);
|
|
126704
126867
|
}
|
|
126705
|
-
if (keyResult.warning) console.warn(
|
|
126868
|
+
if (keyResult.warning) console.warn(import_picocolors49.default.yellow(`
|
|
126706
126869
|
\u26A0 ${keyResult.warning}`));
|
|
126707
126870
|
}
|
|
126708
126871
|
patchLocalConnector(configPath, connectorType, nonSecretPatch, envName);
|
|
126709
126872
|
console.log(
|
|
126710
|
-
`${
|
|
126873
|
+
`${import_picocolors49.default.green("\u2713")} ${import_picocolors49.default.bold(connectorType)} connector saved \u2192 ${import_picocolors49.default.dim(configPath)}`
|
|
126711
126874
|
);
|
|
126712
126875
|
if (secretPatch.length > 0) {
|
|
126713
126876
|
const n4 = secretPatch.length;
|
|
126714
126877
|
console.log(
|
|
126715
|
-
|
|
126878
|
+
import_picocolors49.default.dim(
|
|
126716
126879
|
` ${n4} secret${n4 > 1 ? "s" : ""} encrypted \u2192 ${localSecretsPath(root)}
|
|
126717
126880
|
master key: ${masterKeyStatus().detail}`
|
|
126718
126881
|
)
|
|
126719
126882
|
);
|
|
126720
126883
|
}
|
|
126721
126884
|
printSummary(connectorType, filled);
|
|
126722
|
-
console.log(
|
|
126885
|
+
console.log(import_picocolors49.default.dim(`
|
|
126723
126886
|
run: horus investigate "<hint>"`));
|
|
126724
126887
|
return 0;
|
|
126725
126888
|
} catch (err2) {
|
|
126726
126889
|
if (err2 instanceof ExitPromptError) {
|
|
126727
|
-
console.error(
|
|
126890
|
+
console.error(import_picocolors49.default.red("Cancelled."));
|
|
126728
126891
|
return 1;
|
|
126729
126892
|
}
|
|
126730
|
-
console.error(
|
|
126893
|
+
console.error(import_picocolors49.default.red(err2.message));
|
|
126731
126894
|
return 1;
|
|
126732
126895
|
}
|
|
126733
126896
|
}
|
|
@@ -126736,7 +126899,7 @@ async function fillInteractive(type, opts) {
|
|
|
126736
126899
|
if (!needsInteraction) return opts;
|
|
126737
126900
|
console.log(
|
|
126738
126901
|
`
|
|
126739
|
-
${
|
|
126902
|
+
${import_picocolors49.default.bold(`Connect ${type}`)} ${import_picocolors49.default.dim("(press Enter to skip optional fields)")}
|
|
126740
126903
|
`
|
|
126741
126904
|
);
|
|
126742
126905
|
const filled = { ...opts };
|
|
@@ -126826,7 +126989,7 @@ ${import_picocolors47.default.bold(`Connect ${type}`)} ${import_picocolors47.def
|
|
|
126826
126989
|
if (filled.dataset === void 0) {
|
|
126827
126990
|
if (names.length === 0) {
|
|
126828
126991
|
console.log(
|
|
126829
|
-
|
|
126992
|
+
import_picocolors49.default.yellow(
|
|
126830
126993
|
" Couldn't list datasets (check token / network / region) \u2014 enter the name manually."
|
|
126831
126994
|
)
|
|
126832
126995
|
);
|
|
@@ -126874,7 +127037,7 @@ ${import_picocolors47.default.bold(`Connect ${type}`)} ${import_picocolors47.def
|
|
|
126874
127037
|
break;
|
|
126875
127038
|
case "redis": {
|
|
126876
127039
|
console.log(
|
|
126877
|
-
|
|
127040
|
+
import_picocolors49.default.dim(
|
|
126878
127041
|
" Tip: embed credentials directly in the URL \u2014 redis://:password@host:6379\n or enter the URL and password separately below."
|
|
126879
127042
|
)
|
|
126880
127043
|
);
|
|
@@ -126920,8 +127083,8 @@ function missingRequired(type, opts) {
|
|
|
126920
127083
|
}
|
|
126921
127084
|
function ask(label, placeholder = "", required2 = true) {
|
|
126922
127085
|
return new Promise((resolve13) => {
|
|
126923
|
-
const hint = placeholder ?
|
|
126924
|
-
const suffix = required2 ? "" :
|
|
127086
|
+
const hint = placeholder ? import_picocolors49.default.dim(` (${placeholder})`) : "";
|
|
127087
|
+
const suffix = required2 ? "" : import_picocolors49.default.dim(" [optional]");
|
|
126925
127088
|
process.stdout.write(` ${label}${suffix}${hint}: `);
|
|
126926
127089
|
const rl = (0, import_node_readline.createInterface)({
|
|
126927
127090
|
input: process.stdin,
|
|
@@ -126938,7 +127101,7 @@ function askPassword(label, required2 = false) {
|
|
|
126938
127101
|
return new Promise((resolve13) => {
|
|
126939
127102
|
const stdin = process.stdin;
|
|
126940
127103
|
if (typeof stdin.setRawMode === "function") {
|
|
126941
|
-
const suffix = required2 ? "" :
|
|
127104
|
+
const suffix = required2 ? "" : import_picocolors49.default.dim(" [optional]");
|
|
126942
127105
|
process.stdout.write(` ${label}${suffix}: `);
|
|
126943
127106
|
stdin.setRawMode(true);
|
|
126944
127107
|
stdin.resume();
|
|
@@ -126948,7 +127111,7 @@ function askPassword(label, required2 = false) {
|
|
|
126948
127111
|
if (char2 === "\r" || char2 === "\n") {
|
|
126949
127112
|
if (required2 && value === "") {
|
|
126950
127113
|
process.stdout.write(`
|
|
126951
|
-
${
|
|
127114
|
+
${import_picocolors49.default.yellow(" Required \u2014 please enter a value.")}
|
|
126952
127115
|
`);
|
|
126953
127116
|
process.stdout.write(` ${label}: `);
|
|
126954
127117
|
return;
|
|
@@ -126980,18 +127143,18 @@ async function askRequiredText(label) {
|
|
|
126980
127143
|
for (; ; ) {
|
|
126981
127144
|
const v4 = (await ask(label, "", false)).trim();
|
|
126982
127145
|
if (v4) return v4;
|
|
126983
|
-
console.log(
|
|
127146
|
+
console.log(import_picocolors49.default.yellow(" Required \u2014 please enter a value."));
|
|
126984
127147
|
}
|
|
126985
127148
|
}
|
|
126986
127149
|
async function askShopifyAuthMethod() {
|
|
126987
|
-
console.log(` ${
|
|
126988
|
-
console.log(` ${
|
|
126989
|
-
console.log(` ${
|
|
127150
|
+
console.log(` ${import_picocolors49.default.bold("Auth method")}`);
|
|
127151
|
+
console.log(` ${import_picocolors49.default.bold("1)")} Static Admin API access token ${import_picocolors49.default.dim("\u2014 a Custom App shpat_\u2026 token")}`);
|
|
127152
|
+
console.log(` ${import_picocolors49.default.bold("2)")} Client-Credentials app ${import_picocolors49.default.dim("\u2014 client id + secret, exchanged for a token")}`);
|
|
126990
127153
|
for (; ; ) {
|
|
126991
127154
|
const a2 = (await ask("Choose", "1")).trim();
|
|
126992
127155
|
if (a2 === "1") return "static";
|
|
126993
127156
|
if (a2 === "2") return "client-credentials";
|
|
126994
|
-
console.log(
|
|
127157
|
+
console.log(import_picocolors49.default.yellow(" Enter 1 or 2."));
|
|
126995
127158
|
}
|
|
126996
127159
|
}
|
|
126997
127160
|
function buildEsPatch(opts) {
|
|
@@ -127096,15 +127259,15 @@ function describeProbe(p5) {
|
|
|
127096
127259
|
return `${p5.keyCount} keys \xB7 ${p5.suggestedRoles.join("/")}${examples ? ` \xB7 ${examples}` : ""}`;
|
|
127097
127260
|
}
|
|
127098
127261
|
async function discoverAndSelectDbs(url, bullmqPrefix) {
|
|
127099
|
-
console.log(
|
|
127262
|
+
console.log(import_picocolors49.default.dim("\n Scanning DBs 0-15 (read-only, sampled)\u2026"));
|
|
127100
127263
|
const probes = await probeRedisDatabases(url, { bullmqPrefix });
|
|
127101
127264
|
const nonEmpty = probes.filter((p5) => p5.reachable && p5.keyCount > 0);
|
|
127102
127265
|
if (nonEmpty.length === 0) {
|
|
127103
|
-
console.log(
|
|
127266
|
+
console.log(import_picocolors49.default.dim(" No populated DBs found."));
|
|
127104
127267
|
return [];
|
|
127105
127268
|
}
|
|
127106
127269
|
for (const p5 of nonEmpty) {
|
|
127107
|
-
console.log(` ${
|
|
127270
|
+
console.log(` ${import_picocolors49.default.bold(`DB ${p5.db}`)} ${import_picocolors49.default.dim("\xB7 " + describeProbe(p5))}`);
|
|
127108
127271
|
}
|
|
127109
127272
|
const byLabel = /* @__PURE__ */ new Map();
|
|
127110
127273
|
const choices = nonEmpty.map((p5) => {
|
|
@@ -127275,7 +127438,7 @@ function printSummary(type, opts) {
|
|
|
127275
127438
|
} else if (opts.dashboard) {
|
|
127276
127439
|
lines.push(` dashboard: ${opts.dashboard}`);
|
|
127277
127440
|
}
|
|
127278
|
-
if (lines.length > 0) console.log(
|
|
127441
|
+
if (lines.length > 0) console.log(import_picocolors49.default.dim(lines.join("\n")));
|
|
127279
127442
|
}
|
|
127280
127443
|
function resolveEnvName(configPath, requested) {
|
|
127281
127444
|
const file = readLocalConfig(configPath);
|
|
@@ -127317,11 +127480,11 @@ async function askIndexSelection(indices) {
|
|
|
127317
127480
|
const shown = indices.slice(0, MAX_DISPLAY);
|
|
127318
127481
|
console.log("\n Available Elasticsearch indexes/data streams:");
|
|
127319
127482
|
shown.forEach((name2, i3) => {
|
|
127320
|
-
console.log(` ${
|
|
127483
|
+
console.log(` ${import_picocolors49.default.dim(`[${i3 + 1}]`)} ${name2}`);
|
|
127321
127484
|
});
|
|
127322
127485
|
if (indices.length > MAX_DISPLAY) {
|
|
127323
127486
|
console.log(
|
|
127324
|
-
|
|
127487
|
+
import_picocolors49.default.dim(
|
|
127325
127488
|
` \u2026 and ${indices.length - MAX_DISPLAY} more (type a pattern manually to match all)`
|
|
127326
127489
|
)
|
|
127327
127490
|
);
|
|
@@ -127365,11 +127528,11 @@ async function askDashboardSelection(dashboards) {
|
|
|
127365
127528
|
const shown = dashboards.slice(0, MAX_DISPLAY);
|
|
127366
127529
|
console.log("\n Available Grafana dashboards:");
|
|
127367
127530
|
shown.forEach((d3, i3) => {
|
|
127368
|
-
const folder = d3.folderTitle ?
|
|
127369
|
-
console.log(` ${
|
|
127531
|
+
const folder = d3.folderTitle ? import_picocolors49.default.dim(` (${d3.folderTitle})`) : "";
|
|
127532
|
+
console.log(` ${import_picocolors49.default.dim(`[${i3 + 1}]`)} ${d3.title}${folder}`);
|
|
127370
127533
|
});
|
|
127371
127534
|
if (dashboards.length > MAX_DISPLAY) {
|
|
127372
|
-
console.log(
|
|
127535
|
+
console.log(import_picocolors49.default.dim(` \u2026 and ${dashboards.length - MAX_DISPLAY} more`));
|
|
127373
127536
|
}
|
|
127374
127537
|
const input = (await ask(
|
|
127375
127538
|
` Select dashboards to use (e.g. 1,2 or Enter to type uid manually)`,
|
|
@@ -127427,10 +127590,10 @@ async function askDatasetSelection(names) {
|
|
|
127427
127590
|
const shown = names.slice(0, MAX_DISPLAY);
|
|
127428
127591
|
console.log("\n Available Axiom datasets:");
|
|
127429
127592
|
shown.forEach((name2, i3) => {
|
|
127430
|
-
console.log(` ${
|
|
127593
|
+
console.log(` ${import_picocolors49.default.dim(`[${i3 + 1}]`)} ${name2}`);
|
|
127431
127594
|
});
|
|
127432
127595
|
if (names.length > MAX_DISPLAY) {
|
|
127433
|
-
console.log(
|
|
127596
|
+
console.log(import_picocolors49.default.dim(` \u2026 and ${names.length - MAX_DISPLAY} more`));
|
|
127434
127597
|
}
|
|
127435
127598
|
const input = (await ask(" Select a dataset (e.g. 1 or Enter to type a name manually)", "", false)).trim();
|
|
127436
127599
|
if (!input) return void 0;
|
|
@@ -127443,7 +127606,7 @@ async function askDatasetSelection(names) {
|
|
|
127443
127606
|
async function pickSentryResource(label, resources) {
|
|
127444
127607
|
if (resources.length === 0) {
|
|
127445
127608
|
console.log(
|
|
127446
|
-
|
|
127609
|
+
import_picocolors49.default.yellow(
|
|
127447
127610
|
` Couldn't list ${label.toLowerCase()}s (check token / org / network) \u2014 enter the slug manually.`
|
|
127448
127611
|
)
|
|
127449
127612
|
);
|
|
@@ -127473,10 +127636,10 @@ async function pickSentryResource(label, resources) {
|
|
|
127473
127636
|
console.log(`
|
|
127474
127637
|
Available ${label.toLowerCase()}s:`);
|
|
127475
127638
|
shown.forEach((r, i3) => {
|
|
127476
|
-
console.log(` ${
|
|
127639
|
+
console.log(` ${import_picocolors49.default.dim(`[${i3 + 1}]`)} ${choiceFor(r)}`);
|
|
127477
127640
|
});
|
|
127478
127641
|
if (resources.length > MAX_DISPLAY) {
|
|
127479
|
-
console.log(
|
|
127642
|
+
console.log(import_picocolors49.default.dim(` \u2026 and ${resources.length - MAX_DISPLAY} more`));
|
|
127480
127643
|
}
|
|
127481
127644
|
const input = (await ask(` Select a ${label.toLowerCase()} (e.g. 1, or Enter to type the slug manually)`, "", false)).trim();
|
|
127482
127645
|
if (!input) return void 0;
|
|
@@ -127522,14 +127685,14 @@ function redactUrl(raw) {
|
|
|
127522
127685
|
|
|
127523
127686
|
// ../../packages/cli/src/commands/notify.ts
|
|
127524
127687
|
init_cjs_shims();
|
|
127525
|
-
var
|
|
127688
|
+
var import_picocolors50 = __toESM(require_picocolors(), 1);
|
|
127526
127689
|
init_src();
|
|
127527
127690
|
function locate(opts) {
|
|
127528
127691
|
const cwd = process.cwd();
|
|
127529
127692
|
const configPath = opts.config ?? discoverLocalConfig(cwd) ?? null;
|
|
127530
127693
|
const root = findRepoRoot(cwd);
|
|
127531
127694
|
if (root === null) {
|
|
127532
|
-
console.error(
|
|
127695
|
+
console.error(import_picocolors50.default.red("Not inside a git repository \u2014 run this from your project."));
|
|
127533
127696
|
return null;
|
|
127534
127697
|
}
|
|
127535
127698
|
const resolved = configPath ?? localConfigPath(root);
|
|
@@ -127539,13 +127702,13 @@ function pickEnv(file, requested) {
|
|
|
127539
127702
|
const project = file.project;
|
|
127540
127703
|
const envs = project?.environments ?? [];
|
|
127541
127704
|
if (envs.length === 0) {
|
|
127542
|
-
console.error(
|
|
127705
|
+
console.error(import_picocolors50.default.red("No environments in config \u2014 run `horus connect` or `horus init` first."));
|
|
127543
127706
|
return null;
|
|
127544
127707
|
}
|
|
127545
127708
|
if (requested) {
|
|
127546
127709
|
const found = envs.find((e) => e.name === requested);
|
|
127547
127710
|
if (!found) {
|
|
127548
|
-
console.error(
|
|
127711
|
+
console.error(import_picocolors50.default.red(`Environment "${requested}" not found in config.`));
|
|
127549
127712
|
return null;
|
|
127550
127713
|
}
|
|
127551
127714
|
return found;
|
|
@@ -127556,26 +127719,26 @@ function readConfigOrError(configPath) {
|
|
|
127556
127719
|
try {
|
|
127557
127720
|
return readLocalConfig(configPath);
|
|
127558
127721
|
} catch {
|
|
127559
|
-
console.error(
|
|
127722
|
+
console.error(import_picocolors50.default.red(`No config found at ${configPath} \u2014 run \`horus connect\` or \`horus init\` first.`));
|
|
127560
127723
|
return null;
|
|
127561
127724
|
}
|
|
127562
127725
|
}
|
|
127563
127726
|
async function runSet(opts) {
|
|
127564
127727
|
if (!opts.url) {
|
|
127565
|
-
console.error(
|
|
127728
|
+
console.error(import_picocolors50.default.red("A webhook URL is required: horus notify set --url <https://\u2026> [--secret <s>] [--min-confidence 0.6] [--cloud]"));
|
|
127566
127729
|
return 1;
|
|
127567
127730
|
}
|
|
127568
127731
|
try {
|
|
127569
127732
|
new URL(opts.url);
|
|
127570
127733
|
} catch {
|
|
127571
|
-
console.error(
|
|
127734
|
+
console.error(import_picocolors50.default.red(`Invalid --url "${opts.url}".`));
|
|
127572
127735
|
return 1;
|
|
127573
127736
|
}
|
|
127574
127737
|
let minConfidence;
|
|
127575
127738
|
if (opts.minConfidence !== void 0) {
|
|
127576
127739
|
const n4 = Number(opts.minConfidence);
|
|
127577
127740
|
if (!Number.isFinite(n4) || n4 < 0 || n4 > 1) {
|
|
127578
|
-
console.error(
|
|
127741
|
+
console.error(import_picocolors50.default.red(`--min-confidence must be between 0 and 1 (got "${opts.minConfidence}").`));
|
|
127579
127742
|
return 1;
|
|
127580
127743
|
}
|
|
127581
127744
|
minConfidence = n4;
|
|
@@ -127598,18 +127761,18 @@ async function runSet(opts) {
|
|
|
127598
127761
|
try {
|
|
127599
127762
|
const key = ensureMasterKey();
|
|
127600
127763
|
writeConnectorSecret(loc.root, envName, "notify", "webhookSecret", opts.secret, key.key);
|
|
127601
|
-
secretNote =
|
|
127764
|
+
secretNote = import_picocolors50.default.dim(" \xB7 signing secret stored encrypted (.horus/secrets.local.json)");
|
|
127602
127765
|
} catch (err2) {
|
|
127603
|
-
console.error(
|
|
127766
|
+
console.error(import_picocolors50.default.yellow(`Notify URL saved, but the signing secret could not be encrypted: ${err2.message}`));
|
|
127604
127767
|
}
|
|
127605
127768
|
}
|
|
127606
127769
|
console.log(
|
|
127607
|
-
|
|
127608
|
-
${
|
|
127609
|
-
${
|
|
127610
|
-
${
|
|
127770
|
+
import_picocolors50.default.green(`\u2713 Notify sink configured for "${envName}"`) + `
|
|
127771
|
+
${import_picocolors50.default.dim("webhook:")} ${opts.url}
|
|
127772
|
+
${import_picocolors50.default.dim("threshold:")} ${notify.minConfidence ?? 0.6}
|
|
127773
|
+
${import_picocolors50.default.dim("cloud:")} ${notify.cloud === true}${secretNote}`
|
|
127611
127774
|
);
|
|
127612
|
-
console.log(
|
|
127775
|
+
console.log(import_picocolors50.default.dim(" Run `horus notify test` to send a sample, or `horus watch` to start monitoring."));
|
|
127613
127776
|
return 0;
|
|
127614
127777
|
}
|
|
127615
127778
|
function runShow(opts) {
|
|
@@ -127620,12 +127783,12 @@ function runShow(opts) {
|
|
|
127620
127783
|
const env = pickEnv(file, opts.env);
|
|
127621
127784
|
if (!env) return 1;
|
|
127622
127785
|
if (!env.notify || !env.notify.webhook?.url) {
|
|
127623
|
-
console.log(
|
|
127786
|
+
console.log(import_picocolors50.default.dim(`No notify sink configured for "${env.name}". Set one: horus notify set --url <https://\u2026>`));
|
|
127624
127787
|
return 0;
|
|
127625
127788
|
}
|
|
127626
127789
|
const n4 = env.notify;
|
|
127627
127790
|
console.log(
|
|
127628
|
-
|
|
127791
|
+
import_picocolors50.default.bold(`Notify sink for "${env.name}"`) + `
|
|
127629
127792
|
webhook: ${n4.webhook?.url}
|
|
127630
127793
|
threshold: ${n4.minConfidence ?? 0.6}
|
|
127631
127794
|
cloud: ${n4.cloud === true}`
|
|
@@ -127640,11 +127803,11 @@ async function runTest(opts) {
|
|
|
127640
127803
|
const renv = resolveEnvironment3(config2, { env: opts.env });
|
|
127641
127804
|
notify = renv.notify;
|
|
127642
127805
|
} catch (err2) {
|
|
127643
|
-
console.error(
|
|
127806
|
+
console.error(import_picocolors50.default.red(`Could not load config: ${err2.message}`));
|
|
127644
127807
|
return 1;
|
|
127645
127808
|
}
|
|
127646
127809
|
if (!notify || !notify.webhook) {
|
|
127647
|
-
console.error(
|
|
127810
|
+
console.error(import_picocolors50.default.red("No webhook configured \u2014 run `horus notify set --url <https://\u2026>` first."));
|
|
127648
127811
|
return 1;
|
|
127649
127812
|
}
|
|
127650
127813
|
const results = await dispatchNotify(
|
|
@@ -127657,15 +127820,15 @@ async function runTest(opts) {
|
|
|
127657
127820
|
{ ...notify, minConfidence: 0 }
|
|
127658
127821
|
);
|
|
127659
127822
|
if (results.length === 0) {
|
|
127660
|
-
console.error(
|
|
127823
|
+
console.error(import_picocolors50.default.yellow("Nothing dispatched (no target enabled)."));
|
|
127661
127824
|
return 1;
|
|
127662
127825
|
}
|
|
127663
127826
|
let ok = true;
|
|
127664
127827
|
for (const r of results) {
|
|
127665
|
-
if (r.ok) console.log(
|
|
127828
|
+
if (r.ok) console.log(import_picocolors50.default.green(`\u2713 ${r.target} \u2014 ${r.detail}`));
|
|
127666
127829
|
else {
|
|
127667
127830
|
ok = false;
|
|
127668
|
-
console.error(
|
|
127831
|
+
console.error(import_picocolors50.default.red(`\u2717 ${r.target} \u2014 ${r.detail}`));
|
|
127669
127832
|
}
|
|
127670
127833
|
}
|
|
127671
127834
|
return ok ? 0 : 1;
|
|
@@ -127678,13 +127841,13 @@ function runRemove(opts) {
|
|
|
127678
127841
|
const env = pickEnv(file, opts.env);
|
|
127679
127842
|
if (!env) return 1;
|
|
127680
127843
|
if (!env.notify) {
|
|
127681
|
-
console.log(
|
|
127844
|
+
console.log(import_picocolors50.default.dim(`No notify sink configured for "${env.name}".`));
|
|
127682
127845
|
return 0;
|
|
127683
127846
|
}
|
|
127684
127847
|
delete env.notify;
|
|
127685
127848
|
writeLocalConfig(loc.root, file);
|
|
127686
|
-
console.log(
|
|
127687
|
-
console.log(
|
|
127849
|
+
console.log(import_picocolors50.default.green(`\u2713 Removed notify sink from "${env.name}".`));
|
|
127850
|
+
console.log(import_picocolors50.default.dim(" (Any stored signing secret remains in .horus/secrets.local.json \u2014 remove it with `horus secrets` if needed.)"));
|
|
127688
127851
|
return 0;
|
|
127689
127852
|
}
|
|
127690
127853
|
async function runNotify(sub, opts) {
|
|
@@ -127700,7 +127863,7 @@ async function runNotify(sub, opts) {
|
|
|
127700
127863
|
case "clear":
|
|
127701
127864
|
return runRemove(opts);
|
|
127702
127865
|
default:
|
|
127703
|
-
console.error(
|
|
127866
|
+
console.error(import_picocolors50.default.red(`Unknown subcommand "${sub}". Use: set | show | test | remove.`));
|
|
127704
127867
|
return 1;
|
|
127705
127868
|
}
|
|
127706
127869
|
}
|
|
@@ -127708,7 +127871,7 @@ async function runNotify(sub, opts) {
|
|
|
127708
127871
|
// ../../packages/cli/src/commands/secrets.ts
|
|
127709
127872
|
init_cjs_shims();
|
|
127710
127873
|
var import_node_fs25 = require("fs");
|
|
127711
|
-
var
|
|
127874
|
+
var import_picocolors51 = __toESM(require_picocolors(), 1);
|
|
127712
127875
|
init_src();
|
|
127713
127876
|
function locate2(cwd = process.cwd()) {
|
|
127714
127877
|
const root = findRepoRoot(cwd) ?? cwd;
|
|
@@ -127729,37 +127892,37 @@ function countStoredSecrets(root) {
|
|
|
127729
127892
|
function runSecretsStatus(opts = {}) {
|
|
127730
127893
|
const { root, configPath, exists: exists2 } = locate2(opts.cwd);
|
|
127731
127894
|
const key = masterKeyStatus();
|
|
127732
|
-
console.log(
|
|
127895
|
+
console.log(import_picocolors51.default.bold("\nMaster key"));
|
|
127733
127896
|
console.log(
|
|
127734
|
-
key.available ? ` ${
|
|
127897
|
+
key.available ? ` ${import_picocolors51.default.green("\u25CF")} ${key.detail}` : ` ${import_picocolors51.default.dim("\u25CB")} ${key.detail}`
|
|
127735
127898
|
);
|
|
127736
127899
|
const stored = countStoredSecrets(root);
|
|
127737
|
-
console.log(
|
|
127738
|
-
console.log(` ${stored} stored \u2192 ${
|
|
127900
|
+
console.log(import_picocolors51.default.bold("\nEncrypted secrets"));
|
|
127901
|
+
console.log(` ${stored} stored \u2192 ${import_picocolors51.default.dim(localSecretsPath(root))}`);
|
|
127739
127902
|
if (stored > 0) {
|
|
127740
127903
|
const { warnings } = decryptConnectorSecrets(root);
|
|
127741
127904
|
if (warnings.length > 0) {
|
|
127742
|
-
console.log(
|
|
127743
|
-
for (const w4 of warnings) console.log(
|
|
127905
|
+
console.log(import_picocolors51.default.yellow(` \u26A0 ${warnings.length} cannot be decrypted with the current key:`));
|
|
127906
|
+
for (const w4 of warnings) console.log(import_picocolors51.default.dim(` - ${w4}`));
|
|
127744
127907
|
} else {
|
|
127745
|
-
console.log(
|
|
127908
|
+
console.log(import_picocolors51.default.dim(" all decrypt cleanly with the current key"));
|
|
127746
127909
|
}
|
|
127747
127910
|
}
|
|
127748
|
-
console.log(
|
|
127911
|
+
console.log(import_picocolors51.default.bold("\nPlaintext in config.json"));
|
|
127749
127912
|
if (!exists2) {
|
|
127750
|
-
console.log(
|
|
127913
|
+
console.log(import_picocolors51.default.dim(" no .horus/config.json found"));
|
|
127751
127914
|
} else {
|
|
127752
127915
|
const plaintext = findPlaintextConnectorSecrets(readLocalConfig(configPath).project);
|
|
127753
127916
|
if (plaintext.length === 0) {
|
|
127754
|
-
console.log(` ${
|
|
127917
|
+
console.log(` ${import_picocolors51.default.green("\u2713")} none \u2014 config carries no credentials`);
|
|
127755
127918
|
} else {
|
|
127756
|
-
console.log(
|
|
127757
|
-
for (const p5 of plaintext) console.log(
|
|
127919
|
+
console.log(import_picocolors51.default.yellow(` \u26A0 ${plaintext.length} plaintext secret(s) \u2014 run \`horus secrets migrate\`:`));
|
|
127920
|
+
for (const p5 of plaintext) console.log(import_picocolors51.default.dim(` - ${p5}`));
|
|
127758
127921
|
}
|
|
127759
127922
|
}
|
|
127760
|
-
console.log(
|
|
127923
|
+
console.log(import_picocolors51.default.bold("\nGitignore"));
|
|
127761
127924
|
console.log(
|
|
127762
|
-
isHorusGitignored(root) ? ` ${
|
|
127925
|
+
isHorusGitignored(root) ? ` ${import_picocolors51.default.green("\u2713")} .horus/ is gitignored` : import_picocolors51.default.yellow(" \u26A0 .horus/ is NOT gitignored \u2014 run `horus secrets migrate` or add `.horus/` to .gitignore")
|
|
127763
127926
|
);
|
|
127764
127927
|
console.log("");
|
|
127765
127928
|
return 0;
|
|
@@ -127767,31 +127930,31 @@ function runSecretsStatus(opts = {}) {
|
|
|
127767
127930
|
function runSecretsMigrate(opts = {}) {
|
|
127768
127931
|
const { root, configPath, exists: exists2 } = locate2(opts.cwd);
|
|
127769
127932
|
if (!exists2) {
|
|
127770
|
-
console.error(
|
|
127771
|
-
console.error(
|
|
127933
|
+
console.error(import_picocolors51.default.red(`No .horus/config.json found at ${configPath}.`));
|
|
127934
|
+
console.error(import_picocolors51.default.dim(" Run `horus init` in this repo first."));
|
|
127772
127935
|
return 1;
|
|
127773
127936
|
}
|
|
127774
127937
|
const file = readLocalConfig(configPath);
|
|
127775
127938
|
const plaintext = findPlaintextConnectorSecrets(file.project);
|
|
127776
127939
|
ensureProjectGitignore(root);
|
|
127777
127940
|
if (plaintext.length === 0) {
|
|
127778
|
-
console.log(`${
|
|
127941
|
+
console.log(`${import_picocolors51.default.green("\u2713")} No plaintext connector secrets in config.json \u2014 nothing to migrate.`);
|
|
127779
127942
|
if (!isHorusGitignored(root)) {
|
|
127780
|
-
console.log(
|
|
127943
|
+
console.log(import_picocolors51.default.dim(" Ensured `.horus/` is gitignored."));
|
|
127781
127944
|
}
|
|
127782
127945
|
return 0;
|
|
127783
127946
|
}
|
|
127784
127947
|
if (opts.dryRun) {
|
|
127785
|
-
console.log(
|
|
127786
|
-
for (const p5 of plaintext) console.log(
|
|
127787
|
-
console.log(
|
|
127948
|
+
console.log(import_picocolors51.default.bold(`Would migrate ${plaintext.length} plaintext secret(s) \u2192 encrypted store:`));
|
|
127949
|
+
for (const p5 of plaintext) console.log(import_picocolors51.default.dim(` - ${p5}`));
|
|
127950
|
+
console.log(import_picocolors51.default.dim("\n Re-run without --dry-run to apply."));
|
|
127788
127951
|
return 0;
|
|
127789
127952
|
}
|
|
127790
127953
|
let keyResult;
|
|
127791
127954
|
try {
|
|
127792
127955
|
keyResult = ensureMasterKey();
|
|
127793
127956
|
} catch (err2) {
|
|
127794
|
-
console.error(
|
|
127957
|
+
console.error(import_picocolors51.default.red(err2.message));
|
|
127795
127958
|
return 1;
|
|
127796
127959
|
}
|
|
127797
127960
|
const project = file.project;
|
|
@@ -127813,13 +127976,13 @@ function runSecretsMigrate(opts = {}) {
|
|
|
127813
127976
|
}
|
|
127814
127977
|
}
|
|
127815
127978
|
writeLocalConfig(root, file);
|
|
127816
|
-
console.log(`${
|
|
127817
|
-
console.log(
|
|
127818
|
-
console.log(
|
|
127819
|
-
if (keyResult.warning) console.warn(
|
|
127979
|
+
console.log(`${import_picocolors51.default.green("\u2713")} Migrated ${migrated} secret(s) \u2192 ${import_picocolors51.default.dim(localSecretsPath(root))}`);
|
|
127980
|
+
console.log(import_picocolors51.default.dim(` master key: ${masterKeyStatus().detail}`));
|
|
127981
|
+
console.log(import_picocolors51.default.dim(" config.json now carries no credentials."));
|
|
127982
|
+
if (keyResult.warning) console.warn(import_picocolors51.default.yellow(`
|
|
127820
127983
|
\u26A0 ${keyResult.warning}`));
|
|
127821
127984
|
console.log(
|
|
127822
|
-
|
|
127985
|
+
import_picocolors51.default.dim(
|
|
127823
127986
|
"\n If config.json was ever committed, scrub the old secret from history:\n git rm --cached .horus/config.json # if tracked\n # then rotate the exposed credential at its provider."
|
|
127824
127987
|
)
|
|
127825
127988
|
);
|
|
@@ -127828,20 +127991,20 @@ function runSecretsMigrate(opts = {}) {
|
|
|
127828
127991
|
function runSecretsKey(opts = {}) {
|
|
127829
127992
|
const status = masterKeyStatus();
|
|
127830
127993
|
if (!status.available) {
|
|
127831
|
-
console.log(
|
|
127994
|
+
console.log(import_picocolors51.default.dim("No master key yet \u2014 created on first `horus connect` or `horus secrets migrate`."));
|
|
127832
127995
|
return 0;
|
|
127833
127996
|
}
|
|
127834
127997
|
console.log(`Master key source: ${status.detail}`);
|
|
127835
127998
|
if (!opts.show) {
|
|
127836
|
-
console.log(
|
|
127999
|
+
console.log(import_picocolors51.default.dim(" Pass --show to print the key (base64) for CI use (HORUS_SECRET_KEY)."));
|
|
127837
128000
|
return 0;
|
|
127838
128001
|
}
|
|
127839
128002
|
const key = getMasterKeyForRead();
|
|
127840
128003
|
if (!key) {
|
|
127841
|
-
console.error(
|
|
128004
|
+
console.error(import_picocolors51.default.red("Could not read the master key."));
|
|
127842
128005
|
return 1;
|
|
127843
128006
|
}
|
|
127844
|
-
console.warn(
|
|
128007
|
+
console.warn(import_picocolors51.default.yellow("\u26A0 Treat this as a credential. Anyone with it can decrypt your connector secrets."));
|
|
127845
128008
|
console.log(`
|
|
127846
128009
|
export HORUS_SECRET_KEY=${key.toString("base64")}
|
|
127847
128010
|
`);
|
|
@@ -127854,7 +128017,7 @@ var import_node_child_process11 = require("child_process");
|
|
|
127854
128017
|
var import_node_fs26 = require("fs");
|
|
127855
128018
|
var import_node_util7 = require("util");
|
|
127856
128019
|
var import_node_path28 = require("path");
|
|
127857
|
-
var
|
|
128020
|
+
var import_picocolors52 = __toESM(require_picocolors(), 1);
|
|
127858
128021
|
init_src();
|
|
127859
128022
|
var execFileAsync4 = (0, import_node_util7.promisify)(import_node_child_process11.execFile);
|
|
127860
128023
|
var unlinkAsync = (0, import_node_util7.promisify)(import_node_fs26.unlink);
|
|
@@ -127873,19 +128036,19 @@ async function runStop(opts) {
|
|
|
127873
128036
|
const root = findRepoRoot(cwd) ?? cwd;
|
|
127874
128037
|
const hostUrl = readSourceHostUrl(root);
|
|
127875
128038
|
if (!hostUrl) {
|
|
127876
|
-
console.log(
|
|
128039
|
+
console.log(import_picocolors52.default.dim("No source-intelligence host found for this repo (.horus/source/host.json absent)."));
|
|
127877
128040
|
return 0;
|
|
127878
128041
|
}
|
|
127879
128042
|
return await stopHost(root, hostUrl);
|
|
127880
128043
|
} catch (err2) {
|
|
127881
|
-
console.error(
|
|
128044
|
+
console.error(import_picocolors52.default.red(err2.message));
|
|
127882
128045
|
return 1;
|
|
127883
128046
|
}
|
|
127884
128047
|
}
|
|
127885
128048
|
async function stopHost(root, hostUrl) {
|
|
127886
128049
|
const port = extractPort(hostUrl);
|
|
127887
128050
|
if (port === null) {
|
|
127888
|
-
console.error(
|
|
128051
|
+
console.error(import_picocolors52.default.red(`Cannot determine port from host URL: ${hostUrl}`));
|
|
127889
128052
|
return 1;
|
|
127890
128053
|
}
|
|
127891
128054
|
const healthy = await isHostHealthy(hostUrl);
|
|
@@ -127895,12 +128058,12 @@ async function stopHost(root, hostUrl) {
|
|
|
127895
128058
|
if (!wrapperAlive) {
|
|
127896
128059
|
const res = await stopBackendServerPid(root, port);
|
|
127897
128060
|
if (res === "failed") return 1;
|
|
127898
|
-
if (res !== "stopped") console.log(
|
|
128061
|
+
if (res !== "stopped") console.log(import_picocolors52.default.dim(`Host ${hostUrl} is already stopped.`));
|
|
127899
128062
|
await cleanupSpawnedRecord(root);
|
|
127900
128063
|
return 0;
|
|
127901
128064
|
}
|
|
127902
128065
|
console.log(
|
|
127903
|
-
|
|
128066
|
+
import_picocolors52.default.dim(
|
|
127904
128067
|
`Host ${hostUrl} is unreachable but pid ${owned.pid} is still running \u2014 terminating a stuck host.`
|
|
127905
128068
|
)
|
|
127906
128069
|
);
|
|
@@ -127908,7 +128071,7 @@ async function stopHost(root, hostUrl) {
|
|
|
127908
128071
|
const spawned = readSpawnedHost(root);
|
|
127909
128072
|
if (spawned === null) {
|
|
127910
128073
|
console.error(
|
|
127911
|
-
|
|
128074
|
+
import_picocolors52.default.red(
|
|
127912
128075
|
`No ownership record found (.horus/${SPAWNED_HOST_FILE2} absent). Horus will not stop a host it did not spawn.`
|
|
127913
128076
|
)
|
|
127914
128077
|
);
|
|
@@ -127916,12 +128079,12 @@ async function stopHost(root, hostUrl) {
|
|
|
127916
128079
|
}
|
|
127917
128080
|
const recordError = validateSpawnedRecord(spawned);
|
|
127918
128081
|
if (recordError !== null) {
|
|
127919
|
-
console.error(
|
|
128082
|
+
console.error(import_picocolors52.default.red(`Ownership record is malformed: ${recordError}. Aborting for safety.`));
|
|
127920
128083
|
return 1;
|
|
127921
128084
|
}
|
|
127922
128085
|
if (spawned.port !== port) {
|
|
127923
128086
|
console.error(
|
|
127924
|
-
|
|
128087
|
+
import_picocolors52.default.red(
|
|
127925
128088
|
`Ownership record port (${spawned.port}) does not match host URL port (${port}). Record may be stale.`
|
|
127926
128089
|
)
|
|
127927
128090
|
);
|
|
@@ -127929,7 +128092,7 @@ async function stopHost(root, hostUrl) {
|
|
|
127929
128092
|
}
|
|
127930
128093
|
if (spawned.root !== root) {
|
|
127931
128094
|
console.error(
|
|
127932
|
-
|
|
128095
|
+
import_picocolors52.default.red(
|
|
127933
128096
|
`Ownership record root (${spawned.root}) does not match resolved root (${root}). Record may be stale.`
|
|
127934
128097
|
)
|
|
127935
128098
|
);
|
|
@@ -127940,14 +128103,14 @@ async function stopHost(root, hostUrl) {
|
|
|
127940
128103
|
const res = await stopBackendServerPid(root, port);
|
|
127941
128104
|
if (res === "failed") return 1;
|
|
127942
128105
|
if (res !== "stopped") {
|
|
127943
|
-
console.log(
|
|
128106
|
+
console.log(import_picocolors52.default.dim(`Process pid ${spawned.pid} is no longer running \u2014 already stopped.`));
|
|
127944
128107
|
}
|
|
127945
128108
|
await cleanupSpawnedRecord(root);
|
|
127946
128109
|
return 0;
|
|
127947
128110
|
}
|
|
127948
128111
|
if (!isOwnHostProcess(spawned.pid, port, root, info2.args)) {
|
|
127949
128112
|
console.error(
|
|
127950
|
-
|
|
128113
|
+
import_picocolors52.default.red(
|
|
127951
128114
|
`Pid ${spawned.pid} args do not match "horus-source host --port ${port}". Got: "${info2.args.slice(0, 120)}". Aborting for safety.`
|
|
127952
128115
|
)
|
|
127953
128116
|
);
|
|
@@ -127956,12 +128119,12 @@ async function stopHost(root, hostUrl) {
|
|
|
127956
128119
|
const startTs = new Date(spawned.startedAt).getTime();
|
|
127957
128120
|
const recordedAgeS = Math.round((Date.now() - startTs) / 1e3);
|
|
127958
128121
|
if (!Number.isFinite(info2.etimeSeconds)) {
|
|
127959
|
-
console.error(
|
|
128122
|
+
console.error(import_picocolors52.default.red(`Could not read elapsed time for pid ${spawned.pid}. Aborting for safety.`));
|
|
127960
128123
|
return 1;
|
|
127961
128124
|
}
|
|
127962
128125
|
if (Math.abs(info2.etimeSeconds - recordedAgeS) > START_TIME_TOLERANCE_S) {
|
|
127963
128126
|
console.error(
|
|
127964
|
-
|
|
128127
|
+
import_picocolors52.default.red(
|
|
127965
128128
|
`Pid ${spawned.pid} age mismatch: record says ~${recordedAgeS}s, process reports ${info2.etimeSeconds}s elapsed. Possible PID reuse \u2014 aborting for safety.`
|
|
127966
128129
|
)
|
|
127967
128130
|
);
|
|
@@ -127971,17 +128134,17 @@ async function stopHost(root, hostUrl) {
|
|
|
127971
128134
|
try {
|
|
127972
128135
|
terminated = await terminatePid(spawned.pid);
|
|
127973
128136
|
} catch (err2) {
|
|
127974
|
-
console.error(
|
|
128137
|
+
console.error(import_picocolors52.default.red(`Failed to signal pid ${spawned.pid}: ${err2.message}`));
|
|
127975
128138
|
return 1;
|
|
127976
128139
|
}
|
|
127977
128140
|
if (!terminated) {
|
|
127978
128141
|
console.error(
|
|
127979
|
-
|
|
128142
|
+
import_picocolors52.default.red(`Host pid ${spawned.pid} did not exit even after SIGKILL \u2014 could not reclaim the port.`)
|
|
127980
128143
|
);
|
|
127981
128144
|
return 1;
|
|
127982
128145
|
}
|
|
127983
128146
|
console.log(
|
|
127984
|
-
`${
|
|
128147
|
+
`${import_picocolors52.default.green("\u2713")} Stopped source-intelligence host ` + import_picocolors52.default.dim(`(pid ${spawned.pid}, port ${port})`) + ` for ${root}`
|
|
127985
128148
|
);
|
|
127986
128149
|
if (await stopBackendServerPid(root, port) === "failed") return 1;
|
|
127987
128150
|
await cleanupSpawnedRecord(root);
|
|
@@ -128016,7 +128179,7 @@ async function stopBackendServerPid(root, port) {
|
|
|
128016
128179
|
if (info2 === null) return "none";
|
|
128017
128180
|
if (!isOwnHostProcess(rec.pid, port, root, info2.args)) {
|
|
128018
128181
|
console.log(
|
|
128019
|
-
|
|
128182
|
+
import_picocolors52.default.dim(
|
|
128020
128183
|
`Host pid ${rec.pid} is now an unrelated process (stale source/host.json / PID reuse) \u2014 host already gone.`
|
|
128021
128184
|
)
|
|
128022
128185
|
);
|
|
@@ -128026,17 +128189,17 @@ async function stopBackendServerPid(root, port) {
|
|
|
128026
128189
|
try {
|
|
128027
128190
|
terminated = await terminatePid(rec.pid);
|
|
128028
128191
|
} catch (err2) {
|
|
128029
|
-
console.error(
|
|
128192
|
+
console.error(import_picocolors52.default.red(`Failed to signal pid ${rec.pid}: ${err2.message}`));
|
|
128030
128193
|
return "failed";
|
|
128031
128194
|
}
|
|
128032
128195
|
if (!terminated) {
|
|
128033
128196
|
console.error(
|
|
128034
|
-
|
|
128197
|
+
import_picocolors52.default.red(`Host pid ${rec.pid} did not exit even after SIGKILL \u2014 could not reclaim the port.`)
|
|
128035
128198
|
);
|
|
128036
128199
|
return "failed";
|
|
128037
128200
|
}
|
|
128038
128201
|
console.log(
|
|
128039
|
-
`${
|
|
128202
|
+
`${import_picocolors52.default.green("\u2713")} Stopped source-intelligence host ` + import_picocolors52.default.dim(`(pid ${rec.pid}, port ${port})`) + ` for ${root}`
|
|
128040
128203
|
);
|
|
128041
128204
|
return "stopped";
|
|
128042
128205
|
}
|
|
@@ -128044,7 +128207,7 @@ async function stopAll() {
|
|
|
128044
128207
|
const registry2 = readRegistry();
|
|
128045
128208
|
const projects2 = Object.entries(registry2.projects);
|
|
128046
128209
|
if (projects2.length === 0) {
|
|
128047
|
-
console.log(
|
|
128210
|
+
console.log(import_picocolors52.default.dim("No registered projects."));
|
|
128048
128211
|
return 0;
|
|
128049
128212
|
}
|
|
128050
128213
|
let stopped = 0;
|
|
@@ -128056,17 +128219,17 @@ async function stopAll() {
|
|
|
128056
128219
|
if (!healthy && readSpawnedHost(entry.root) === null && readSourceHostPid(entry.root) === null) {
|
|
128057
128220
|
continue;
|
|
128058
128221
|
}
|
|
128059
|
-
console.log(` Stopping ${
|
|
128222
|
+
console.log(` Stopping ${import_picocolors52.default.bold(name2)} ${import_picocolors52.default.dim(`(${hostUrl})`)}`);
|
|
128060
128223
|
const code = await stopHost(entry.root, hostUrl);
|
|
128061
128224
|
if (code === 0) stopped++;
|
|
128062
128225
|
else failed++;
|
|
128063
128226
|
}
|
|
128064
128227
|
if (stopped === 0 && failed === 0) {
|
|
128065
|
-
console.log(
|
|
128228
|
+
console.log(import_picocolors52.default.dim("No running source-intelligence hosts found."));
|
|
128066
128229
|
} else {
|
|
128067
128230
|
console.log(
|
|
128068
128231
|
`
|
|
128069
|
-
Stopped ${stopped} host(s)${failed > 0 ?
|
|
128232
|
+
Stopped ${stopped} host(s)${failed > 0 ? import_picocolors52.default.red(`, ${failed} failed`) : ""}.`
|
|
128070
128233
|
);
|
|
128071
128234
|
}
|
|
128072
128235
|
return failed > 0 ? 1 : 0;
|
|
@@ -128154,7 +128317,7 @@ function extractPort(hostUrl) {
|
|
|
128154
128317
|
|
|
128155
128318
|
// ../../packages/cli/src/commands/hosts.ts
|
|
128156
128319
|
init_cjs_shims();
|
|
128157
|
-
var
|
|
128320
|
+
var import_picocolors53 = __toESM(require_picocolors(), 1);
|
|
128158
128321
|
var import_node_path29 = require("path");
|
|
128159
128322
|
init_src();
|
|
128160
128323
|
|
|
@@ -128266,14 +128429,14 @@ async function runHosts(opts = {}) {
|
|
|
128266
128429
|
for (const row of rows) {
|
|
128267
128430
|
if (row.hostUrl === null) continue;
|
|
128268
128431
|
printedAny = true;
|
|
128269
|
-
const status = row.live ?
|
|
128432
|
+
const status = row.live ? import_picocolors53.default.green("\u25CF running") : row.healthy && row.servesRepo === false ? import_picocolors53.default.yellow("\u25CF foreign \u2014 port serves another repo") : import_picocolors53.default.red("\u25CF stopped");
|
|
128270
128433
|
const port = row.port ?? "?";
|
|
128271
128434
|
console.log(
|
|
128272
|
-
` ${status} ${
|
|
128435
|
+
` ${status} ${import_picocolors53.default.bold(row.name.padEnd(24))} port ${String(port).padEnd(6)} ${import_picocolors53.default.dim(row.root)}`
|
|
128273
128436
|
);
|
|
128274
128437
|
}
|
|
128275
128438
|
const noHost = rows.filter((r) => r.hostUrl === null);
|
|
128276
|
-
for (const row of noHost) console.log(` ${
|
|
128439
|
+
for (const row of noHost) console.log(` ${import_picocolors53.default.dim("\u25CB no host")} ${import_picocolors53.default.dim(row.name)}`);
|
|
128277
128440
|
if (printedAny || noHost.length > 0) console.log("");
|
|
128278
128441
|
const claimedPids = /* @__PURE__ */ new Set();
|
|
128279
128442
|
for (const [, entry] of projects2) {
|
|
@@ -128286,37 +128449,37 @@ async function runHosts(opts = {}) {
|
|
|
128286
128449
|
let reapFailed = 0;
|
|
128287
128450
|
if (orphans.length > 0) {
|
|
128288
128451
|
console.log(
|
|
128289
|
-
|
|
128452
|
+
import_picocolors53.default.yellow(` \u26A0 ${orphans.length} orphaned source host(s) \u2014 no registered repo owns them:`)
|
|
128290
128453
|
);
|
|
128291
|
-
for (const o5 of orphans) console.log(
|
|
128454
|
+
for (const o5 of orphans) console.log(import_picocolors53.default.dim(` pid ${o5.pid} port ${o5.port}`));
|
|
128292
128455
|
if (opts.reap) {
|
|
128293
128456
|
let reaped = 0;
|
|
128294
128457
|
for (const o5 of orphans) {
|
|
128295
128458
|
if (await reapPid(o5.pid)) {
|
|
128296
128459
|
reaped++;
|
|
128297
|
-
console.log(` ${
|
|
128460
|
+
console.log(` ${import_picocolors53.default.green("\u2713")} reaped pid ${o5.pid} ${import_picocolors53.default.dim(`(port ${o5.port})`)}`);
|
|
128298
128461
|
} else {
|
|
128299
128462
|
reapFailed++;
|
|
128300
|
-
console.log(
|
|
128463
|
+
console.log(import_picocolors53.default.red(` \u2717 could not stop pid ${o5.pid} (port ${o5.port})`));
|
|
128301
128464
|
}
|
|
128302
128465
|
}
|
|
128303
|
-
console.log(
|
|
128466
|
+
console.log(import_picocolors53.default.dim(` Reaped ${reaped}/${orphans.length} orphan(s).`));
|
|
128304
128467
|
} else {
|
|
128305
|
-
console.log(
|
|
128468
|
+
console.log(import_picocolors53.default.dim(" Run `horus hosts --reap` to stop them."));
|
|
128306
128469
|
}
|
|
128307
128470
|
console.log("");
|
|
128308
128471
|
}
|
|
128309
128472
|
if (projects2.length === 0 && orphans.length === 0) {
|
|
128310
|
-
console.log(
|
|
128473
|
+
console.log(import_picocolors53.default.dim("No registered projects. Run `horus init` in a repo first."));
|
|
128311
128474
|
return 0;
|
|
128312
128475
|
}
|
|
128313
128476
|
if (!printedAny && orphans.length === 0) {
|
|
128314
|
-
console.log(
|
|
128477
|
+
console.log(import_picocolors53.default.dim("No source-intelligence hosts found. Run `horus init` to start one."));
|
|
128315
128478
|
return 0;
|
|
128316
128479
|
}
|
|
128317
128480
|
const running = countDistinctLiveHosts(rows);
|
|
128318
128481
|
console.log(
|
|
128319
|
-
|
|
128482
|
+
import_picocolors53.default.dim(
|
|
128320
128483
|
`${running} running${orphans.length ? ` \xB7 ${orphans.length} orphan(s)` : ""} \xB7 horus hosts --reap to clear orphans \xB7 horus stop --all to stop everything`
|
|
128321
128484
|
)
|
|
128322
128485
|
);
|
|
@@ -128333,7 +128496,7 @@ function extractPort2(hostUrl) {
|
|
|
128333
128496
|
|
|
128334
128497
|
// ../../packages/cli/src/commands/doctor.ts
|
|
128335
128498
|
init_cjs_shims();
|
|
128336
|
-
var
|
|
128499
|
+
var import_picocolors54 = __toESM(require_picocolors(), 1);
|
|
128337
128500
|
init_src();
|
|
128338
128501
|
var CONNECTOR_CHECKS = {
|
|
128339
128502
|
// Elasticsearch (runtime logs)
|
|
@@ -128473,9 +128636,9 @@ var CONNECTOR_CHECKS = {
|
|
|
128473
128636
|
};
|
|
128474
128637
|
var DOCTOR_CONNECTOR_KEYS = Object.keys(CONNECTOR_CHECKS);
|
|
128475
128638
|
function mark2(status) {
|
|
128476
|
-
if (status === "pass") return
|
|
128477
|
-
if (status === "warn") return
|
|
128478
|
-
return
|
|
128639
|
+
if (status === "pass") return import_picocolors54.default.green("\u2713");
|
|
128640
|
+
if (status === "warn") return import_picocolors54.default.yellow("~");
|
|
128641
|
+
return import_picocolors54.default.red("\u2717");
|
|
128479
128642
|
}
|
|
128480
128643
|
async function runDoctor(opts) {
|
|
128481
128644
|
const cwd = opts?.cwd ?? process.cwd();
|
|
@@ -128633,15 +128796,15 @@ async function runDoctor(opts) {
|
|
|
128633
128796
|
write(JSON.stringify(output, null, 2));
|
|
128634
128797
|
return hasFailure ? 1 : 0;
|
|
128635
128798
|
}
|
|
128636
|
-
write(
|
|
128799
|
+
write(import_picocolors54.default.bold("\nHorus readiness check\n"));
|
|
128637
128800
|
for (const check2 of checks) {
|
|
128638
|
-
write(` ${mark2(check2.status)} ${
|
|
128801
|
+
write(` ${mark2(check2.status)} ${import_picocolors54.default.bold(check2.label.padEnd(26))} ${import_picocolors54.default.dim(check2.detail)}`);
|
|
128639
128802
|
if (check2.next) {
|
|
128640
|
-
write(` ${
|
|
128803
|
+
write(` ${import_picocolors54.default.dim("\u2192 " + check2.next)}`);
|
|
128641
128804
|
}
|
|
128642
128805
|
}
|
|
128643
128806
|
write("");
|
|
128644
|
-
write(
|
|
128807
|
+
write(import_picocolors54.default.dim(" Hit a bug or a missing capability? Report it: horus report"));
|
|
128645
128808
|
write("");
|
|
128646
128809
|
return hasFailure ? 1 : 0;
|
|
128647
128810
|
}
|
|
@@ -128649,17 +128812,17 @@ async function runDoctor(opts) {
|
|
|
128649
128812
|
// ../../packages/cli/src/commands/providers-doctor.ts
|
|
128650
128813
|
init_cjs_shims();
|
|
128651
128814
|
var import_node_child_process13 = require("child_process");
|
|
128652
|
-
var
|
|
128815
|
+
var import_picocolors55 = __toESM(require_picocolors(), 1);
|
|
128653
128816
|
init_src();
|
|
128654
128817
|
function statusMark(status) {
|
|
128655
|
-
if (status === "ready") return
|
|
128656
|
-
if (status === "installed") return
|
|
128657
|
-
return
|
|
128818
|
+
if (status === "ready") return import_picocolors55.default.green("\u2713");
|
|
128819
|
+
if (status === "installed") return import_picocolors55.default.yellow("~");
|
|
128820
|
+
return import_picocolors55.default.red("\u2717");
|
|
128658
128821
|
}
|
|
128659
128822
|
function statusLabel(status) {
|
|
128660
|
-
if (status === "ready") return
|
|
128661
|
-
if (status === "installed") return
|
|
128662
|
-
return
|
|
128823
|
+
if (status === "ready") return import_picocolors55.default.green("ready");
|
|
128824
|
+
if (status === "installed") return import_picocolors55.default.yellow("installed (not configured)");
|
|
128825
|
+
return import_picocolors55.default.dim("not found on PATH");
|
|
128663
128826
|
}
|
|
128664
128827
|
function detectBinary(id) {
|
|
128665
128828
|
const result = (0, import_node_child_process13.spawnSync)(id, ["--version"], { stdio: "pipe", timeout: 2e3 });
|
|
@@ -128676,7 +128839,7 @@ async function runProvidersDoctorCommand(opts) {
|
|
|
128676
128839
|
const registry2 = opts?.registry ?? DEFAULT_LOCAL_PROVIDER_REGISTRY;
|
|
128677
128840
|
const write = opts?.write ?? ((line2) => console.log(line2));
|
|
128678
128841
|
const results = buildProviderResults(registry2, opts?._detect);
|
|
128679
|
-
write(
|
|
128842
|
+
write(import_picocolors55.default.bold("\nLocal AI providers\n"));
|
|
128680
128843
|
for (const result of results) {
|
|
128681
128844
|
const descriptor = registry2.get(result.id);
|
|
128682
128845
|
const name2 = descriptor?.displayName ?? result.id;
|
|
@@ -128684,11 +128847,11 @@ async function runProvidersDoctorCommand(opts) {
|
|
|
128684
128847
|
` ${statusMark(result.status)} ${result.id.padEnd(8)} ${name2.padEnd(22)} ${statusLabel(result.status)}`
|
|
128685
128848
|
);
|
|
128686
128849
|
if (result.status !== "ready" && result.detail) {
|
|
128687
|
-
write(` ${
|
|
128850
|
+
write(` ${import_picocolors55.default.dim("\u2192 " + result.detail)}`);
|
|
128688
128851
|
}
|
|
128689
128852
|
}
|
|
128690
128853
|
write("");
|
|
128691
|
-
write(
|
|
128854
|
+
write(import_picocolors55.default.bold("Cloud AI providers\n"));
|
|
128692
128855
|
let source = null;
|
|
128693
128856
|
if (opts?._anthropicKey !== void 0) {
|
|
128694
128857
|
source = opts._anthropicKey ? "env" : null;
|
|
@@ -128703,18 +128866,18 @@ async function runProvidersDoctorCommand(opts) {
|
|
|
128703
128866
|
}
|
|
128704
128867
|
if (source === "config") {
|
|
128705
128868
|
write(
|
|
128706
|
-
` ${
|
|
128869
|
+
` ${import_picocolors55.default.green("\u2713")} ${"anthropic".padEnd(8)} ${"Anthropic Claude API".padEnd(22)} ${import_picocolors55.default.green("configured (local .horus config)")}`
|
|
128707
128870
|
);
|
|
128708
128871
|
} else if (source === "env") {
|
|
128709
128872
|
write(
|
|
128710
|
-
` ${
|
|
128873
|
+
` ${import_picocolors55.default.green("\u2713")} ${"anthropic".padEnd(8)} ${"Anthropic Claude API".padEnd(22)} ${import_picocolors55.default.green("configured (ANTHROPIC_API_KEY env)")}`
|
|
128711
128874
|
);
|
|
128712
128875
|
} else {
|
|
128713
128876
|
write(
|
|
128714
|
-
` ${
|
|
128877
|
+
` ${import_picocolors55.default.red("\u2717")} ${"anthropic".padEnd(8)} ${"Anthropic Claude API".padEnd(22)} ${import_picocolors55.default.dim("not configured")}`
|
|
128715
128878
|
);
|
|
128716
128879
|
write(
|
|
128717
|
-
` ${
|
|
128880
|
+
` ${import_picocolors55.default.dim("\u2192 run `horus connect ai` (or set ANTHROPIC_API_KEY) to enable `horus investigate --ai`")}`
|
|
128718
128881
|
);
|
|
128719
128882
|
}
|
|
128720
128883
|
write("");
|
|
@@ -128723,7 +128886,7 @@ async function runProvidersDoctorCommand(opts) {
|
|
|
128723
128886
|
|
|
128724
128887
|
// ../../packages/cli/src/commands/readiness.ts
|
|
128725
128888
|
init_cjs_shims();
|
|
128726
|
-
var
|
|
128889
|
+
var import_picocolors56 = __toESM(require_picocolors(), 1);
|
|
128727
128890
|
init_src();
|
|
128728
128891
|
var READINESS_AI_CONTRACT = `Provide a clearly separated AI readiness summary with:
|
|
128729
128892
|
|
|
@@ -128746,9 +128909,9 @@ Recommended next action
|
|
|
128746
128909
|
Confidence / gaps
|
|
128747
128910
|
- Which checks Horus could verify vs. which require manual confirmation`;
|
|
128748
128911
|
function mark3(status) {
|
|
128749
|
-
if (status === "pass") return
|
|
128750
|
-
if (status === "warn") return
|
|
128751
|
-
return
|
|
128912
|
+
if (status === "pass") return import_picocolors56.default.green("\u2713");
|
|
128913
|
+
if (status === "warn") return import_picocolors56.default.yellow("~");
|
|
128914
|
+
return import_picocolors56.default.red("\u2717");
|
|
128752
128915
|
}
|
|
128753
128916
|
async function runReadiness(opts) {
|
|
128754
128917
|
const cwd = opts?.cwd ?? process.cwd();
|
|
@@ -128955,20 +129118,20 @@ async function runReadiness(opts) {
|
|
|
128955
129118
|
}
|
|
128956
129119
|
const blockingChecks = checks.filter((c4) => c4.blocking);
|
|
128957
129120
|
const optionalChecks = checks.filter((c4) => !c4.blocking);
|
|
128958
|
-
write(
|
|
128959
|
-
write(
|
|
129121
|
+
write(import_picocolors56.default.bold("\nHorus release readiness\n"));
|
|
129122
|
+
write(import_picocolors56.default.bold(" Blocking"));
|
|
128960
129123
|
for (const check2 of blockingChecks) {
|
|
128961
|
-
write(` ${mark3(check2.status)} ${
|
|
129124
|
+
write(` ${mark3(check2.status)} ${import_picocolors56.default.bold(check2.label.padEnd(22))} ${import_picocolors56.default.dim(check2.detail)}`);
|
|
128962
129125
|
if (check2.next) {
|
|
128963
|
-
write(` ${
|
|
129126
|
+
write(` ${import_picocolors56.default.dim("\u2192 " + check2.next)}`);
|
|
128964
129127
|
}
|
|
128965
129128
|
}
|
|
128966
129129
|
write("");
|
|
128967
|
-
write(
|
|
129130
|
+
write(import_picocolors56.default.bold(" Optional"));
|
|
128968
129131
|
for (const check2 of optionalChecks) {
|
|
128969
|
-
write(` ${mark3(check2.status)} ${
|
|
129132
|
+
write(` ${mark3(check2.status)} ${import_picocolors56.default.bold(check2.label.padEnd(22))} ${import_picocolors56.default.dim(check2.detail)}`);
|
|
128970
129133
|
if (check2.next) {
|
|
128971
|
-
write(` ${
|
|
129134
|
+
write(` ${import_picocolors56.default.dim("\u2192 " + check2.next)}`);
|
|
128972
129135
|
}
|
|
128973
129136
|
}
|
|
128974
129137
|
write("");
|
|
@@ -128976,21 +129139,21 @@ async function runReadiness(opts) {
|
|
|
128976
129139
|
const optionalWarns = optionalChecks.filter((c4) => c4.status === "warn").length;
|
|
128977
129140
|
if (blockingFails.length === 0) {
|
|
128978
129141
|
if (optionalWarns === 0) {
|
|
128979
|
-
write(
|
|
129142
|
+
write(import_picocolors56.default.green(" Ready for demo/release."));
|
|
128980
129143
|
} else {
|
|
128981
129144
|
write(
|
|
128982
|
-
|
|
129145
|
+
import_picocolors56.default.yellow(
|
|
128983
129146
|
` Ready for a basic demo. ${optionalWarns} optional item(s) not configured \u2014 investigation evidence will be limited.`
|
|
128984
129147
|
)
|
|
128985
129148
|
);
|
|
128986
129149
|
}
|
|
128987
129150
|
} else {
|
|
128988
129151
|
write(
|
|
128989
|
-
|
|
129152
|
+
import_picocolors56.default.red(
|
|
128990
129153
|
` Not ready. ${blockingFails.length} blocking item(s) must be resolved before demo/release.`
|
|
128991
129154
|
)
|
|
128992
129155
|
);
|
|
128993
|
-
write(
|
|
129156
|
+
write(import_picocolors56.default.dim(" Re-run `horus readiness` after resolving the items above."));
|
|
128994
129157
|
}
|
|
128995
129158
|
write("");
|
|
128996
129159
|
if (opts?.ai) {
|
|
@@ -129005,7 +129168,7 @@ async function runReadiness(opts) {
|
|
|
129005
129168
|
});
|
|
129006
129169
|
console.log("\n" + renderInterpretation(result));
|
|
129007
129170
|
if (!result.ok) {
|
|
129008
|
-
console.error(
|
|
129171
|
+
console.error(import_picocolors56.default.yellow(`[ai] ${result.warning}`));
|
|
129009
129172
|
}
|
|
129010
129173
|
}
|
|
129011
129174
|
return blockingFails.length > 0 ? 1 : 0;
|
|
@@ -129013,7 +129176,7 @@ async function runReadiness(opts) {
|
|
|
129013
129176
|
|
|
129014
129177
|
// ../../packages/cli/src/commands/db.ts
|
|
129015
129178
|
init_cjs_shims();
|
|
129016
|
-
var
|
|
129179
|
+
var import_picocolors57 = __toESM(require_picocolors(), 1);
|
|
129017
129180
|
function redactUrl2(url) {
|
|
129018
129181
|
try {
|
|
129019
129182
|
const u3 = new URL(url);
|
|
@@ -129027,33 +129190,33 @@ async function runDbImport(opts) {
|
|
|
129027
129190
|
const from = opts.from ?? process.env["DATABASE_URL"];
|
|
129028
129191
|
if (!from || from.trim() === "") {
|
|
129029
129192
|
console.error(
|
|
129030
|
-
|
|
129193
|
+
import_picocolors57.default.red("No source database to import from.") + import_picocolors57.default.dim(" Pass --from <postgres-url> (or set DATABASE_URL).")
|
|
129031
129194
|
);
|
|
129032
129195
|
return 1;
|
|
129033
129196
|
}
|
|
129034
129197
|
const { db, sql: sql2 } = await openDb();
|
|
129035
129198
|
try {
|
|
129036
129199
|
console.log(
|
|
129037
|
-
|
|
129200
|
+
import_picocolors57.default.dim(`Importing from ${redactUrl2(from)} into the embedded database (${localDbPath()})\u2026`)
|
|
129038
129201
|
);
|
|
129039
129202
|
const counts = await importFromPostgres(from, db);
|
|
129040
129203
|
const total = Object.values(counts).reduce((a2, b5) => a2 + b5, 0);
|
|
129041
129204
|
for (const [table, n4] of Object.entries(counts)) {
|
|
129042
|
-
console.log(` ${
|
|
129205
|
+
console.log(` ${import_picocolors57.default.bold(String(n4).padStart(6))} ${table}`);
|
|
129043
129206
|
}
|
|
129044
129207
|
console.log(
|
|
129045
|
-
|
|
129208
|
+
import_picocolors57.default.green(`\u2713 Imported ${total} row(s) from Postgres into the embedded database.`)
|
|
129046
129209
|
);
|
|
129047
129210
|
if (total === 0) {
|
|
129048
|
-
console.log(
|
|
129211
|
+
console.log(import_picocolors57.default.dim(" (nothing to copy \u2014 the source had no investigation/memory rows)"));
|
|
129049
129212
|
}
|
|
129050
129213
|
return 0;
|
|
129051
129214
|
} catch (err2) {
|
|
129052
129215
|
if (err2 instanceof CloudDatabaseUrlError) {
|
|
129053
|
-
console.error(
|
|
129216
|
+
console.error(import_picocolors57.default.red(err2.message));
|
|
129054
129217
|
return 1;
|
|
129055
129218
|
}
|
|
129056
|
-
console.error(
|
|
129219
|
+
console.error(import_picocolors57.default.red(`Import failed: ${err2.message}`));
|
|
129057
129220
|
return 1;
|
|
129058
129221
|
} finally {
|
|
129059
129222
|
await sql2.end();
|
|
@@ -129066,7 +129229,7 @@ var import_node_fs27 = require("fs");
|
|
|
129066
129229
|
var import_node_path30 = require("path");
|
|
129067
129230
|
var import_node_os11 = require("os");
|
|
129068
129231
|
var import_promises3 = require("readline/promises");
|
|
129069
|
-
var
|
|
129232
|
+
var import_picocolors58 = __toESM(require_picocolors(), 1);
|
|
129070
129233
|
var SUPPORTED_TARGETS = [
|
|
129071
129234
|
"claude",
|
|
129072
129235
|
"codex",
|
|
@@ -129361,8 +129524,8 @@ async function confirm(message) {
|
|
|
129361
129524
|
async function runSkillInstall(target, opts) {
|
|
129362
129525
|
const log = opts.write ?? ((line2) => console.log(line2));
|
|
129363
129526
|
if (!isValidTarget(target)) {
|
|
129364
|
-
log(`${
|
|
129365
|
-
log(
|
|
129527
|
+
log(`${import_picocolors58.default.red("\u2717")} Unknown target: ${import_picocolors58.default.bold(target)}`);
|
|
129528
|
+
log(import_picocolors58.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
129366
129529
|
return 1;
|
|
129367
129530
|
}
|
|
129368
129531
|
const outPath = getSkillInstallPath(target, { global: opts.global, cwd: opts.cwd });
|
|
@@ -129375,54 +129538,54 @@ async function runSkillInstall(target, opts) {
|
|
|
129375
129538
|
`Found old flat skill file at ${legacyPath}. Replace it with the new directory layout?`
|
|
129376
129539
|
);
|
|
129377
129540
|
if (!confirmed) {
|
|
129378
|
-
log(`${
|
|
129379
|
-
log(
|
|
129541
|
+
log(`${import_picocolors58.default.yellow("!")} Migration cancelled; existing skill left untouched.`);
|
|
129542
|
+
log(import_picocolors58.default.dim(" Pass --force to replace without prompting."));
|
|
129380
129543
|
return 1;
|
|
129381
129544
|
}
|
|
129382
129545
|
}
|
|
129383
129546
|
try {
|
|
129384
129547
|
(0, import_node_fs27.rmSync)(legacyPath);
|
|
129385
|
-
log(`${
|
|
129548
|
+
log(`${import_picocolors58.default.yellow("!")} Replaced old flat skill file: ${legacyPath}`);
|
|
129386
129549
|
} catch (err2) {
|
|
129387
129550
|
log(
|
|
129388
|
-
`${
|
|
129551
|
+
`${import_picocolors58.default.red("\u2717")} Could not remove legacy skill file ${legacyPath}: ${err2.message}`
|
|
129389
129552
|
);
|
|
129390
129553
|
return 1;
|
|
129391
129554
|
}
|
|
129392
129555
|
}
|
|
129393
129556
|
}
|
|
129394
129557
|
if ((0, import_node_fs27.existsSync)(outPath) && !opts.force) {
|
|
129395
|
-
log(`${
|
|
129396
|
-
log(
|
|
129558
|
+
log(`${import_picocolors58.default.red("\u2717")} ${outPath} already exists`);
|
|
129559
|
+
log(import_picocolors58.default.dim(" pass --force to overwrite"));
|
|
129397
129560
|
return 1;
|
|
129398
129561
|
}
|
|
129399
129562
|
try {
|
|
129400
129563
|
(0, import_node_fs27.mkdirSync)((0, import_node_path30.dirname)(outPath), { recursive: true });
|
|
129401
129564
|
(0, import_node_fs27.writeFileSync)(outPath, content, "utf8");
|
|
129402
129565
|
} catch (err2) {
|
|
129403
|
-
log(`${
|
|
129566
|
+
log(`${import_picocolors58.default.red("\u2717")} Could not write ${outPath}: ${err2.message}`);
|
|
129404
129567
|
return 1;
|
|
129405
129568
|
}
|
|
129406
|
-
log(`${
|
|
129569
|
+
log(`${import_picocolors58.default.green("\u2713")} Horus skill installed \u2192 ${outPath}`);
|
|
129407
129570
|
if (target === "claude") {
|
|
129408
|
-
log(
|
|
129409
|
-
log(
|
|
129571
|
+
log(import_picocolors58.default.dim(" Claude Code will load this skill automatically."));
|
|
129572
|
+
log(import_picocolors58.default.dim(" Invoke it with: /horus"));
|
|
129410
129573
|
} else if (target === "gemini") {
|
|
129411
|
-
log(
|
|
129574
|
+
log(import_picocolors58.default.dim(" Gemini CLI will load this context file automatically."));
|
|
129412
129575
|
} else if (target === "cursor") {
|
|
129413
|
-
log(
|
|
129576
|
+
log(import_picocolors58.default.dim(" Cursor will load this rule automatically."));
|
|
129414
129577
|
} else if (target === "codex") {
|
|
129415
|
-
log(
|
|
129578
|
+
log(import_picocolors58.default.dim(" Codex CLI will load this file automatically."));
|
|
129416
129579
|
} else {
|
|
129417
|
-
log(
|
|
129580
|
+
log(import_picocolors58.default.dim(` Copy or reference this file in your ${target} agent instructions.`));
|
|
129418
129581
|
}
|
|
129419
129582
|
return 0;
|
|
129420
129583
|
}
|
|
129421
129584
|
async function runSkillPrint(target, opts) {
|
|
129422
129585
|
const log = opts.write ?? ((line2) => console.log(line2));
|
|
129423
129586
|
if (!isValidTarget(target)) {
|
|
129424
|
-
log(`${
|
|
129425
|
-
log(
|
|
129587
|
+
log(`${import_picocolors58.default.red("\u2717")} Unknown target: ${import_picocolors58.default.bold(target)}`);
|
|
129588
|
+
log(import_picocolors58.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
129426
129589
|
return 1;
|
|
129427
129590
|
}
|
|
129428
129591
|
process.stdout.write(generateSkillContent(target));
|
|
@@ -129431,8 +129594,8 @@ async function runSkillPrint(target, opts) {
|
|
|
129431
129594
|
async function runSkillPath(target, opts) {
|
|
129432
129595
|
const log = opts.write ?? ((line2) => console.log(line2));
|
|
129433
129596
|
if (!isValidTarget(target)) {
|
|
129434
|
-
log(`${
|
|
129435
|
-
log(
|
|
129597
|
+
log(`${import_picocolors58.default.red("\u2717")} Unknown target: ${import_picocolors58.default.bold(target)}`);
|
|
129598
|
+
log(import_picocolors58.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
129436
129599
|
return 1;
|
|
129437
129600
|
}
|
|
129438
129601
|
const outPath = getSkillInstallPath(target, { global: opts.global, cwd: opts.cwd });
|
|
@@ -129442,7 +129605,7 @@ async function runSkillPath(target, opts) {
|
|
|
129442
129605
|
|
|
129443
129606
|
// ../../packages/cli/src/commands/login.ts
|
|
129444
129607
|
init_cjs_shims();
|
|
129445
|
-
var
|
|
129608
|
+
var import_picocolors59 = __toESM(require_picocolors(), 1);
|
|
129446
129609
|
var sleep3 = (ms) => new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
129447
129610
|
async function loginWithToken(apiBaseUrl, token) {
|
|
129448
129611
|
const client = new CloudClient(apiBaseUrl, token);
|
|
@@ -129458,19 +129621,19 @@ async function loginWithToken(apiBaseUrl, token) {
|
|
|
129458
129621
|
}
|
|
129459
129622
|
});
|
|
129460
129623
|
console.log(
|
|
129461
|
-
`${
|
|
129624
|
+
`${import_picocolors59.default.green("\u2713")} Logged in as ${import_picocolors59.default.bold(me3.user.primaryEmail)}. Run ${import_picocolors59.default.bold("horus cloud link")} to connect this repo.`
|
|
129462
129625
|
);
|
|
129463
129626
|
return 0;
|
|
129464
129627
|
} catch (err2) {
|
|
129465
129628
|
if (err2 instanceof CloudOfflineError) {
|
|
129466
|
-
console.error(
|
|
129629
|
+
console.error(import_picocolors59.default.red(err2.message));
|
|
129467
129630
|
return 1;
|
|
129468
129631
|
}
|
|
129469
129632
|
if (err2 instanceof CloudError && err2.status === 401) {
|
|
129470
|
-
console.error(
|
|
129633
|
+
console.error(import_picocolors59.default.red("That token is not valid. Create a fresh one in the dashboard and try again."));
|
|
129471
129634
|
return 1;
|
|
129472
129635
|
}
|
|
129473
|
-
console.error(
|
|
129636
|
+
console.error(import_picocolors59.default.red(`Login failed: ${err2.message}`));
|
|
129474
129637
|
return 1;
|
|
129475
129638
|
}
|
|
129476
129639
|
}
|
|
@@ -129481,19 +129644,19 @@ async function loginWithBrowser(apiBaseUrl) {
|
|
|
129481
129644
|
session = await client.startCliSession();
|
|
129482
129645
|
} catch (err2) {
|
|
129483
129646
|
if (err2 instanceof CloudOfflineError) {
|
|
129484
|
-
console.error(
|
|
129647
|
+
console.error(import_picocolors59.default.red(err2.message));
|
|
129485
129648
|
return 1;
|
|
129486
129649
|
}
|
|
129487
|
-
console.error(
|
|
129650
|
+
console.error(import_picocolors59.default.red(`Could not start login: ${err2.message}`));
|
|
129488
129651
|
return 1;
|
|
129489
129652
|
}
|
|
129490
129653
|
console.log("");
|
|
129491
129654
|
console.log(` To sign in, open this URL in your browser:`);
|
|
129492
|
-
console.log(` ${
|
|
129655
|
+
console.log(` ${import_picocolors59.default.cyan(import_picocolors59.default.bold(session.verificationUri))}`);
|
|
129493
129656
|
console.log("");
|
|
129494
|
-
console.log(` and enter the code: ${
|
|
129657
|
+
console.log(` and enter the code: ${import_picocolors59.default.bold(session.userCode)}`);
|
|
129495
129658
|
console.log("");
|
|
129496
|
-
console.log(
|
|
129659
|
+
console.log(import_picocolors59.default.dim(` Waiting for approval\u2026 (press Ctrl+C to cancel)`));
|
|
129497
129660
|
openBrowser(session.verificationUriComplete);
|
|
129498
129661
|
const deadline = Date.now() + session.expiresIn * 1e3;
|
|
129499
129662
|
let intervalMs = Math.max(session.interval, 1) * 1e3;
|
|
@@ -129504,7 +129667,7 @@ async function loginWithBrowser(apiBaseUrl) {
|
|
|
129504
129667
|
poll = await client.pollCliSession(session.deviceCode);
|
|
129505
129668
|
} catch (err2) {
|
|
129506
129669
|
if (err2 instanceof CloudOfflineError) {
|
|
129507
|
-
console.error(
|
|
129670
|
+
console.error(import_picocolors59.default.red(`
|
|
129508
129671
|
${err2.message}`));
|
|
129509
129672
|
return 1;
|
|
129510
129673
|
}
|
|
@@ -129517,14 +129680,14 @@ ${err2.message}`));
|
|
|
129517
129680
|
intervalMs += 2e3;
|
|
129518
129681
|
break;
|
|
129519
129682
|
case "denied":
|
|
129520
|
-
console.error(
|
|
129683
|
+
console.error(import_picocolors59.default.red("\nLogin was denied in the browser."));
|
|
129521
129684
|
return 1;
|
|
129522
129685
|
case "expired":
|
|
129523
|
-
console.error(
|
|
129686
|
+
console.error(import_picocolors59.default.red("\nThis login request expired. Run `horus login` again."));
|
|
129524
129687
|
return 1;
|
|
129525
129688
|
case "approved":
|
|
129526
129689
|
if (!poll.token || !poll.account) {
|
|
129527
|
-
console.error(
|
|
129690
|
+
console.error(import_picocolors59.default.red("\nLogin approved but no token was returned. Try again."));
|
|
129528
129691
|
return 1;
|
|
129529
129692
|
}
|
|
129530
129693
|
writeAuth({
|
|
@@ -129534,12 +129697,12 @@ ${err2.message}`));
|
|
|
129534
129697
|
});
|
|
129535
129698
|
console.log(
|
|
129536
129699
|
`
|
|
129537
|
-
${
|
|
129700
|
+
${import_picocolors59.default.green("\u2713")} Logged in as ${import_picocolors59.default.bold(poll.account.email)}. Run ${import_picocolors59.default.bold("horus cloud link")} to connect this repo.`
|
|
129538
129701
|
);
|
|
129539
129702
|
return 0;
|
|
129540
129703
|
}
|
|
129541
129704
|
}
|
|
129542
|
-
console.error(
|
|
129705
|
+
console.error(import_picocolors59.default.red("\nTimed out waiting for approval. Run `horus login` again."));
|
|
129543
129706
|
return 1;
|
|
129544
129707
|
}
|
|
129545
129708
|
async function runLogin(opts = {}) {
|
|
@@ -129553,7 +129716,7 @@ async function runLogin(opts = {}) {
|
|
|
129553
129716
|
async function runLogout() {
|
|
129554
129717
|
const auth = readAuth();
|
|
129555
129718
|
if (!auth) {
|
|
129556
|
-
console.log(
|
|
129719
|
+
console.log(import_picocolors59.default.dim("Not logged in."));
|
|
129557
129720
|
return 0;
|
|
129558
129721
|
}
|
|
129559
129722
|
const session = authedClient();
|
|
@@ -129567,13 +129730,13 @@ async function runLogout() {
|
|
|
129567
129730
|
}
|
|
129568
129731
|
}
|
|
129569
129732
|
clearAuth();
|
|
129570
|
-
console.log(`${
|
|
129733
|
+
console.log(`${import_picocolors59.default.green("\u2713")} Logged out. Local mode still works.`);
|
|
129571
129734
|
return 0;
|
|
129572
129735
|
}
|
|
129573
129736
|
|
|
129574
129737
|
// ../../packages/cli/src/commands/cloud.ts
|
|
129575
129738
|
init_cjs_shims();
|
|
129576
|
-
var
|
|
129739
|
+
var import_picocolors60 = __toESM(require_picocolors(), 1);
|
|
129577
129740
|
init_src();
|
|
129578
129741
|
var import_promises4 = require("readline/promises");
|
|
129579
129742
|
|
|
@@ -129619,7 +129782,7 @@ async function runCloudLink(opts = {}) {
|
|
|
129619
129782
|
const root = repoRootOrCwd(opts.cwd);
|
|
129620
129783
|
const session = authedClient();
|
|
129621
129784
|
if (!session) {
|
|
129622
|
-
console.error(
|
|
129785
|
+
console.error(import_picocolors60.default.red(`Not logged in. Run ${import_picocolors60.default.bold("horus login")} first.`));
|
|
129623
129786
|
return 1;
|
|
129624
129787
|
}
|
|
129625
129788
|
let ctx;
|
|
@@ -129629,7 +129792,7 @@ async function runCloudLink(opts = {}) {
|
|
|
129629
129792
|
return reportCloudError(err2);
|
|
129630
129793
|
}
|
|
129631
129794
|
const remote = detectGitRemote(root);
|
|
129632
|
-
if (remote) console.log(
|
|
129795
|
+
if (remote) console.log(import_picocolors60.default.dim(`Detected git remote: ${remote.remoteUrl}`));
|
|
129633
129796
|
let resolved = null;
|
|
129634
129797
|
let target = opts.project;
|
|
129635
129798
|
if (!target) {
|
|
@@ -129645,7 +129808,7 @@ async function runCloudLink(opts = {}) {
|
|
|
129645
129808
|
const org = ctx.organizations.find((o5) => o5.id === match.organizationId);
|
|
129646
129809
|
if (ws && org) {
|
|
129647
129810
|
target = `${org.slug}/${ws.slug}/${match.slug}`;
|
|
129648
|
-
console.log(
|
|
129811
|
+
console.log(import_picocolors60.default.dim(`Matched existing project by remote: ${import_picocolors60.default.bold(target)}`));
|
|
129649
129812
|
}
|
|
129650
129813
|
}
|
|
129651
129814
|
}
|
|
@@ -129660,8 +129823,8 @@ async function runCloudLink(opts = {}) {
|
|
|
129660
129823
|
if (created === "aborted") return 1;
|
|
129661
129824
|
if (!created) {
|
|
129662
129825
|
console.error(
|
|
129663
|
-
|
|
129664
|
-
Run ${
|
|
129826
|
+
import_picocolors60.default.red("No project to link.") + `
|
|
129827
|
+
Run ${import_picocolors60.default.bold("horus cloud link")} in a TTY to pick or create one, pass a target (${import_picocolors60.default.bold("horus cloud link <org/workspace/project>")}), or create a project at ${import_picocolors60.default.bold("https://cloud.horus.sh")}.`
|
|
129665
129828
|
);
|
|
129666
129829
|
return 1;
|
|
129667
129830
|
}
|
|
@@ -129671,8 +129834,8 @@ async function runCloudLink(opts = {}) {
|
|
|
129671
129834
|
resolved = resolveTriple(ctx, target);
|
|
129672
129835
|
if (!resolved) {
|
|
129673
129836
|
console.error(
|
|
129674
|
-
|
|
129675
|
-
Run ${
|
|
129837
|
+
import_picocolors60.default.red(`You don't have access to ${import_picocolors60.default.bold(target)}.`) + `
|
|
129838
|
+
Run ${import_picocolors60.default.bold("horus context list")} to see available projects.`
|
|
129676
129839
|
);
|
|
129677
129840
|
return 1;
|
|
129678
129841
|
}
|
|
@@ -129685,10 +129848,10 @@ async function runCloudLink(opts = {}) {
|
|
|
129685
129848
|
project: resolved.project
|
|
129686
129849
|
});
|
|
129687
129850
|
console.log(
|
|
129688
|
-
`${
|
|
129851
|
+
`${import_picocolors60.default.green("\u2713")} Linked. Context for this repo is now ${import_picocolors60.default.bold(label)} ${import_picocolors60.default.dim("(cloud)")}.`
|
|
129689
129852
|
);
|
|
129690
129853
|
console.log(
|
|
129691
|
-
|
|
129854
|
+
import_picocolors60.default.dim(` Investigations here save to Horus Cloud. ${import_picocolors60.default.bold("horus context use local")} to switch back.`)
|
|
129692
129855
|
);
|
|
129693
129856
|
return 0;
|
|
129694
129857
|
}
|
|
@@ -129696,11 +129859,11 @@ async function runCloudUnlink(opts = {}) {
|
|
|
129696
129859
|
const root = repoRootOrCwd(opts.cwd);
|
|
129697
129860
|
const cfg = readCloudConfig(root);
|
|
129698
129861
|
if (!cfg || cfg.context !== "cloud") {
|
|
129699
|
-
console.log(
|
|
129862
|
+
console.log(import_picocolors60.default.dim("This repo isn't linked to a cloud project."));
|
|
129700
129863
|
return 0;
|
|
129701
129864
|
}
|
|
129702
129865
|
clearCloudConfig(root);
|
|
129703
|
-
console.log(`${
|
|
129866
|
+
console.log(`${import_picocolors60.default.green("\u2713")} Unlinked. This repo is back to ${import_picocolors60.default.bold("local")} mode.`);
|
|
129704
129867
|
return 0;
|
|
129705
129868
|
}
|
|
129706
129869
|
async function runCloudStatus(opts = {}) {
|
|
@@ -129708,18 +129871,18 @@ async function runCloudStatus(opts = {}) {
|
|
|
129708
129871
|
const cfg = readCloudConfig(root);
|
|
129709
129872
|
const session = authedClient();
|
|
129710
129873
|
if (!isCloudActive(cfg) || !cfg?.project) {
|
|
129711
|
-
console.log(`${
|
|
129712
|
-
console.log(`${
|
|
129874
|
+
console.log(`${import_picocolors60.default.bold("Context:")} local`);
|
|
129875
|
+
console.log(`${import_picocolors60.default.bold("Storage:")} local Postgres (~/.horus)`);
|
|
129713
129876
|
console.log(
|
|
129714
|
-
|
|
129877
|
+
import_picocolors60.default.dim(`Tip: ${import_picocolors60.default.bold("horus login")} then ${import_picocolors60.default.bold("horus cloud link")} to share investigations with your team.`)
|
|
129715
129878
|
);
|
|
129716
129879
|
return 0;
|
|
129717
129880
|
}
|
|
129718
129881
|
const triple = `${cfg.organization?.slug}/${cfg.workspace?.slug}/${cfg.project.slug}`;
|
|
129719
|
-
console.log(`${
|
|
129882
|
+
console.log(`${import_picocolors60.default.bold("Context:")} ${triple} ${import_picocolors60.default.dim("(cloud)")}`);
|
|
129720
129883
|
let projectLine = `${cfg.project.slug}`;
|
|
129721
129884
|
let metaLines = [];
|
|
129722
|
-
let account =
|
|
129885
|
+
let account = import_picocolors60.default.dim("not logged in");
|
|
129723
129886
|
if (session) {
|
|
129724
129887
|
account = session.auth.account.email;
|
|
129725
129888
|
try {
|
|
@@ -129734,9 +129897,9 @@ async function runCloudStatus(opts = {}) {
|
|
|
129734
129897
|
} catch {
|
|
129735
129898
|
}
|
|
129736
129899
|
}
|
|
129737
|
-
console.log(`${
|
|
129900
|
+
console.log(`${import_picocolors60.default.bold("Project:")} ${projectLine}`);
|
|
129738
129901
|
for (const line2 of metaLines) console.log(line2);
|
|
129739
|
-
console.log(`${
|
|
129902
|
+
console.log(`${import_picocolors60.default.bold("Account:")} ${account}`);
|
|
129740
129903
|
return 0;
|
|
129741
129904
|
}
|
|
129742
129905
|
async function runCloudSync(opts = {}) {
|
|
@@ -129744,13 +129907,13 @@ async function runCloudSync(opts = {}) {
|
|
|
129744
129907
|
const cfg = readCloudConfig(root);
|
|
129745
129908
|
if (!isCloudActive(cfg) || !cfg.project) {
|
|
129746
129909
|
console.error(
|
|
129747
|
-
|
|
129910
|
+
import_picocolors60.default.red("This repo isn't linked to a cloud project.") + ` Run ${import_picocolors60.default.bold("horus cloud link")} first.`
|
|
129748
129911
|
);
|
|
129749
129912
|
return 1;
|
|
129750
129913
|
}
|
|
129751
129914
|
const session = authedClient();
|
|
129752
129915
|
if (!session) {
|
|
129753
|
-
console.error(
|
|
129916
|
+
console.error(import_picocolors60.default.red(`Not logged in. Run ${import_picocolors60.default.bold("horus login")} first.`));
|
|
129754
129917
|
return 1;
|
|
129755
129918
|
}
|
|
129756
129919
|
let project;
|
|
@@ -129773,26 +129936,26 @@ async function runCloudSync(opts = {}) {
|
|
|
129773
129936
|
const target = `${cfg.organization?.slug}/${cfg.workspace?.slug}/${cfg.project.slug}`;
|
|
129774
129937
|
if (uploadable.length === 0) {
|
|
129775
129938
|
console.log(
|
|
129776
|
-
|
|
129939
|
+
import_picocolors60.default.dim(
|
|
129777
129940
|
`No local investigations with reports to upload.` + (skippedNoReport ? ` (${skippedNoReport} without a report skipped)` : "")
|
|
129778
129941
|
)
|
|
129779
129942
|
);
|
|
129780
129943
|
return 0;
|
|
129781
129944
|
}
|
|
129782
|
-
console.log(
|
|
129945
|
+
console.log(import_picocolors60.default.bold(`Will upload ${uploadable.length} investigation(s) to ${target} ${import_picocolors60.default.dim("(cloud)")}:`));
|
|
129783
129946
|
for (const c4 of uploadable.slice(0, 20)) {
|
|
129784
|
-
console.log(` ${
|
|
129947
|
+
console.log(` ${import_picocolors60.default.dim(c4.id.slice(0, 8))} ${(c4.title ?? "untitled").slice(0, 70)}`);
|
|
129785
129948
|
}
|
|
129786
|
-
if (uploadable.length > 20) console.log(
|
|
129787
|
-
if (skippedNoReport) console.log(
|
|
129949
|
+
if (uploadable.length > 20) console.log(import_picocolors60.default.dim(` \u2026and ${uploadable.length - 20} more`));
|
|
129950
|
+
if (skippedNoReport) console.log(import_picocolors60.default.dim(` (${skippedNoReport} local investigation(s) without a report will be skipped)`));
|
|
129788
129951
|
if (opts.dryRun) {
|
|
129789
|
-
console.log(
|
|
129952
|
+
console.log(import_picocolors60.default.dim("Dry run \u2014 nothing uploaded. Re-run without --dry-run to upload."));
|
|
129790
129953
|
return 0;
|
|
129791
129954
|
}
|
|
129792
129955
|
if (!opts.yes) {
|
|
129793
129956
|
if (!process.stdin.isTTY) {
|
|
129794
129957
|
console.error(
|
|
129795
|
-
|
|
129958
|
+
import_picocolors60.default.yellow(`Re-run with ${import_picocolors60.default.bold("--yes")} to upload, or ${import_picocolors60.default.bold("--dry-run")} to preview only.`)
|
|
129796
129959
|
);
|
|
129797
129960
|
return 1;
|
|
129798
129961
|
}
|
|
@@ -129800,7 +129963,7 @@ async function runCloudSync(opts = {}) {
|
|
|
129800
129963
|
try {
|
|
129801
129964
|
const answer = (await rl.question(`Upload ${uploadable.length} investigation(s) to ${target}? (y/N) `)).trim().toLowerCase();
|
|
129802
129965
|
if (answer !== "y" && answer !== "yes") {
|
|
129803
|
-
console.log(
|
|
129966
|
+
console.log(import_picocolors60.default.dim("Aborted. Nothing uploaded."));
|
|
129804
129967
|
return 0;
|
|
129805
129968
|
}
|
|
129806
129969
|
} finally {
|
|
@@ -129813,18 +129976,18 @@ async function runCloudSync(opts = {}) {
|
|
|
129813
129976
|
try {
|
|
129814
129977
|
const refs = await uploadInvestigationToCloud(session.client, cfg, c4.report, { db });
|
|
129815
129978
|
created++;
|
|
129816
|
-
console.log(`${
|
|
129979
|
+
console.log(`${import_picocolors60.default.green("\u2713")} ${import_picocolors60.default.dim(c4.id.slice(0, 8))} \u2192 ${refs.investigationId}`);
|
|
129817
129980
|
} catch (err2) {
|
|
129818
129981
|
failed++;
|
|
129819
|
-
console.error(`${
|
|
129982
|
+
console.error(`${import_picocolors60.default.red("\u2717")} ${import_picocolors60.default.dim(c4.id.slice(0, 8))} ${err2.message}`);
|
|
129820
129983
|
}
|
|
129821
129984
|
}
|
|
129822
129985
|
console.log("");
|
|
129823
129986
|
console.log(
|
|
129824
|
-
`${
|
|
129987
|
+
`${import_picocolors60.default.bold("Sync complete:")} ${import_picocolors60.default.green(`${created} uploaded`)}, ${skippedNoReport} skipped, ` + (failed ? import_picocolors60.default.red(`${failed} failed`) : "0 failed") + "."
|
|
129825
129988
|
);
|
|
129826
129989
|
console.log(
|
|
129827
|
-
|
|
129990
|
+
import_picocolors60.default.dim("Local data was not modified. Re-running is safe \u2014 duplicates are deduped by idempotency key.")
|
|
129828
129991
|
);
|
|
129829
129992
|
return failed > 0 ? 1 : 0;
|
|
129830
129993
|
} finally {
|
|
@@ -129835,8 +129998,8 @@ async function createProjectFromRepo(client, ctx, remote, yes) {
|
|
|
129835
129998
|
if (!process.stdin.isTTY && !yes) return null;
|
|
129836
129999
|
if (ctx.organizations.length === 0) {
|
|
129837
130000
|
console.error(
|
|
129838
|
-
|
|
129839
|
-
Create one at ${
|
|
130001
|
+
import_picocolors60.default.red("You're not a member of any organization yet.") + `
|
|
130002
|
+
Create one at ${import_picocolors60.default.bold("https://cloud.horus.sh")} first.`
|
|
129840
130003
|
);
|
|
129841
130004
|
return null;
|
|
129842
130005
|
}
|
|
@@ -129861,9 +130024,9 @@ async function createProjectFromRepo(client, ctx, remote, yes) {
|
|
|
129861
130024
|
const wsName = await ask2("New workspace name", repoName || "default");
|
|
129862
130025
|
const ws = await client.createWorkspace(org.id, { name: wsName });
|
|
129863
130026
|
workspace = { id: ws.id, slug: ws.slug };
|
|
129864
|
-
console.log(
|
|
130027
|
+
console.log(import_picocolors60.default.dim(`Created workspace ${import_picocolors60.default.bold(ws.slug)}.`));
|
|
129865
130028
|
} else {
|
|
129866
|
-
console.log(`Workspaces in ${
|
|
130029
|
+
console.log(`Workspaces in ${import_picocolors60.default.bold(org.slug)}:`);
|
|
129867
130030
|
orgWorkspaces.forEach((w4, i3) => console.log(` ${i3 + 1}) ${w4.slug}`));
|
|
129868
130031
|
console.log(` ${orgWorkspaces.length + 1}) + create a new workspace`);
|
|
129869
130032
|
const pick2 = Number(await ask2("Workspace number", "1"));
|
|
@@ -129871,7 +130034,7 @@ async function createProjectFromRepo(client, ctx, remote, yes) {
|
|
|
129871
130034
|
const wsName = await ask2("New workspace name", repoName || "default");
|
|
129872
130035
|
const ws = await client.createWorkspace(org.id, { name: wsName });
|
|
129873
130036
|
workspace = { id: ws.id, slug: ws.slug };
|
|
129874
|
-
console.log(
|
|
130037
|
+
console.log(import_picocolors60.default.dim(`Created workspace ${import_picocolors60.default.bold(ws.slug)}.`));
|
|
129875
130038
|
} else {
|
|
129876
130039
|
const chosen = orgWorkspaces[pick2 - 1] ?? orgWorkspaces[0];
|
|
129877
130040
|
workspace = { id: chosen.id, slug: chosen.slug };
|
|
@@ -129883,7 +130046,7 @@ async function createProjectFromRepo(client, ctx, remote, yes) {
|
|
|
129883
130046
|
remoteUrl: remote?.remoteUrl,
|
|
129884
130047
|
provider: remote ? inferProvider(remote.remoteUrl) : void 0
|
|
129885
130048
|
});
|
|
129886
|
-
console.log(
|
|
130049
|
+
console.log(import_picocolors60.default.dim(`Created project ${import_picocolors60.default.bold(project.slug)}.`));
|
|
129887
130050
|
return {
|
|
129888
130051
|
organization: { id: org.id, slug: org.slug },
|
|
129889
130052
|
workspace,
|
|
@@ -129899,7 +130062,7 @@ async function createProjectFromRepo(client, ctx, remote, yes) {
|
|
|
129899
130062
|
|
|
129900
130063
|
// ../../packages/cli/src/commands/telemetry.ts
|
|
129901
130064
|
init_cjs_shims();
|
|
129902
|
-
var
|
|
130065
|
+
var import_picocolors62 = __toESM(require_picocolors(), 1);
|
|
129903
130066
|
var import_node_crypto11 = require("crypto");
|
|
129904
130067
|
|
|
129905
130068
|
// ../../packages/cli/src/lib/telemetry/transport.ts
|
|
@@ -129960,7 +130123,7 @@ async function deleteRemoteTelemetry(installId, opts = {}) {
|
|
|
129960
130123
|
|
|
129961
130124
|
// ../../packages/cli/src/lib/telemetry/notice.ts
|
|
129962
130125
|
init_cjs_shims();
|
|
129963
|
-
var
|
|
130126
|
+
var import_picocolors61 = __toESM(require_picocolors(), 1);
|
|
129964
130127
|
var PRIVACY_URL = "https://horus.sh/privacy";
|
|
129965
130128
|
var SUPPRESS_FIRST_TOKEN = /* @__PURE__ */ new Set(["telemetry", "help"]);
|
|
129966
130129
|
var SUPPRESS_FLAGS = /* @__PURE__ */ new Set(["-V", "--version", "-h", "--help"]);
|
|
@@ -129972,11 +130135,11 @@ function shouldSuppressFor(argv) {
|
|
|
129972
130135
|
return firstToken != null && SUPPRESS_FIRST_TOKEN.has(firstToken);
|
|
129973
130136
|
}
|
|
129974
130137
|
function banner() {
|
|
129975
|
-
const b5 =
|
|
129976
|
-
const dim =
|
|
130138
|
+
const b5 = import_picocolors61.default.bold;
|
|
130139
|
+
const dim = import_picocolors61.default.dim;
|
|
129977
130140
|
return [
|
|
129978
130141
|
"",
|
|
129979
|
-
|
|
130142
|
+
import_picocolors61.default.cyan(b5("Horus collects anonymous usage data to improve the tool.")),
|
|
129980
130143
|
dim(" \u2022 On by default: command names, timings, success/failure, and where the"),
|
|
129981
130144
|
dim(" engine ran out of evidence. No file contents, queries, or secrets."),
|
|
129982
130145
|
dim(" \u2022 Off by default: your investigation inputs/outputs (opt in to help train"),
|
|
@@ -129984,7 +130147,7 @@ function banner() {
|
|
|
129984
130147
|
dim(" \u2022 If you use Horus Cloud, linked investigations sync to your workspace."),
|
|
129985
130148
|
"",
|
|
129986
130149
|
` ${dim("Opt out anytime:")} ${b5("horus telemetry disable")} ${dim("\xB7")} ${b5("HORUS_TELEMETRY=0")} ${dim("\xB7")} ${b5("DO_NOT_TRACK=1")}`,
|
|
129987
|
-
` ${dim("Details:")} ${
|
|
130150
|
+
` ${dim("Details:")} ${import_picocolors61.default.underline(PRIVACY_URL)}`,
|
|
129988
130151
|
""
|
|
129989
130152
|
].join("\n");
|
|
129990
130153
|
}
|
|
@@ -130007,45 +130170,45 @@ function maybeShowFirstRunNotice(argv = process.argv) {
|
|
|
130007
130170
|
|
|
130008
130171
|
// ../../packages/cli/src/commands/telemetry.ts
|
|
130009
130172
|
function onOff(enabled) {
|
|
130010
|
-
return enabled ?
|
|
130173
|
+
return enabled ? import_picocolors62.default.green("on") : import_picocolors62.default.dim("off");
|
|
130011
130174
|
}
|
|
130012
130175
|
function warnIfEnvOverrides() {
|
|
130013
130176
|
const decision = resolveConsent();
|
|
130014
130177
|
if (decision.forcedOff) {
|
|
130015
130178
|
console.log(
|
|
130016
|
-
|
|
130179
|
+
import_picocolors62.default.yellow(
|
|
130017
130180
|
`
|
|
130018
130181
|
Note: telemetry is currently forced off by your environment (${decision.reason}).`
|
|
130019
130182
|
)
|
|
130020
130183
|
);
|
|
130021
|
-
console.log(
|
|
130184
|
+
console.log(import_picocolors62.default.dim("Your saved preference will apply once that override is removed."));
|
|
130022
130185
|
} else if (decision.source === "ci") {
|
|
130023
130186
|
console.log(
|
|
130024
|
-
|
|
130187
|
+
import_picocolors62.default.yellow("\nNote: CI environment detected \u2014 telemetry stays off here regardless.")
|
|
130025
130188
|
);
|
|
130026
130189
|
}
|
|
130027
130190
|
}
|
|
130028
130191
|
async function runTelemetryStatus() {
|
|
130029
130192
|
const state = readTelemetryState();
|
|
130030
130193
|
const decision = resolveConsent({ state });
|
|
130031
|
-
console.log(
|
|
130194
|
+
console.log(import_picocolors62.default.bold("Horus telemetry"));
|
|
130032
130195
|
console.log(
|
|
130033
|
-
` Usage metadata (Tier A): ${onOff(decision.tierA)} ${
|
|
130196
|
+
` Usage metadata (Tier A): ${onOff(decision.tierA)} ${import_picocolors62.default.dim(`[${decision.source}]`)}`
|
|
130034
130197
|
);
|
|
130035
130198
|
console.log(` Content sharing (Tier B): ${onOff(decision.tierB)}`);
|
|
130036
|
-
console.log(
|
|
130199
|
+
console.log(import_picocolors62.default.dim(` Reason: ${decision.reason}`));
|
|
130037
130200
|
if (state) {
|
|
130038
|
-
console.log(
|
|
130201
|
+
console.log(import_picocolors62.default.dim(` Install ID: ${state.installId}`));
|
|
130039
130202
|
console.log(
|
|
130040
|
-
|
|
130203
|
+
import_picocolors62.default.dim(
|
|
130041
130204
|
` Saved: Tier A ${state.tierA.enabled ? "on" : "off"}, Tier B ${state.tierB.enabled ? "on" : "off"}`
|
|
130042
130205
|
)
|
|
130043
130206
|
);
|
|
130044
130207
|
} else {
|
|
130045
|
-
console.log(
|
|
130208
|
+
console.log(import_picocolors62.default.dim(" No saved preference yet (defaults apply)."));
|
|
130046
130209
|
}
|
|
130047
|
-
console.log(
|
|
130048
|
-
console.log(
|
|
130210
|
+
console.log(import_picocolors62.default.dim(` Config: ${telemetryPath()}`));
|
|
130211
|
+
console.log(import_picocolors62.default.dim(` Privacy: ${PRIVACY_URL}`));
|
|
130049
130212
|
if (!state || decision.source === "env" || decision.source === "ci") {
|
|
130050
130213
|
warnIfEnvOverrides();
|
|
130051
130214
|
}
|
|
@@ -130056,7 +130219,7 @@ async function runTelemetryEnable() {
|
|
|
130056
130219
|
s5.tierA.enabled = true;
|
|
130057
130220
|
if (!s5.tierA.noticeShownAt) s5.tierA.noticeShownAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
130058
130221
|
});
|
|
130059
|
-
console.log(
|
|
130222
|
+
console.log(import_picocolors62.default.green("Anonymous usage metadata (Tier A) is now ON. Thank you!"));
|
|
130060
130223
|
warnIfEnvOverrides();
|
|
130061
130224
|
return 0;
|
|
130062
130225
|
}
|
|
@@ -130066,7 +130229,7 @@ async function runTelemetryDisable() {
|
|
|
130066
130229
|
s5.tierB.enabled = false;
|
|
130067
130230
|
if (!s5.tierA.noticeShownAt) s5.tierA.noticeShownAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
130068
130231
|
});
|
|
130069
|
-
console.log(
|
|
130232
|
+
console.log(import_picocolors62.default.yellow("All telemetry is now OFF (Tier A and Tier B)."));
|
|
130070
130233
|
return 0;
|
|
130071
130234
|
}
|
|
130072
130235
|
async function runTelemetryEnableContent() {
|
|
@@ -130077,10 +130240,10 @@ async function runTelemetryEnableContent() {
|
|
|
130077
130240
|
if (!s5.tierA.noticeShownAt) s5.tierA.noticeShownAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
130078
130241
|
});
|
|
130079
130242
|
console.log(
|
|
130080
|
-
|
|
130243
|
+
import_picocolors62.default.green("Content sharing (Tier B) is now ON \u2014 redacted inputs/outputs help improve Horus.")
|
|
130081
130244
|
);
|
|
130082
|
-
console.log(
|
|
130083
|
-
console.log(
|
|
130245
|
+
console.log(import_picocolors62.default.dim("Content is scrubbed of secrets/PII before it ever leaves your machine."));
|
|
130246
|
+
console.log(import_picocolors62.default.dim(`What this means: ${PRIVACY_URL}`));
|
|
130084
130247
|
warnIfEnvOverrides();
|
|
130085
130248
|
return 0;
|
|
130086
130249
|
}
|
|
@@ -130088,7 +130251,7 @@ async function runTelemetryDisableContent() {
|
|
|
130088
130251
|
updateTelemetryState((s5) => {
|
|
130089
130252
|
s5.tierB.enabled = false;
|
|
130090
130253
|
});
|
|
130091
|
-
console.log(
|
|
130254
|
+
console.log(import_picocolors62.default.yellow("Content sharing (Tier B) is now OFF. Usage metadata is unchanged."));
|
|
130092
130255
|
return 0;
|
|
130093
130256
|
}
|
|
130094
130257
|
async function runTelemetryResetId() {
|
|
@@ -130096,8 +130259,8 @@ async function runTelemetryResetId() {
|
|
|
130096
130259
|
updateTelemetryState((s5) => {
|
|
130097
130260
|
s5.installId = next;
|
|
130098
130261
|
});
|
|
130099
|
-
console.log(
|
|
130100
|
-
console.log(
|
|
130262
|
+
console.log(import_picocolors62.default.green("Install ID reset."));
|
|
130263
|
+
console.log(import_picocolors62.default.dim(` New install ID: ${next}`));
|
|
130101
130264
|
return 0;
|
|
130102
130265
|
}
|
|
130103
130266
|
async function runTelemetryDelete() {
|
|
@@ -130105,9 +130268,9 @@ async function runTelemetryDelete() {
|
|
|
130105
130268
|
if (installId) await deleteRemoteTelemetry(installId);
|
|
130106
130269
|
deleteTelemetryState();
|
|
130107
130270
|
clearSpool();
|
|
130108
|
-
console.log(
|
|
130271
|
+
console.log(import_picocolors62.default.green("Telemetry deleted \u2014 local state cleared and a server purge requested."));
|
|
130109
130272
|
console.log(
|
|
130110
|
-
|
|
130273
|
+
import_picocolors62.default.dim(
|
|
130111
130274
|
"Next run will treat this as a fresh install and re-show the notice. If the purge could not reach the server (offline), re-run this command when back online."
|
|
130112
130275
|
)
|
|
130113
130276
|
);
|
|
@@ -130152,7 +130315,7 @@ function installCommandTelemetry(program2) {
|
|
|
130152
130315
|
init_cjs_shims();
|
|
130153
130316
|
var import_promises5 = require("fs/promises");
|
|
130154
130317
|
var import_node_path31 = require("path");
|
|
130155
|
-
var
|
|
130318
|
+
var import_picocolors63 = __toESM(require_picocolors(), 1);
|
|
130156
130319
|
init_src();
|
|
130157
130320
|
function resolveProject2(config2, repo) {
|
|
130158
130321
|
let project;
|
|
@@ -130161,7 +130324,7 @@ function resolveProject2(config2, repo) {
|
|
|
130161
130324
|
} catch {
|
|
130162
130325
|
}
|
|
130163
130326
|
if (!project) {
|
|
130164
|
-
console.error(
|
|
130327
|
+
console.error(import_picocolors63.default.red("Could not resolve a project \u2014 pass --repo <name> or run inside a repo."));
|
|
130165
130328
|
return null;
|
|
130166
130329
|
}
|
|
130167
130330
|
return project;
|
|
@@ -130170,7 +130333,7 @@ function readSlice(opts) {
|
|
|
130170
130333
|
let source;
|
|
130171
130334
|
if (opts.source !== void 0) {
|
|
130172
130335
|
if (!isOutcomeSource(opts.source)) {
|
|
130173
|
-
console.error(
|
|
130336
|
+
console.error(import_picocolors63.default.red(`Unknown --source "${opts.source}" (one of: feedback, confirm).`));
|
|
130174
130337
|
return null;
|
|
130175
130338
|
}
|
|
130176
130339
|
source = opts.source;
|
|
@@ -130178,7 +130341,7 @@ function readSlice(opts) {
|
|
|
130178
130341
|
let since;
|
|
130179
130342
|
if (opts.days !== void 0) {
|
|
130180
130343
|
if (!Number.isFinite(opts.days) || opts.days <= 0) {
|
|
130181
|
-
console.error(
|
|
130344
|
+
console.error(import_picocolors63.default.red("--days must be a positive number."));
|
|
130182
130345
|
return null;
|
|
130183
130346
|
}
|
|
130184
130347
|
since = new Date(Date.now() - opts.days * 24 * 60 * 60 * 1e3);
|
|
@@ -130226,26 +130389,26 @@ async function runEvalBuild(opts) {
|
|
|
130226
130389
|
if (opts.json) {
|
|
130227
130390
|
console.log(JSON.stringify({ project, corpusPath, manifestPath, manifest }, null, 2));
|
|
130228
130391
|
} else {
|
|
130229
|
-
console.log(
|
|
130392
|
+
console.log(import_picocolors63.default.bold(`Eval corpus \u2014 ${project}`));
|
|
130230
130393
|
console.log(
|
|
130231
|
-
` Rows: ${
|
|
130394
|
+
` Rows: ${import_picocolors63.default.green(String(build.rows.length))} ` + import_picocolors63.default.dim(
|
|
130232
130395
|
`(evaluated ${build.evaluated}, quarantined ${build.quarantined.length}, unjoinable ${build.unjoinable.length})`
|
|
130233
130396
|
)
|
|
130234
130397
|
);
|
|
130235
130398
|
console.log(
|
|
130236
|
-
|
|
130399
|
+
import_picocolors63.default.dim(
|
|
130237
130400
|
` Class balance: ${build.classBalance.yes} yes, ${build.classBalance.partly} partly, ${build.classBalance.no} no \xB7 source: ${build.bySource.feedback} feedback, ${build.bySource.confirm} confirm`
|
|
130238
130401
|
)
|
|
130239
130402
|
);
|
|
130240
|
-
console.log(` Corpus: ${
|
|
130241
|
-
console.log(` Manifest: ${
|
|
130403
|
+
console.log(` Corpus: ${import_picocolors63.default.cyan(corpusPath)}`);
|
|
130404
|
+
console.log(` Manifest: ${import_picocolors63.default.cyan(manifestPath)}`);
|
|
130242
130405
|
}
|
|
130243
130406
|
return 0;
|
|
130244
130407
|
} finally {
|
|
130245
130408
|
await sql2.end();
|
|
130246
130409
|
}
|
|
130247
130410
|
} catch (err2) {
|
|
130248
|
-
console.error(
|
|
130411
|
+
console.error(import_picocolors63.default.red(err2.message));
|
|
130249
130412
|
return 1;
|
|
130250
130413
|
}
|
|
130251
130414
|
}
|
|
@@ -130275,31 +130438,31 @@ async function runEvalBaseline(opts) {
|
|
|
130275
130438
|
console.log(JSON.stringify({ project, baseline, separation }, null, 2));
|
|
130276
130439
|
} else {
|
|
130277
130440
|
const pct2 = (n4) => `${(n4 * 100).toFixed(0)}%`;
|
|
130278
|
-
console.log(
|
|
130441
|
+
console.log(import_picocolors63.default.bold(`Eval baseline \u2014 ${project}`));
|
|
130279
130442
|
if (baseline.n === 0) {
|
|
130280
130443
|
console.log(
|
|
130281
|
-
|
|
130444
|
+
import_picocolors63.default.dim(
|
|
130282
130445
|
"No outcome labels yet. Leave feedback (`horus feedback`) or confirm an investigation (`horus memory confirm`) to seed the eval set."
|
|
130283
130446
|
)
|
|
130284
130447
|
);
|
|
130285
130448
|
} else {
|
|
130286
130449
|
console.log(
|
|
130287
|
-
` Strict hit-rate: ${
|
|
130450
|
+
` Strict hit-rate: ${import_picocolors63.default.green(pct2(baseline.strictHitRate))} ` + import_picocolors63.default.dim(`(weighted ${pct2(baseline.weightedHitRate)}) over ${baseline.n} investigation(s)`)
|
|
130288
130451
|
);
|
|
130289
130452
|
console.log(
|
|
130290
|
-
` Class balance: ${
|
|
130453
|
+
` Class balance: ${import_picocolors63.default.green(`${baseline.classBalance.yes} yes`)}, ${import_picocolors63.default.yellow(`${baseline.classBalance.partly} partly`)}, ${import_picocolors63.default.red(`${baseline.classBalance.no} no`)} \xB7 ` + import_picocolors63.default.dim(`source: ${baseline.bySource.feedback} feedback, ${baseline.bySource.confirm} confirm`)
|
|
130291
130454
|
);
|
|
130292
130455
|
if (separation.factors.length === 0) {
|
|
130293
130456
|
console.log(
|
|
130294
|
-
|
|
130457
|
+
import_picocolors63.default.dim(
|
|
130295
130458
|
` Feature separation: no discriminative sample yet (needs feedback rows with yes AND no verdicts and a ranked cause).`
|
|
130296
130459
|
)
|
|
130297
130460
|
);
|
|
130298
130461
|
} else {
|
|
130299
|
-
console.log(
|
|
130462
|
+
console.log(import_picocolors63.default.dim(` Feature separation (yes vs no, ${separation.evaluated} row(s)):`));
|
|
130300
130463
|
for (const f5 of separation.factors.slice(0, 10)) {
|
|
130301
130464
|
console.log(
|
|
130302
|
-
|
|
130465
|
+
import_picocolors63.default.dim(
|
|
130303
130466
|
` ${f5.factor}: \u0394 ${f5.separation.toFixed(3)} (yes ${f5.meanYes.toFixed(3)} vs no ${f5.meanNo.toFixed(3)}, effect ${f5.effectSize.toFixed(2)})`
|
|
130304
130467
|
)
|
|
130305
130468
|
);
|
|
@@ -130312,7 +130475,7 @@ async function runEvalBaseline(opts) {
|
|
|
130312
130475
|
await sql2.end();
|
|
130313
130476
|
}
|
|
130314
130477
|
} catch (err2) {
|
|
130315
|
-
console.error(
|
|
130478
|
+
console.error(import_picocolors63.default.red(err2.message));
|
|
130316
130479
|
return 1;
|
|
130317
130480
|
}
|
|
130318
130481
|
}
|
|
@@ -130322,7 +130485,7 @@ init_cjs_shims();
|
|
|
130322
130485
|
var import_promises6 = require("fs/promises");
|
|
130323
130486
|
var import_node_path32 = require("path");
|
|
130324
130487
|
var import_node_os12 = require("os");
|
|
130325
|
-
var
|
|
130488
|
+
var import_picocolors64 = __toESM(require_picocolors(), 1);
|
|
130326
130489
|
init_src();
|
|
130327
130490
|
var RERANKER_MODEL_PATH = (0, import_node_path32.join)((0, import_node_os12.homedir)(), ".horus", "reranker.json");
|
|
130328
130491
|
function candidatesFromReport(blob) {
|
|
@@ -130338,7 +130501,7 @@ async function runTrain(opts) {
|
|
|
130338
130501
|
let source;
|
|
130339
130502
|
if (opts.source !== void 0) {
|
|
130340
130503
|
if (!isOutcomeSource(opts.source)) {
|
|
130341
|
-
console.error(
|
|
130504
|
+
console.error(import_picocolors64.default.red(`Unknown --source "${opts.source}" (one of: feedback, confirm).`));
|
|
130342
130505
|
return 1;
|
|
130343
130506
|
}
|
|
130344
130507
|
source = opts.source;
|
|
@@ -130346,7 +130509,7 @@ async function runTrain(opts) {
|
|
|
130346
130509
|
let since;
|
|
130347
130510
|
if (opts.days !== void 0) {
|
|
130348
130511
|
if (!Number.isFinite(opts.days) || opts.days <= 0) {
|
|
130349
|
-
console.error(
|
|
130512
|
+
console.error(import_picocolors64.default.red("--days must be a positive number."));
|
|
130350
130513
|
return 1;
|
|
130351
130514
|
}
|
|
130352
130515
|
since = new Date(Date.now() - opts.days * 24 * 60 * 60 * 1e3);
|
|
@@ -130382,7 +130545,7 @@ async function runTrain(opts) {
|
|
|
130382
130545
|
await sql2.end();
|
|
130383
130546
|
}
|
|
130384
130547
|
} catch (err2) {
|
|
130385
|
-
console.error(
|
|
130548
|
+
console.error(import_picocolors64.default.red(`Could not read the local corpus: ${err2.message}`));
|
|
130386
130549
|
return 1;
|
|
130387
130550
|
}
|
|
130388
130551
|
const split = holdoutSplit(investigations2);
|
|
@@ -130390,26 +130553,26 @@ async function runTrain(opts) {
|
|
|
130390
130553
|
if (!result.ok) {
|
|
130391
130554
|
if (result.reason === "insufficient-corpus") {
|
|
130392
130555
|
console.log(
|
|
130393
|
-
|
|
130556
|
+
import_picocolors64.default.yellow(
|
|
130394
130557
|
`Not enough labeled investigations to train yet (have ${result.labeledInvestigations} with a known-correct cause; need \u2265${MIN_TRAIN_INVESTIGATIONS}).`
|
|
130395
130558
|
)
|
|
130396
130559
|
);
|
|
130397
|
-
console.log(
|
|
130560
|
+
console.log(import_picocolors64.default.dim(" Keep labeling outcomes with `horus feedback` \u2014 the reranker trains once the corpus is large enough."));
|
|
130398
130561
|
} else {
|
|
130399
|
-
console.log(
|
|
130562
|
+
console.log(import_picocolors64.default.yellow(`Cannot train a meaningful model yet: ${result.detail}.`));
|
|
130400
130563
|
}
|
|
130401
130564
|
return 0;
|
|
130402
130565
|
}
|
|
130403
130566
|
const { baselineHitRate, rerankedHitRate, delta, n: n4 } = result.holdout;
|
|
130404
|
-
console.log(
|
|
130567
|
+
console.log(import_picocolors64.default.bold("\nReranker training (local, per-tenant)\n"));
|
|
130405
130568
|
console.log(` Holdout investigations: ${n4}`);
|
|
130406
130569
|
console.log(` Baseline top-1 hit-rate: ${pct(baselineHitRate)}`);
|
|
130407
130570
|
console.log(` Reranked top-1 hit-rate: ${pct(rerankedHitRate)}`);
|
|
130408
130571
|
console.log(` Delta: ${delta >= 0 ? "+" : ""}${pct(delta)}`);
|
|
130409
130572
|
console.log("");
|
|
130410
130573
|
if (delta <= 0) {
|
|
130411
|
-
console.log(
|
|
130412
|
-
console.log(
|
|
130574
|
+
console.log(import_picocolors64.default.yellow(" The reranker did NOT beat the deterministic baseline \u2014 not saving a model."));
|
|
130575
|
+
console.log(import_picocolors64.default.dim(" Horus stays on its hand-tuned ranking. Re-run as more labels accumulate."));
|
|
130413
130576
|
return 0;
|
|
130414
130577
|
}
|
|
130415
130578
|
try {
|
|
@@ -130418,20 +130581,20 @@ async function runTrain(opts) {
|
|
|
130418
130581
|
void _ok;
|
|
130419
130582
|
await (0, import_promises6.writeFile)(RERANKER_MODEL_PATH, JSON.stringify(model, null, 2) + "\n", "utf8");
|
|
130420
130583
|
} catch (err2) {
|
|
130421
|
-
console.error(
|
|
130584
|
+
console.error(import_picocolors64.default.red(`Trained, but could not write the model: ${err2.message}`));
|
|
130422
130585
|
return 1;
|
|
130423
130586
|
}
|
|
130424
|
-
console.log(
|
|
130425
|
-
console.log(
|
|
130587
|
+
console.log(import_picocolors64.default.green(` \u2713 Reranker beats baseline by +${pct(delta)} \u2014 saved to ${RERANKER_MODEL_PATH}`));
|
|
130588
|
+
console.log(import_picocolors64.default.dim(" It ships OFF by default. Enable it with `HORUS_RERANK=1 horus investigate \u2026`."));
|
|
130426
130589
|
return 0;
|
|
130427
130590
|
}
|
|
130428
130591
|
|
|
130429
130592
|
// ../../packages/cli/src/lib/report-crash.ts
|
|
130430
130593
|
init_cjs_shims();
|
|
130431
|
-
var
|
|
130594
|
+
var import_picocolors65 = __toESM(require_picocolors(), 1);
|
|
130432
130595
|
function reportCrash(err2, log = console.error) {
|
|
130433
130596
|
log(err2);
|
|
130434
|
-
log(
|
|
130597
|
+
log(import_picocolors65.default.dim("\n Looks like a Horus bug or a missing capability? Report it: horus report"));
|
|
130435
130598
|
}
|
|
130436
130599
|
|
|
130437
130600
|
// ../../packages/cli/src/index.ts
|
|
@@ -131100,6 +131263,33 @@ Examples:
|
|
|
131100
131263
|
});
|
|
131101
131264
|
}
|
|
131102
131265
|
);
|
|
131266
|
+
program2.command("trace <from> <to>").description(
|
|
131267
|
+
"Shortest relationship path between two symbols across all edges (calls, imports, extends, implements, uses_type), both directions"
|
|
131268
|
+
).option("-c, --config <path>", "path to horus.config.ts").option("-d, --max-depth <n>", "maximum hops (default 10, max 10)", (v4) => parseInt(v4, 10)).option(
|
|
131269
|
+
"--relations <list>",
|
|
131270
|
+
"comma-separated edge kinds to restrict the walk (e.g. calls,imports)"
|
|
131271
|
+
).option("--json", "output JSON").action(
|
|
131272
|
+
async (from, to, opts) => {
|
|
131273
|
+
process.exitCode = await runTrace(from, to, {
|
|
131274
|
+
config: opts.config,
|
|
131275
|
+
maxDepth: opts.maxDepth,
|
|
131276
|
+
relations: opts.relations,
|
|
131277
|
+
json: opts.json
|
|
131278
|
+
});
|
|
131279
|
+
}
|
|
131280
|
+
);
|
|
131281
|
+
program2.command("insights").description(
|
|
131282
|
+
"Graph-shape insights: the codebase's hubs (most-connected symbols), surprising cross-community connections, and suggested questions"
|
|
131283
|
+
).option("-c, --config <path>", "path to horus.config.ts").option("--hubs <n>", "how many top hubs to show (default 8)", (v4) => parseInt(v4, 10)).option("--bridges <n>", "how many cross-community edges to show (default 8)", (v4) => parseInt(v4, 10)).option("--json", "output JSON").action(
|
|
131284
|
+
async (opts) => {
|
|
131285
|
+
process.exitCode = await runInsights({
|
|
131286
|
+
config: opts.config,
|
|
131287
|
+
hubs: opts.hubs,
|
|
131288
|
+
bridges: opts.bridges,
|
|
131289
|
+
json: opts.json
|
|
131290
|
+
});
|
|
131291
|
+
}
|
|
131292
|
+
);
|
|
131103
131293
|
program2.command("repos").description("List configured repositories and their source-intelligence host health").option("-c, --config <path>", "path to horus.config.ts").action(async (opts) => {
|
|
131104
131294
|
process.exitCode = await runRepos({ config: opts.config });
|
|
131105
131295
|
});
|