@merittdev/horus 0.5.0 → 0.6.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/index.cjs +33 -14
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -62439,7 +62439,7 @@ init_cjs_shims();
|
|
|
62439
62439
|
|
|
62440
62440
|
// ../../packages/core/src/version.ts
|
|
62441
62441
|
init_cjs_shims();
|
|
62442
|
-
var HORUS_VERSION = true ? "0.
|
|
62442
|
+
var HORUS_VERSION = true ? "0.6.0" : "dev";
|
|
62443
62443
|
var PINNED_SOURCE_VERSION = "1.0.7";
|
|
62444
62444
|
|
|
62445
62445
|
// ../../packages/core/src/evidence.ts
|
|
@@ -82986,15 +82986,20 @@ function looksExplanatory(hint) {
|
|
|
82986
82986
|
}
|
|
82987
82987
|
return false;
|
|
82988
82988
|
}
|
|
82989
|
-
function formatRegressionCitation(recentChanges, changes) {
|
|
82990
|
-
const
|
|
82989
|
+
function formatRegressionCitation(recentChanges, changes, seedFile) {
|
|
82990
|
+
const matchesSeed = (f) => seedFile === void 0 || f === seedFile || seedFile.endsWith(f) || f.endsWith(seedFile);
|
|
82991
|
+
const all = recentChanges?.commits ?? [];
|
|
82992
|
+
const seedCommits = seedFile ? all.filter((c) => c.files.some(matchesSeed)) : all;
|
|
82993
|
+
const commits = seedCommits.slice(0, 2);
|
|
82991
82994
|
const commitParts = commits.map((c) => {
|
|
82992
82995
|
const sha = c.shortSha || c.sha.slice(0, 7);
|
|
82993
82996
|
const subject = (c.subject ?? "").replace(/\s+/g, " ").trim();
|
|
82994
82997
|
return subject ? `${sha} "${subject.slice(0, 50)}"` : sha;
|
|
82995
82998
|
});
|
|
82996
82999
|
const commitClause = commitParts.length > 0 ? ` (${commitParts.join(", ")})` : "";
|
|
82997
|
-
const modified = changes?.modified ?? []
|
|
83000
|
+
const modified = (changes?.modified ?? []).filter(
|
|
83001
|
+
(m) => matchesSeed((m.after ?? m.before).filePath ?? "")
|
|
83002
|
+
);
|
|
82998
83003
|
const symbolNames = [];
|
|
82999
83004
|
for (const m of modified) {
|
|
83000
83005
|
const name = m.after?.name ?? m.before?.name;
|
|
@@ -83878,13 +83883,15 @@ async function investigate(input, deps) {
|
|
|
83878
83883
|
const gitChangedFiles = recentChanges?.changedFiles ?? [];
|
|
83879
83884
|
const seedFile = top?.filePath;
|
|
83880
83885
|
const seedInChanges = seedFile !== void 0 && gitChangedFiles.length > 0 && gitChangedFiles.some((f) => f === seedFile || seedFile.endsWith(f) || f.endsWith(seedFile));
|
|
83881
|
-
const citation = formatRegressionCitation(recentChanges, changes);
|
|
83886
|
+
const citation = formatRegressionCitation(recentChanges, changes, seedFile);
|
|
83887
|
+
const regressionTitle = top && seedInChanges ? `Recent change${citation.commitClause} to ${top.name}${citation.symbolClause} in ${input.since}..HEAD may have introduced the regression` : top ? `Changes shipped in ${input.since}..HEAD but none touched ${top.name} \u2014 a regression here is unlikely to be a code change to the seed itself (check upstream deps, data, or config)` : `Recent change${citation.commitClause}${citation.symbolClause} in ${input.since}..HEAD may have introduced the regression`;
|
|
83882
83888
|
causeInputs.push({
|
|
83883
83889
|
id: "cause:deployment-regression",
|
|
83884
|
-
title:
|
|
83890
|
+
title: regressionTitle,
|
|
83885
83891
|
category: "deployment-regression",
|
|
83886
83892
|
sourceEvidenceIds: [changeEvId, ...seedEv ? [seedEv.id] : []],
|
|
83887
|
-
|
|
83893
|
+
// A regression NOT backed by a seed-touching commit must not score like one that is.
|
|
83894
|
+
baseScore: clamp015((seedInChanges ? 0.45 : 0.18) + (queueHits.length > 0 ? 0.05 : 0)),
|
|
83888
83895
|
metadata: { blastRadius }
|
|
83889
83896
|
});
|
|
83890
83897
|
}
|
|
@@ -83997,14 +84004,25 @@ async function investigate(input, deps) {
|
|
|
83997
84004
|
ambientLogEvIds.length > 0 ? new Set(ambientLogEvIds) : void 0
|
|
83998
84005
|
);
|
|
83999
84006
|
const seedResolved = seeds.length === 0 ? 0 : seedIsLowConfidence ? 0.3 : 1;
|
|
84000
|
-
|
|
84007
|
+
let confidence = clamp015(0.5 * evidenceConfidence + 0.5 * seedResolved);
|
|
84001
84008
|
const area = ctx?.community?.name ?? top?.filePath ?? (input.service ?? "runtime evidence");
|
|
84002
84009
|
const topCause = rankedCauses[0];
|
|
84003
|
-
const
|
|
84010
|
+
const seedLinkedEvIds = /* @__PURE__ */ new Set([
|
|
84011
|
+
...directLogEvIds,
|
|
84012
|
+
...seedEv ? [seedEv.id] : [],
|
|
84013
|
+
...impactEv ? [impactEv.id] : []
|
|
84014
|
+
]);
|
|
84015
|
+
const isLinkedToSeed = (ids2) => ids2.some((id) => seedLinkedEvIds.has(id));
|
|
84016
|
+
const topLinkedCause = rankedCauses.find(
|
|
84017
|
+
(c) => c.finalScore >= 0.2 && isLinkedToSeed(c.sourceEvidenceIds)
|
|
84018
|
+
);
|
|
84019
|
+
const headlineCause = topLinkedCause ?? (topCause && topCause.finalScore >= 0.2 ? topCause : void 0);
|
|
84020
|
+
const headlineLinked = headlineCause !== void 0 && isLinkedToSeed(headlineCause.sourceEvidenceIds);
|
|
84021
|
+
if (headlineCause && !headlineLinked) confidence = Math.min(confidence, 0.6);
|
|
84004
84022
|
const banner2 = degradedNoSource ? "Runtime-only (source intelligence unavailable). " : "";
|
|
84005
84023
|
const scope = top ? `resolved to ${label} (${area})` : `over runtime evidence (${area})`;
|
|
84006
84024
|
const seedDisclaimer = seedIsLowConfidence && top ? `\u26A0 No symbol closely matched "${hint}" \u2014 "${top.name}" is a low-confidence closest match (semantic). Refine with an exact symbol or error code to target precisely. ` : "";
|
|
84007
|
-
let summary = headlineCause ? `${seedDisclaimer}${banner2}Investigation of "${hint}" ${scope}. Top suspected cause: ${headlineCause.title}.` : `${seedDisclaimer}${banner2}Investigation of "${hint}" ${scope}. No dominant suspected cause emerged from the available ${degradedNoSource ? "runtime" : "structural"} evidence.`;
|
|
84025
|
+
let summary = headlineCause ? headlineLinked ? `${seedDisclaimer}${banner2}Investigation of "${hint}" ${scope}. Top suspected cause: ${headlineCause.title}.` : `${seedDisclaimer}${banner2}Investigation of "${hint}" ${scope}. No cause is structurally linked to the seed; the strongest co-occurring signal (a lead to verify, not a diagnosis) is: ${headlineCause.title}.` : `${seedDisclaimer}${banner2}Investigation of "${hint}" ${scope}. No dominant suspected cause emerged from the available ${degradedNoSource ? "runtime" : "structural"} evidence.`;
|
|
84008
84026
|
const hasIncidentSignal = directLogEvIds.length > 0 || latencyMetricEvIds.length > 0 || queueMetricEvIds.length > 0 || dataAnomalyEvIds.length > 0 || queueFailureSignals.length > 0 || findings2.some((f) => f.kind === "anomaly") || headlineCause !== void 0;
|
|
84009
84027
|
const explanatoryHint = looksExplanatory(hint) && !hasIncidentSignal;
|
|
84010
84028
|
if (explanatoryHint) {
|
|
@@ -85133,8 +85151,7 @@ function scoreInvestigation(r) {
|
|
|
85133
85151
|
const total = r.hypotheses.length;
|
|
85134
85152
|
const resolved = r.hypotheses.filter((h) => h.verdict !== "unconfirmed").length;
|
|
85135
85153
|
const discriminationValue = total > 0 ? resolved / total : 0;
|
|
85136
|
-
const
|
|
85137
|
-
const rootCauseValue = supported.length > 0 ? Math.max(...supported.map((h) => h.confidence)) : 0;
|
|
85154
|
+
const rootCauseValue = r.confidence;
|
|
85138
85155
|
const completenessValue = 1 - Math.min(1, r.gapAnalysis.gaps.length / 6);
|
|
85139
85156
|
const actionabilityValue = r.nextActions.length > 0 ? 1 : 0;
|
|
85140
85157
|
const components = [
|
|
@@ -85151,10 +85168,10 @@ function scoreInvestigation(r) {
|
|
|
85151
85168
|
note: "fraction of hypotheses ruled in or out (vs left unconfirmed)"
|
|
85152
85169
|
},
|
|
85153
85170
|
{
|
|
85154
|
-
dimension: "
|
|
85171
|
+
dimension: "diagnostic calibration",
|
|
85155
85172
|
value: rootCauseValue,
|
|
85156
85173
|
weight: 0.25,
|
|
85157
|
-
note: "confidence in a
|
|
85174
|
+
note: "calibrated confidence in the diagnosis \u2014 a seed-linked cause scores high; honest uncertainty is not punished"
|
|
85158
85175
|
},
|
|
85159
85176
|
{
|
|
85160
85177
|
dimension: "evidence completeness",
|
|
@@ -100810,6 +100827,8 @@ Ask a follow-up: horus ask ${report.id} "<question>"`));
|
|
|
100810
100827
|
} finally {
|
|
100811
100828
|
await sql2.end();
|
|
100812
100829
|
if (mongo) await mongo.close();
|
|
100830
|
+
if (postgres2) await postgres2.close();
|
|
100831
|
+
if (redisState) await redisState.close();
|
|
100813
100832
|
if (queue) await queue.close();
|
|
100814
100833
|
}
|
|
100815
100834
|
return 0;
|