@merittdev/horus 0.8.7 → 0.8.9

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.
Files changed (2) hide show
  1. package/dist/index.cjs +76 -50
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -65880,7 +65880,7 @@ init_cjs_shims();
65880
65880
 
65881
65881
  // ../../packages/core/src/version.ts
65882
65882
  init_cjs_shims();
65883
- var HORUS_VERSION = true ? "0.8.7" : "dev";
65883
+ var HORUS_VERSION = true ? "0.8.9" : "dev";
65884
65884
  var PINNED_SOURCE_VERSION = "1.5.0";
65885
65885
 
65886
65886
  // ../../packages/core/src/evidence.ts
@@ -70614,6 +70614,11 @@ async function loadConfig(configPath, opts) {
70614
70614
  } else {
70615
70615
  const jsPath = (0, import_node_path2.resolve)(cwd, "config/horus.config.js");
70616
70616
  const tsPath = (0, import_node_path2.resolve)(cwd, "config/horus.config.ts");
70617
+ if (!(0, import_node_fs2.existsSync)(jsPath) && !(0, import_node_fs2.existsSync)(tsPath)) {
70618
+ throw new Error(
70619
+ `No Horus config found for ${cwd}. Run \`horus index\` in this repo to set it up, or pass --config <path> / --name <project>.`
70620
+ );
70621
+ }
70617
70622
  target = (0, import_node_fs2.existsSync)(jsPath) ? jsPath : tsPath;
70618
70623
  }
70619
70624
  }
@@ -93680,8 +93685,12 @@ async function investigate(input, deps) {
93680
93685
  });
93681
93686
  }
