@merittdev/horus 0.1.16 → 0.1.17
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 +193 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50314,7 +50314,7 @@ init_cjs_shims();
|
|
|
50314
50314
|
|
|
50315
50315
|
// ../../packages/core/src/version.ts
|
|
50316
50316
|
init_cjs_shims();
|
|
50317
|
-
var HORUS_VERSION = true ? "0.1.
|
|
50317
|
+
var HORUS_VERSION = true ? "0.1.17" : "dev";
|
|
50318
50318
|
var PINNED_AXON_VERSION = "1.0.7";
|
|
50319
50319
|
var PINNED_SOURCE_VERSION = PINNED_AXON_VERSION;
|
|
50320
50320
|
|
|
@@ -59087,7 +59087,7 @@ function sql(strings, ...params) {
|
|
|
59087
59087
|
return new SQL([new StringChunk(str)]);
|
|
59088
59088
|
}
|
|
59089
59089
|
sql2.raw = raw;
|
|
59090
|
-
function
|
|
59090
|
+
function join6(chunks, separator) {
|
|
59091
59091
|
const result = [];
|
|
59092
59092
|
for (const [i, chunk] of chunks.entries()) {
|
|
59093
59093
|
if (i > 0 && separator !== void 0) {
|
|
@@ -59097,7 +59097,7 @@ function sql(strings, ...params) {
|
|
|
59097
59097
|
}
|
|
59098
59098
|
return new SQL(result);
|
|
59099
59099
|
}
|
|
59100
|
-
sql2.join =
|
|
59100
|
+
sql2.join = join6;
|
|
59101
59101
|
function identifier(value) {
|
|
59102
59102
|
return new Name(value);
|
|
59103
59103
|
}
|
|
@@ -62688,7 +62688,7 @@ var PgSelectQueryBuilderBase = class extends TypedQueryBuilder {
|
|
|
62688
62688
|
return (table, on) => {
|
|
62689
62689
|
const baseTableName = this.tableName;
|
|
62690
62690
|
const tableName = getTableLikeName(table);
|
|
62691
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
62691
|
+
if (typeof tableName === "string" && this.config.joins?.some((join6) => join6.alias === tableName)) {
|
|
62692
62692
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
62693
62693
|
}
|
|
62694
62694
|
if (!this.isPartialSelect) {
|
|
@@ -63700,7 +63700,7 @@ var PgUpdateBase = class extends QueryPromise {
|
|
|
63700
63700
|
createJoin(joinType) {
|
|
63701
63701
|
return (table, on) => {
|
|
63702
63702
|
const tableName = getTableLikeName(table);
|
|
63703
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
63703
|
+
if (typeof tableName === "string" && this.config.joins.some((join6) => join6.alias === tableName)) {
|
|
63704
63704
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
63705
63705
|
}
|
|
63706
63706
|
if (typeof on === "function") {
|
|
@@ -63796,10 +63796,10 @@ var PgUpdateBase = class extends QueryPromise {
|
|
|
63796
63796
|
const fromFields = this.getTableLikeFields(this.config.from);
|
|
63797
63797
|
fields[tableName] = fromFields;
|
|
63798
63798
|
}
|
|
63799
|
-
for (const
|
|
63800
|
-
const tableName2 = getTableLikeName(
|
|
63801
|
-
if (typeof tableName2 === "string" && !is(
|
|
63802
|
-
const fromFields = this.getTableLikeFields(
|
|
63799
|
+
for (const join6 of this.config.joins) {
|
|
63800
|
+
const tableName2 = getTableLikeName(join6.table);
|
|
63801
|
+
if (typeof tableName2 === "string" && !is(join6.table, SQL)) {
|
|
63802
|
+
const fromFields = this.getTableLikeFields(join6.table);
|
|
63803
63803
|
fields[tableName2] = fromFields;
|
|
63804
63804
|
}
|
|
63805
63805
|
}
|
|
@@ -72938,22 +72938,22 @@ function extractQueueGraph(input) {
|
|
|
72938
72938
|
}
|
|
72939
72939
|
}
|
|
72940
72940
|
const producers = [];
|
|
72941
|
-
for (const
|
|
72942
|
-
for (const m of
|
|
72941
|
+
for (const pc36 of input.producerClasses) {
|
|
72942
|
+
for (const m of pc36.content.matchAll(INJECT_QUEUE_RE)) {
|
|
72943
72943
|
const queue = m[1] ?? "";
|
|
72944
|
-
if (queue) producers.push({ queue, symbol:
|
|
72944
|
+
if (queue) producers.push({ queue, symbol: pc36.name, file: pc36.filePath });
|
|
72945
72945
|
}
|
|
72946
|
-
for (const m of
|
|
72946
|
+
for (const m of pc36.content.matchAll(NEW_BULL_RE)) {
|
|
72947
72947
|
if (m[2] !== "Queue") continue;
|
|
72948
72948
|
const queue = resolveArg(m[3] ?? "", constMap);
|
|
72949
72949
|
if (queue) {
|
|
72950
|
-
producers.push({ queue, symbol: (m[1] ??
|
|
72950
|
+
producers.push({ queue, symbol: (m[1] ?? pc36.name) || baseName(pc36.filePath), file: pc36.filePath });
|
|
72951
72951
|
}
|
|
72952
72952
|
}
|
|
72953
|
-
for (const m of
|
|
72953
|
+
for (const m of pc36.content.matchAll(QUEUE_NAME_CONST_RE)) {
|
|
72954
72954
|
const ident = m[1] ?? "";
|
|
72955
72955
|
const queue = m[2] ?? "";
|
|
72956
|
-
if (queue) producers.push({ queue, symbol: ident || baseName(
|
|
72956
|
+
if (queue) producers.push({ queue, symbol: ident || baseName(pc36.filePath), file: pc36.filePath });
|
|
72957
72957
|
}
|
|
72958
72958
|
}
|
|
72959
72959
|
const workers = [];
|
|
@@ -77899,6 +77899,153 @@ async function runReadiness(opts) {
|
|
|
77899
77899
|
return blockingFails.length > 0 ? 1 : 0;
|
|
77900
77900
|
}
|
|
77901
77901
|
|
|
77902
|
+
// ../../packages/cli/src/commands/skill.ts
|
|
77903
|
+
init_cjs_shims();
|
|
77904
|
+
var import_node_fs9 = require("fs");
|
|
77905
|
+
var import_node_path11 = require("path");
|
|
77906
|
+
var import_node_os2 = require("os");
|
|
77907
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
77908
|
+
var SUPPORTED_TARGETS = ["claude", "codex", "gemini", "cursor", "generic"];
|
|
77909
|
+
function isValidTarget(target) {
|
|
77910
|
+
return SUPPORTED_TARGETS.includes(target);
|
|
77911
|
+
}
|
|
77912
|
+
function getSkillInstallPath(target, opts) {
|
|
77913
|
+
const base2 = opts.global ? (0, import_node_os2.homedir)() : opts.cwd ?? process.cwd();
|
|
77914
|
+
if (target === "claude") {
|
|
77915
|
+
return (0, import_node_path11.join)(base2, ".claude", "skills", "horus.md");
|
|
77916
|
+
}
|
|
77917
|
+
return (0, import_node_path11.join)(base2, ".horus", "skills", `horus-${target}.md`);
|
|
77918
|
+
}
|
|
77919
|
+
var BASE_SKILL = `# Horus Incident Investigation Skill
|
|
77920
|
+
|
|
77921
|
+
When investigating a production issue in a repo with Horus configured, use Horus before guessing.
|
|
77922
|
+
|
|
77923
|
+
## When to use Horus
|
|
77924
|
+
|
|
77925
|
+
Use Horus when the user asks:
|
|
77926
|
+
- why something is broken, slow, or failing
|
|
77927
|
+
- about a production incident or outage
|
|
77928
|
+
- what changed recently
|
|
77929
|
+
- who owns a component or service
|
|
77930
|
+
- about blast radius or impact of a change
|
|
77931
|
+
- about queues, workers, Redis/BullMQ, logs, metrics, MongoDB state, or source paths
|
|
77932
|
+
- to verify a fix or check for regressions after a change
|
|
77933
|
+
|
|
77934
|
+
## Getting started
|
|
77935
|
+
|
|
77936
|
+
\`\`\`bash
|
|
77937
|
+
horus status
|
|
77938
|
+
horus explain <symbol-or-hint>
|
|
77939
|
+
horus investigate "<incident hint>"
|
|
77940
|
+
\`\`\`
|
|
77941
|
+
|
|
77942
|
+
## Runtime evidence
|
|
77943
|
+
|
|
77944
|
+
\`\`\`bash
|
|
77945
|
+
horus logs [service]
|
|
77946
|
+
horus state
|
|
77947
|
+
horus metrics "<hint>"
|
|
77948
|
+
horus queues --live
|
|
77949
|
+
\`\`\`
|
|
77950
|
+
|
|
77951
|
+
## Source reasoning
|
|
77952
|
+
|
|
77953
|
+
\`\`\`bash
|
|
77954
|
+
horus blast-radius <symbol>
|
|
77955
|
+
horus owner <symbol>
|
|
77956
|
+
horus changes <base> [compare]
|
|
77957
|
+
horus timeline
|
|
77958
|
+
horus what-changed
|
|
77959
|
+
\`\`\`
|
|
77960
|
+
|
|
77961
|
+
## Saved investigations
|
|
77962
|
+
|
|
77963
|
+
\`\`\`bash
|
|
77964
|
+
horus replay <id>
|
|
77965
|
+
horus ask <id> "what evidence is missing?"
|
|
77966
|
+
horus ask <id> "what evidence contradicts <hypothesis>?"
|
|
77967
|
+
horus postmortem <id>
|
|
77968
|
+
horus score <id>
|
|
77969
|
+
\`\`\`
|
|
77970
|
+
|
|
77971
|
+
## Rules
|
|
77972
|
+
|
|
77973
|
+
- Treat Horus evidence as grounded but not infallible.
|
|
77974
|
+
- Mention when Horus evidence is missing, stale, ambient, or not structurally linked.
|
|
77975
|
+
- Do not invent runtime evidence Horus did not collect.
|
|
77976
|
+
- Prefer exact source locations from Horus over guesses.
|
|
77977
|
+
- If Horus output conflicts with filesystem or source inspection, report the discrepancy.
|
|
77978
|
+
- For write or fix tasks, use Horus to validate blast radius and rerun relevant checks after changes.
|
|
77979
|
+
- Horus is read-only evidence collection \u2014 never use Horus to mutate production systems.
|
|
77980
|
+
- Do not hallucinate evidence. If Horus returns nothing, say so explicitly.
|
|
77981
|
+
`;
|
|
77982
|
+
var CLAUDE_SUFFIX = `## Claude Code notes
|
|
77983
|
+
|
|
77984
|
+
This skill is loaded automatically when present at \`.claude/skills/horus.md\`.
|
|
77985
|
+
|
|
77986
|
+
Useful starting points:
|
|
77987
|
+
- \`horus investigations\` \u2014 list saved investigation IDs
|
|
77988
|
+
- \`horus doctor\` \u2014 check system health
|
|
77989
|
+
- \`horus onboard [area]\` \u2014 get oriented in a new codebase area
|
|
77990
|
+
`;
|
|
77991
|
+
function generateSkillContent(target) {
|
|
77992
|
+
if (target === "claude") {
|
|
77993
|
+
return BASE_SKILL + "\n" + CLAUDE_SUFFIX;
|
|
77994
|
+
}
|
|
77995
|
+
return BASE_SKILL;
|
|
77996
|
+
}
|
|
77997
|
+
async function runSkillInstall(target, opts) {
|
|
77998
|
+
const log = opts.write ?? ((line2) => console.log(line2));
|
|
77999
|
+
if (!isValidTarget(target)) {
|
|
78000
|
+
log(`${import_picocolors35.default.red("\u2717")} Unknown target: ${import_picocolors35.default.bold(target)}`);
|
|
78001
|
+
log(import_picocolors35.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
78002
|
+
return 1;
|
|
78003
|
+
}
|
|
78004
|
+
const outPath = getSkillInstallPath(target, { global: opts.global, cwd: opts.cwd });
|
|
78005
|
+
const content = generateSkillContent(target);
|
|
78006
|
+
if ((0, import_node_fs9.existsSync)(outPath) && !opts.force) {
|
|
78007
|
+
log(`${import_picocolors35.default.red("\u2717")} ${outPath} already exists`);
|
|
78008
|
+
log(import_picocolors35.default.dim(" pass --force to overwrite"));
|
|
78009
|
+
return 1;
|
|
78010
|
+
}
|
|
78011
|
+
try {
|
|
78012
|
+
(0, import_node_fs9.mkdirSync)((0, import_node_path11.dirname)(outPath), { recursive: true });
|
|
78013
|
+
(0, import_node_fs9.writeFileSync)(outPath, content, "utf8");
|
|
78014
|
+
} catch (err) {
|
|
78015
|
+
log(`${import_picocolors35.default.red("\u2717")} Could not write ${outPath}: ${err.message}`);
|
|
78016
|
+
return 1;
|
|
78017
|
+
}
|
|
78018
|
+
log(`${import_picocolors35.default.green("\u2713")} Horus skill installed \u2192 ${outPath}`);
|
|
78019
|
+
if (target === "claude") {
|
|
78020
|
+
log(import_picocolors35.default.dim(" Claude Code will load this skill automatically."));
|
|
78021
|
+
log(import_picocolors35.default.dim(" Invoke it with: /horus"));
|
|
78022
|
+
} else {
|
|
78023
|
+
log(import_picocolors35.default.dim(` Copy or reference this file in your ${target} agent instructions.`));
|
|
78024
|
+
}
|
|
78025
|
+
return 0;
|
|
78026
|
+
}
|
|
78027
|
+
async function runSkillPrint(target, opts) {
|
|
78028
|
+
const log = opts.write ?? ((line2) => console.log(line2));
|
|
78029
|
+
if (!isValidTarget(target)) {
|
|
78030
|
+
log(`${import_picocolors35.default.red("\u2717")} Unknown target: ${import_picocolors35.default.bold(target)}`);
|
|
78031
|
+
log(import_picocolors35.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
78032
|
+
return 1;
|
|
78033
|
+
}
|
|
78034
|
+
process.stdout.write(generateSkillContent(target));
|
|
78035
|
+
return 0;
|
|
78036
|
+
}
|
|
78037
|
+
async function runSkillPath(target, opts) {
|
|
78038
|
+
const log = opts.write ?? ((line2) => console.log(line2));
|
|
78039
|
+
if (!isValidTarget(target)) {
|
|
78040
|
+
log(`${import_picocolors35.default.red("\u2717")} Unknown target: ${import_picocolors35.default.bold(target)}`);
|
|
78041
|
+
log(import_picocolors35.default.dim(` Supported targets: ${SUPPORTED_TARGETS.join(", ")}`));
|
|
78042
|
+
return 1;
|
|
78043
|
+
}
|
|
78044
|
+
const outPath = getSkillInstallPath(target, { global: opts.global, cwd: opts.cwd });
|
|
78045
|
+
log(outPath);
|
|
78046
|
+
return 0;
|
|
78047
|
+
}
|
|
78048
|
+
|
|
77902
78049
|
// ../../packages/cli/src/index.ts
|
|
77903
78050
|
function buildProgram() {
|
|
77904
78051
|
const program2 = new Command();
|
|
@@ -78211,6 +78358,36 @@ Examples:
|
|
|
78211
78358
|
process.exitCode = await runMetrics(hint, opts);
|
|
78212
78359
|
}
|
|
78213
78360
|
);
|
|
78361
|
+
const skill = program2.command("skill").description("Manage the Horus agent skill \u2014 install playbooks that teach agents to use Horus as their evidence layer");
|
|
78362
|
+
skill.command("install <target>").description("Install the Horus skill for a coding agent (claude | codex | gemini | cursor | generic)").option("--force", "overwrite an existing skill file").option("--global", "install into the home directory instead of the current repo").action(async (target, opts) => {
|
|
78363
|
+
process.exitCode = await runSkillInstall(target, { force: opts.force, global: opts.global });
|
|
78364
|
+
}).addHelpText("after", `
|
|
78365
|
+
Targets:
|
|
78366
|
+
claude \u2192 .claude/skills/horus.md (Claude Code \u2014 loaded automatically)
|
|
78367
|
+
codex \u2192 .horus/skills/horus-codex.md
|
|
78368
|
+
gemini \u2192 .horus/skills/horus-gemini.md
|
|
78369
|
+
cursor \u2192 .horus/skills/horus-cursor.md
|
|
78370
|
+
generic \u2192 .horus/skills/horus-generic.md
|
|
78371
|
+
|
|
78372
|
+
Examples:
|
|
78373
|
+
horus skill install claude
|
|
78374
|
+
horus skill install generic --force
|
|
78375
|
+
horus skill install claude --global
|
|
78376
|
+
`);
|
|
78377
|
+
skill.command("print <target>").description("Print the Horus skill to stdout \u2014 copy it into any agent setup").action(async (target) => {
|
|
78378
|
+
process.exitCode = await runSkillPrint(target, {});
|
|
78379
|
+
}).addHelpText("after", `
|
|
78380
|
+
Examples:
|
|
78381
|
+
horus skill print generic
|
|
78382
|
+
horus skill print claude
|
|
78383
|
+
`);
|
|
78384
|
+
skill.command("path <target>").description("Print the install path for the given target").option("--global", "show the global (home directory) path").action(async (target, opts) => {
|
|
78385
|
+
process.exitCode = await runSkillPath(target, { global: opts.global });
|
|
78386
|
+
}).addHelpText("after", `
|
|
78387
|
+
Examples:
|
|
78388
|
+
horus skill path claude
|
|
78389
|
+
horus skill path generic --global
|
|
78390
|
+
`);
|
|
78214
78391
|
return program2;
|
|
78215
78392
|
}
|
|
78216
78393
|
async function run(argv = process.argv) {
|