93682
93687
  if (seedEmittedJoins.length > 0 && top && seedEv) {
93688
+ const hintNamedCodes = new Set(extractEventCodes(hint));
93683
93689
  const ordered = [...seedEmittedJoins].sort((a2, b5) => {
93684
93690
  if (a2.raisedBySeed !== b5.raisedBySeed) return a2.raisedBySeed ? -1 : 1;
93691
+ const ha = hintNamedCodes.has(a2.code);
93692
+ const hb = hintNamedCodes.has(b5.code);
93693
+ if (ha !== hb) return ha ? -1 : 1;
93685
93694
  const ta = seedEmittedSeverityTier(a2.level, a2.code, a2.message);
93686
93695
  const tb = seedEmittedSeverityTier(b5.level, b5.code, b5.message);
93687
93696
  if (ta !== tb) return tb - ta;
@@ -97273,6 +97282,50 @@ async function stitch(client, db, opts = {}) {
97273
97282
  };
97274
97283
  }
97275
97284
 
97285
+ // ../../packages/cli/src/lib/ensure-host.ts
97286
+ init_cjs_shims();
97287
+ function parseHostPort(hostUrl) {
97288
+ try {
97289
+ const port = parseInt(new URL(hostUrl).port, 10);
97290
+ return Number.isNaN(port) ? null : port;
97291
+ } catch {
97292
+ return null;
97293
+ }
97294
+ }
97295
+ function ensureHostReasonHint(reason) {
97296
+ switch (reason) {
97297
+ case "source-unavailable":
97298
+ return "horus-source is not installed \u2014 install it: pip install horus-source";
97299
+ case "version-mismatch":
97300
+ return "the installed horus-source backend does not match the version Horus is pinned to \u2014 reinstall the pinned version (run `horus status` to see it)";
97301
+ case "not-analyzed":
97302
+ return "this repo has not been indexed yet \u2014 run: horus index";
97303
+ case "bad-url":
97304
+ return "the configured source host URL is not a valid URL";
97305
+ default:
97306
+ return "the host did not become healthy \u2014 run: horus index";
97307
+ }
97308
+ }
97309
+ async function ensureSourceHost(root, hostUrl, opts = {}) {
97310
+ if (await isHostHealthy(hostUrl)) return { ok: true, hostUrl };
97311
+ if (!await sourceAvailable()) return { ok: false, reason: "source-unavailable" };
97312
+ try {
97313
+ await assertSourceVersionPinned();
97314
+ } catch {
97315
+ return { ok: false, reason: "version-mismatch" };
97316
+ }
97317
+ if (!isAnalyzed(root)) return { ok: false, reason: "not-analyzed" };
97318
+ const port = parseHostPort(hostUrl);
97319
+ if (port === null) return { ok: false, reason: "bad-url" };
97320
+ startHost(root, port);
97321
+ if (await waitForHost(hostUrl, opts.timeoutMs ?? 2e4)) {
97322
+ reconcileSpawnedHostPid(root, port);
97323
+ return { ok: true, hostUrl };
97324
+ }
97325
+ removeSpawnedHostRecord(root);
97326
+ return { ok: false, reason: "unhealthy" };
97327
+ }
97328
+
97276
97329
  // ../../packages/cli/src/commands/index-repo.ts
97277
97330
  async function stitchQueueMap(hostUrl, dbUrl, label) {
97278
97331
  const source = new SourceHttpClient({ baseUrl: hostUrl });
@@ -97286,6 +97339,14 @@ async function stitchQueueMap(hostUrl, dbUrl, label) {
97286
97339
  await sql2.end();
97287
97340
  }
97288
97341
  }
97342
+ async function hostServesRepo(hostUrl, root) {
97343
+ try {
97344
+ const info2 = await new SourceHttpClient({ baseUrl: hostUrl }).hostInfo();
97345
+ return (0, import_node_path10.resolve)(info2.repoPath) === (0, import_node_path10.resolve)(root);
97346
+ } catch {
97347
+ return true;
97348
+ }
97349
+ }
97289
97350
  function findConfiguredRepo(config2, root) {
97290
97351
  const target = (0, import_node_path10.resolve)(root);
97291
97352
  for (const p5 of config2.projects) {
@@ -97372,7 +97433,7 @@ async function runIndex(opts) {
97372
97433
  let hostUrl;
97373
97434
  let spawned = false;
97374
97435
  for (const candidate of [configuredHost, readSourceHostUrl(root) ?? void 0]) {
97375
- if (candidate && await isHostHealthy(candidate)) {
97436
+ if (candidate && await isHostHealthy(candidate) && await hostServesRepo(candidate, root)) {
97376
97437
  hostUrl = candidate;
97377
97438
  break;
97378
97439
  }
@@ -97403,7 +97464,17 @@ async function runIndex(opts) {
97403
97464
  } else {
97404
97465
  console.log(import_picocolors3.default.dim(" already analyzed"));
97405
97466
  }
97406
- const port = await findFreePort();
97467
+ const priorPort = parseHostPort(configuredHost ?? "") ?? parseHostPort(readSourceHostUrl(root) ?? "");
97468
+ let port;
97469
+ if (priorPort !== null) {
97470
+ try {
97471
+ port = await findFreePort(priorPort, priorPort);
97472
+ } catch {
97473
+ port = await findFreePort();
97474
+ }
97475
+ } else {
97476
+ port = await findFreePort();
97477
+ }
97407
97478
  hostUrl = `http://127.0.0.1:${port}`;
97408
97479
  console.log(import_picocolors3.default.dim(` starting source-intelligence host on port ${port}\u2026`));
97409
97480
  startHost(root, port);
@@ -97418,7 +97489,8 @@ async function runIndex(opts) {
97418
97489
  }
97419
97490
  await stitchQueueMap(hostUrl, dbUrl, label);
97420
97491
  buildKnowledgeIndex(root, config2, label, configuredProject, opts);
97421
- if (spawned && !isConfigured) {
97492
+ const hasLocalConfig = discoverLocalConfig(root) !== null;
97493
+ if (!isConfigured && !hasLocalConfig) {
97422
97494
  const file = {
97423
97495
  version: 1,
97424
97496
  project: {
@@ -110339,52 +110411,6 @@ async function maybePromptFeedback(opts) {
110339
110411
  // ../../packages/cli/src/lib/investigation-runner.ts
110340
110412
  init_cjs_shims();
110341
110413
  var import_picocolors9 = __toESM(require_picocolors(), 1);
110342
-
110343
- // ../../packages/cli/src/lib/ensure-host.ts
110344
- init_cjs_shims();
110345
- function parseHostPort(hostUrl) {
110346
- try {
110347
- const port = parseInt(new URL(hostUrl).port, 10);
110348
- return Number.isNaN(port) ? null : port;
110349
- } catch {
110350
- return null;
110351
- }
110352
- }
110353
- function ensureHostReasonHint(reason) {
110354
- switch (reason) {
110355
- case "source-unavailable":
110356
- return "horus-source is not installed \u2014 install it: pip install horus-source";
110357
- case "version-mismatch":
110358
- return "the installed horus-source backend does not match the version Horus is pinned to \u2014 reinstall the pinned version (run `horus status` to see it)";
110359
- case "not-analyzed":
110360
- return "this repo has not been indexed yet \u2014 run: horus index";
110361
- case "bad-url":
110362
- return "the configured source host URL is not a valid URL";
110363
- default:
110364
- return "the host did not become healthy \u2014 run: horus index";
110365
- }
110366
- }
110367
- async function ensureSourceHost(root, hostUrl, opts = {}) {
110368
- if (await isHostHealthy(hostUrl)) return { ok: true, hostUrl };
110369
- if (!await sourceAvailable()) return { ok: false, reason: "source-unavailable" };
110370
- try {
110371
- await assertSourceVersionPinned();
110372
- } catch {
110373
- return { ok: false, reason: "version-mismatch" };
110374
- }
110375
- if (!isAnalyzed(root)) return { ok: false, reason: "not-analyzed" };
110376
- const port = parseHostPort(hostUrl);
110377
- if (port === null) return { ok: false, reason: "bad-url" };
110378
- startHost(root, port);
110379
- if (await waitForHost(hostUrl, opts.timeoutMs ?? 2e4)) {
110380
- reconcileSpawnedHostPid(root, port);
110381
- return { ok: true, hostUrl };
110382
- }
110383
- removeSpawnedHostRecord(root);
110384
- return { ok: false, reason: "unhealthy" };
110385
- }
110386
-
110387
- // ../../packages/cli/src/lib/investigation-runner.ts
110388
110414
  async function buildInvestigationContext(renv, opts) {
110389
110415
  const log = opts.log ?? ((l2) => console.error(l2));
110390
110416
  const code = codeForEnv(renv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merittdev/horus",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "description": "Local-first, source-aware production-incident investigation engine",
5
5
  "type": "module",
6
6
  "bin": {