buddy-agent-harness 0.14.0 → 0.16.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cli.mjs +314 -58
- package/dist/index.d.mts +35 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +267 -12
- package/dist/index.mjs.map +1 -1
- package/dist/skill-scripts/doctor.mjs +18 -6
- package/dist/skill-scripts/init.mjs +18 -6
- package/dist/skill-scripts/mcp.mjs +18 -6
- package/dist/skill-scripts/reference.mjs +18 -6
- package/llms.txt +102 -0
- package/package.json +4 -1
- package/plugin.json +1 -1
- package/skills/doctor-buddy-agent-harness/SKILL.md +1 -1
- package/skills/doctor-buddy-agent-harness/scripts/doctor.mjs +18 -6
- package/skills/init-buddy-agent-harness/SKILL.md +1 -1
- package/skills/init-buddy-agent-harness/scripts/doctor.mjs +18 -6
- package/skills/init-buddy-agent-harness/scripts/init.mjs +18 -6
- package/skills/reference/README.md +2 -2
- package/skills/reference/SKILL.md +8 -3
- package/skills/reference/references/create.md +15 -4
- package/skills/reference/scripts/reference.mjs +18 -6
- package/skills/repair/SKILL.md +1 -1
- package/skills/repair/scripts/doctor.mjs +18 -6
- package/skills/repair/scripts/mcp.mjs +18 -6
- package/src/cli.ts +12 -11
- package/src/command-output/command-output.ts +1 -1
- package/src/governance-overrides/governance-overrides.ts +32 -4
- package/src/governance-overrides/governance.command.ts +3 -0
- package/src/references/create-reference.ts +57 -0
- package/src/references/reference-document.ts +7 -1
- package/src/references/reference-invocation.ts +1 -1
- package/src/references/reference.command.ts +245 -9
- package/src/references/resolve-reference.ts +2 -1
package/dist/index.mjs
CHANGED
|
@@ -2088,6 +2088,11 @@ function stripMergeComments(body) {
|
|
|
2088
2088
|
const inFence = fenceTracker();
|
|
2089
2089
|
return body.split("\n").filter((line) => inFence(line) || !mergeCommentPattern.test(line)).join("\n");
|
|
2090
2090
|
}
|
|
2091
|
+
/** Each heading with a single `#` outside a code fence, as written. */
|
|
2092
|
+
function titleHeadings(body) {
|
|
2093
|
+
const inFence = fenceTracker();
|
|
2094
|
+
return body.split("\n").filter((line) => !inFence(line) && headingPattern.exec(line)?.[1] === "#");
|
|
2095
|
+
}
|
|
2091
2096
|
function sectionKey(title) {
|
|
2092
2097
|
return title.trim().replace(/\s+/g, " ").toLowerCase();
|
|
2093
2098
|
}
|
|
@@ -2264,6 +2269,7 @@ function pluginLabel(layer) {
|
|
|
2264
2269
|
function layerName(layer) {
|
|
2265
2270
|
return layer.tier === "plugin" ? `plugin ${pluginLabel(layer)}` : layer.tier;
|
|
2266
2271
|
}
|
|
2272
|
+
/** The layers a name is resolved through, in the order `resolveReference` traces them. */
|
|
2267
2273
|
function layersFor$2(ref, layers) {
|
|
2268
2274
|
const plugin = ref.plugin;
|
|
2269
2275
|
if (plugin === void 0) return [...layers];
|
|
@@ -2512,6 +2518,7 @@ function searchReferences(query, layers, options = {}) {
|
|
|
2512
2518
|
}
|
|
2513
2519
|
//#endregion
|
|
2514
2520
|
//#region src/governance-overrides/governance-overrides.ts
|
|
2521
|
+
/** @deprecated Use `managedReferencesDir`. Removed in the next major version. */
|
|
2515
2522
|
function managedGovernancesDir(platform, programData) {
|
|
2516
2523
|
if (platform === "darwin") return "/Library/Application Support/BuddyAgentHarness/governances";
|
|
2517
2524
|
if (platform === "win32") return join(programData || "C:\\ProgramData", "BuddyAgentHarness", "governances");
|
|
@@ -2520,6 +2527,8 @@ function managedGovernancesDir(platform, programData) {
|
|
|
2520
2527
|
/**
|
|
2521
2528
|
* Still read below the layer above, so a machine already using it keeps working; reported as
|
|
2522
2529
|
* deprecated so an admin knows to move it.
|
|
2530
|
+
*
|
|
2531
|
+
* @deprecated Use `managedReferencesDir`. Removed in the next major version.
|
|
2523
2532
|
*/
|
|
2524
2533
|
function deprecatedManagedGovernancesDir(platform, programData) {
|
|
2525
2534
|
if (platform === "darwin") return "/Library/Application Support/UniPlugin/governances";
|
|
@@ -2545,6 +2554,7 @@ function packageGovernancesDir(from = fileURLToPath(import.meta.url)) {
|
|
|
2545
2554
|
dir = parent;
|
|
2546
2555
|
}
|
|
2547
2556
|
}
|
|
2557
|
+
/** @deprecated Use `referenceLayers`. Removed in the next major version. */
|
|
2548
2558
|
function governanceLayers({ root, home, platform, programData }) {
|
|
2549
2559
|
return [
|
|
2550
2560
|
{
|
|
@@ -2572,6 +2582,8 @@ function governanceLayers({ root, home, platform, programData }) {
|
|
|
2572
2582
|
/**
|
|
2573
2583
|
* Filters by scope rather than slicing the list, so a layer added later can't quietly become an
|
|
2574
2584
|
* override by position.
|
|
2585
|
+
*
|
|
2586
|
+
* @deprecated Use `referenceLayers`. Removed in the next major version.
|
|
2575
2587
|
*/
|
|
2576
2588
|
function overrideLayers(layers) {
|
|
2577
2589
|
return layers.filter((layer) => layer.scope !== "package");
|
|
@@ -2580,6 +2592,8 @@ const namePattern = /^[a-z0-9]+(?:[-.][a-z0-9]+)*$/i;
|
|
|
2580
2592
|
/**
|
|
2581
2593
|
* Rejects rather than sanitizes — silently answering a different question is how untrusted input
|
|
2582
2594
|
* reads a file outside the layer.
|
|
2595
|
+
*
|
|
2596
|
+
* @deprecated Use `parseReferenceName`. Removed in the next major version.
|
|
2583
2597
|
*/
|
|
2584
2598
|
function parseGovernanceName(value) {
|
|
2585
2599
|
if (value.endsWith(".md")) throw new Error(`"${value}" names a file. Ask for the governance by name, without the .md extension.`);
|
|
@@ -2601,7 +2615,11 @@ function documentNames(dir) {
|
|
|
2601
2615
|
return [];
|
|
2602
2616
|
}
|
|
2603
2617
|
}
|
|
2604
|
-
/**
|
|
2618
|
+
/**
|
|
2619
|
+
* The first layer that holds the name wins; the rest are not read.
|
|
2620
|
+
*
|
|
2621
|
+
* @deprecated Use `resolveReference`. Removed in the next major version.
|
|
2622
|
+
*/
|
|
2605
2623
|
function resolveGovernance(name, layers) {
|
|
2606
2624
|
for (const { scope, dir } of layers) {
|
|
2607
2625
|
const path = join(dir, `${name}.md`);
|
|
@@ -2614,7 +2632,11 @@ function resolveGovernance(name, layers) {
|
|
|
2614
2632
|
};
|
|
2615
2633
|
}
|
|
2616
2634
|
}
|
|
2617
|
-
/**
|
|
2635
|
+
/**
|
|
2636
|
+
* Every name any layer holds, each reported at the layer that would win, sorted by name.
|
|
2637
|
+
*
|
|
2638
|
+
* @deprecated Use `listReferences`. Removed in the next major version.
|
|
2639
|
+
*/
|
|
2618
2640
|
function listGovernances(layers) {
|
|
2619
2641
|
const found = /* @__PURE__ */ new Map();
|
|
2620
2642
|
for (const { scope, dir } of layers) for (const name of documentNames(dir)) if (!found.has(name)) found.set(name, {
|
|
@@ -3579,12 +3601,61 @@ const governanceShowCommand = command({
|
|
|
3579
3601
|
}
|
|
3580
3602
|
}
|
|
3581
3603
|
});
|
|
3604
|
+
/** @deprecated Use `referenceCommand`. Removed in the next major version. */
|
|
3582
3605
|
const governanceCommand = command({
|
|
3583
3606
|
name: "governance",
|
|
3584
3607
|
description: "Deprecated: use `reference`. Read the governance documents the project, user, and machine-wide override layers hold. Read-only.",
|
|
3585
3608
|
commands: [governanceListCommand, governanceShowCommand]
|
|
3586
3609
|
});
|
|
3587
3610
|
//#endregion
|
|
3611
|
+
//#region src/references/create-reference.ts
|
|
3612
|
+
/** No `#` title: `merge-sections` matches by heading path, so a title would hold every section under it. */
|
|
3613
|
+
const defaultTemplate = `---
|
|
3614
|
+
description: What this reference covers, and when an agent should read it.
|
|
3615
|
+
tags: [topic]
|
|
3616
|
+
---
|
|
3617
|
+
|
|
3618
|
+
## Overview
|
|
3619
|
+
|
|
3620
|
+
Write the guidance here. Give each topic its own top-level \`##\` section.
|
|
3621
|
+
`;
|
|
3622
|
+
function readTemplate(path) {
|
|
3623
|
+
if (path === void 0) return parseTemplate(defaultTemplate, "the default template");
|
|
3624
|
+
let content;
|
|
3625
|
+
try {
|
|
3626
|
+
content = readFileSync(path, "utf8");
|
|
3627
|
+
} catch (error) {
|
|
3628
|
+
throw new Error(`cannot read the template ${path}: ${error.message}`);
|
|
3629
|
+
}
|
|
3630
|
+
return parseTemplate(content, `the template ${path}`);
|
|
3631
|
+
}
|
|
3632
|
+
function parseTemplate(content, label) {
|
|
3633
|
+
let mapping = true;
|
|
3634
|
+
const { metadata, body } = parseDocument(content, () => {
|
|
3635
|
+
mapping = false;
|
|
3636
|
+
});
|
|
3637
|
+
if (!mapping) throw new Error(`${label} has frontmatter that is not a YAML mapping.`);
|
|
3638
|
+
return {
|
|
3639
|
+
content,
|
|
3640
|
+
metadata,
|
|
3641
|
+
body
|
|
3642
|
+
};
|
|
3643
|
+
}
|
|
3644
|
+
/** Adds one line and changes nothing else, so the result still reads as the template it came from. */
|
|
3645
|
+
function withMergeSections(content) {
|
|
3646
|
+
const match = frontmatterPattern.exec(content);
|
|
3647
|
+
if (!match) return `---\nmerge: merge-sections\n---\n\n${content}`;
|
|
3648
|
+
const open = match[0].indexOf("\n") + 1;
|
|
3649
|
+
const newline = match[0][open - 2] === "\r" ? "\r\n" : "\n";
|
|
3650
|
+
const end = open + match[1].length;
|
|
3651
|
+
return `${content.slice(0, end)}${newline}merge: merge-sections${content.slice(end)}`;
|
|
3652
|
+
}
|
|
3653
|
+
function templateWarnings({ metadata, body }) {
|
|
3654
|
+
const warnings = titleHeadings(body).map((heading) => `"${heading.trim()}" is a heading with one hash; merge-sections matches by heading path, so an override would replace or duplicate the whole document. Use top-level ## sections.`);
|
|
3655
|
+
if (typeof metadata["description"] !== "string" || !metadata["description"].trim()) warnings.push("the reference has no `description` in its frontmatter; `list` and `search` show it blank.");
|
|
3656
|
+
return warnings;
|
|
3657
|
+
}
|
|
3658
|
+
//#endregion
|
|
3588
3659
|
//#region src/references/reference.command.ts
|
|
3589
3660
|
const rootOption = {
|
|
3590
3661
|
description: "Directory the project tier is read from, and each folder above it up to the repository root. Defaults to the current directory.",
|
|
@@ -3603,6 +3674,12 @@ function fail(error, fallback) {
|
|
|
3603
3674
|
process.stderr.write(`error: ${error instanceof Error ? error.message : fallback}\n`);
|
|
3604
3675
|
return exitCodes.error;
|
|
3605
3676
|
}
|
|
3677
|
+
function traceOf(resolved, home) {
|
|
3678
|
+
return resolved.trace.map(({ description: _, ...step }) => ({
|
|
3679
|
+
...step,
|
|
3680
|
+
path: collapseHome(home, step.path)
|
|
3681
|
+
}));
|
|
3682
|
+
}
|
|
3606
3683
|
function showEntry(resolved, home, suggestions, trace) {
|
|
3607
3684
|
const entry = {
|
|
3608
3685
|
name: resolved.name,
|
|
@@ -3624,10 +3701,7 @@ function showEntry(resolved, home, suggestions, trace) {
|
|
|
3624
3701
|
if (resolved.status === "missing") entry.suggestions = suggestions;
|
|
3625
3702
|
if (resolved.status === "ambiguous") entry.plugins = resolved.plugins;
|
|
3626
3703
|
entry.warnings = resolved.warnings;
|
|
3627
|
-
if (trace) entry.trace = resolved
|
|
3628
|
-
...step,
|
|
3629
|
-
path: collapseHome(home, step.path)
|
|
3630
|
-
}));
|
|
3704
|
+
if (trace) entry.trace = traceOf(resolved, home);
|
|
3631
3705
|
return entry;
|
|
3632
3706
|
}
|
|
3633
3707
|
function missReason(entry) {
|
|
@@ -3761,13 +3835,180 @@ const referenceSearchCommand = command({
|
|
|
3761
3835
|
}
|
|
3762
3836
|
}
|
|
3763
3837
|
});
|
|
3838
|
+
/** Managed is left out: writing there needs an admin, and most of it cannot be read locally. */
|
|
3839
|
+
const slotScopes = {
|
|
3840
|
+
project: "everyone working in this repository",
|
|
3841
|
+
user: "only you, in every repository",
|
|
3842
|
+
plugin: "read-only; override it with the project or user file"
|
|
3843
|
+
};
|
|
3844
|
+
const callerScope = "read-only; the calling skill's own copy, read only when no layer holds the name";
|
|
3845
|
+
const mergeNote = "The default, first-wins, makes the override replace the whole document. Set `merge: merge-sections` in its frontmatter to keep the sections it does not redefine.";
|
|
3846
|
+
function slotStatus(outcome) {
|
|
3847
|
+
if (outcome === "missing") return "empty";
|
|
3848
|
+
return outcome.startsWith("shadowed") ? "shadowed" : outcome;
|
|
3849
|
+
}
|
|
3850
|
+
/** Where Load reads the caller's copy when no layer holds the name, in the order it tries them. */
|
|
3851
|
+
function callerCopy(caller, name) {
|
|
3852
|
+
return [join(caller, "references", `${name}.md`), join(caller, "references", "governances", `${name}.md`)].find((path) => existsSync(path));
|
|
3853
|
+
}
|
|
3854
|
+
function callerStatus(resolved) {
|
|
3855
|
+
if (resolved.status === "missing") return "used";
|
|
3856
|
+
return resolved.status === "ambiguous" ? "not read — the name is ambiguous" : "shadowed";
|
|
3857
|
+
}
|
|
3858
|
+
const referenceWhereCommand = command({
|
|
3859
|
+
name: "where",
|
|
3860
|
+
description: "List the project and user files an override of a reference can be written to, highest precedence first, with the copy each overrides and who it applies to.",
|
|
3861
|
+
arguments: [{
|
|
3862
|
+
name: "name",
|
|
3863
|
+
description: "Reference name, without the `.md` extension; `<plugin>/<name>` picks one plugin.",
|
|
3864
|
+
type: z.string()
|
|
3865
|
+
}],
|
|
3866
|
+
options: {
|
|
3867
|
+
root: rootOption,
|
|
3868
|
+
caller: {
|
|
3869
|
+
description: "Folder of the skill that loads the reference, so its own copy is reported as the reference skill's Load mode reads it.",
|
|
3870
|
+
type: z.optional(z.string())
|
|
3871
|
+
},
|
|
3872
|
+
format: listFormatOption
|
|
3873
|
+
},
|
|
3874
|
+
async run(args) {
|
|
3875
|
+
try {
|
|
3876
|
+
const format = parseFormat(args.format);
|
|
3877
|
+
const name = parseReferenceName(args.name);
|
|
3878
|
+
const home = homedir();
|
|
3879
|
+
const layers = await layersFor(args, home);
|
|
3880
|
+
const root = resolve(args.root ?? process.cwd());
|
|
3881
|
+
const display = (path) => collapseHome(home, path);
|
|
3882
|
+
const resolved = resolveReference(name, layers, { display });
|
|
3883
|
+
const traced = layersFor$2(name, layers);
|
|
3884
|
+
const slots = [];
|
|
3885
|
+
for (const [index, step] of resolved.trace.entries()) {
|
|
3886
|
+
const layer = traced[index];
|
|
3887
|
+
const scope = slotScopes[step.tier];
|
|
3888
|
+
if (!scope || (layer.status || step.tier === "plugin") && !step.found) continue;
|
|
3889
|
+
const path = step.found ? step.path : join(layer.dir, `${name.name}.md`);
|
|
3890
|
+
slots.push({
|
|
3891
|
+
layer: step.tier === "plugin" ? `plugin ${step.plugin}` : step.tier,
|
|
3892
|
+
path: step.tier === "project" ? relative(root, path) : display(path),
|
|
3893
|
+
status: slotStatus(step.outcome),
|
|
3894
|
+
scope
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
const copy = args.caller === void 0 ? void 0 : callerCopy(resolve(args.caller), name.name);
|
|
3898
|
+
if (copy) slots.push({
|
|
3899
|
+
layer: "caller",
|
|
3900
|
+
path: display(copy),
|
|
3901
|
+
status: callerStatus(resolved),
|
|
3902
|
+
scope: callerScope
|
|
3903
|
+
});
|
|
3904
|
+
const report = {
|
|
3905
|
+
name: name.name,
|
|
3906
|
+
root: display(root),
|
|
3907
|
+
slots,
|
|
3908
|
+
merge: mergeNote
|
|
3909
|
+
};
|
|
3910
|
+
if (resolved.status === "ambiguous") report.plugins = resolved.plugins;
|
|
3911
|
+
if (resolved.warnings.length) report.warnings = resolved.warnings;
|
|
3912
|
+
writeResult(report, format);
|
|
3913
|
+
if (resolved.status !== "ambiguous") return exitCodes.success;
|
|
3914
|
+
process.stderr.write(`error: ${missReason({
|
|
3915
|
+
name: name.raw,
|
|
3916
|
+
status: "ambiguous",
|
|
3917
|
+
plugins: resolved.plugins,
|
|
3918
|
+
warnings: []
|
|
3919
|
+
})}\n`);
|
|
3920
|
+
return exitCodes.error;
|
|
3921
|
+
} catch (error) {
|
|
3922
|
+
return fail(error, "Reference placement lookup failed.");
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
});
|
|
3926
|
+
function parseScope(value) {
|
|
3927
|
+
if (value !== "project" && value !== "user") throw new Error("--scope must be project or user.");
|
|
3928
|
+
return value;
|
|
3929
|
+
}
|
|
3930
|
+
const referenceCreateCommand = command({
|
|
3931
|
+
name: "create",
|
|
3932
|
+
description: "Start a new reference in the project or user tier from a template, marked merge-sections when it overrides a copy below. Never overwrites.",
|
|
3933
|
+
arguments: [{
|
|
3934
|
+
name: "name",
|
|
3935
|
+
description: "Reference name, without the `.md` extension.",
|
|
3936
|
+
type: z.string()
|
|
3937
|
+
}],
|
|
3938
|
+
options: {
|
|
3939
|
+
root: rootOption,
|
|
3940
|
+
template: {
|
|
3941
|
+
description: "File whose text is written as it is, frontmatter included. Defaults to a built-in template of top-level `##` sections with no `#` title.",
|
|
3942
|
+
type: z.optional(z.string())
|
|
3943
|
+
},
|
|
3944
|
+
scope: {
|
|
3945
|
+
description: "Tier to write: project (default), `.agents/references/` at the root, or user, `~/.agents/references/`.",
|
|
3946
|
+
type: z.optional(z.string()),
|
|
3947
|
+
default: "project"
|
|
3948
|
+
},
|
|
3949
|
+
"dry-run": {
|
|
3950
|
+
description: "Print the target path and the exact content, and write nothing.",
|
|
3951
|
+
type: z.optional(z.boolean())
|
|
3952
|
+
},
|
|
3953
|
+
format: {
|
|
3954
|
+
description: "Output format: text (default) writes the path, then the content or the trace; toon and json return an object.",
|
|
3955
|
+
type: z.optional(z.string()),
|
|
3956
|
+
default: "text"
|
|
3957
|
+
}
|
|
3958
|
+
},
|
|
3959
|
+
async run(args) {
|
|
3960
|
+
try {
|
|
3961
|
+
const format = parseFormat(args.format);
|
|
3962
|
+
const name = parseReferenceName(args.name);
|
|
3963
|
+
if (name.plugin !== void 0) throw new Error(`an override is written under the bare name, which every tier resolves; ask for "${name.name}".`);
|
|
3964
|
+
const scope = parseScope(args.scope);
|
|
3965
|
+
const template = readTemplate(args.template === void 0 ? void 0 : resolve(args.template));
|
|
3966
|
+
const home = homedir();
|
|
3967
|
+
const dir = scope === "project" ? projectReferencesDir(resolve(args.root ?? process.cwd())) : join(home, ".agents", "references");
|
|
3968
|
+
const target = join(dir, `${name.name}.md`);
|
|
3969
|
+
const display = (path) => collapseHome(home, path);
|
|
3970
|
+
const layers = await layersFor(args, home);
|
|
3971
|
+
const { trace } = resolveReference(name, layers, { display });
|
|
3972
|
+
const at = layers.findIndex((layer) => layer.dir === dir);
|
|
3973
|
+
if (trace[at]?.found) throw new Error(`${display(trace[at].path)} already holds "${name.name}"; change it with the reference skill's Update mode.`);
|
|
3974
|
+
const shadow = trace.slice(0, at).find((step) => step.found && step.merge === "first-wins");
|
|
3975
|
+
if (shadow) throw new Error(`the ${shadow.tier} copy ${display(shadow.path)} is first-wins, so nothing would read a new ${scope} file; change that copy instead.`);
|
|
3976
|
+
const content = trace.slice(at + 1).some((step) => step.found) && template.metadata["merge"] === void 0 ? withMergeSections(template.content) : template.content;
|
|
3977
|
+
const warnings = templateWarnings(template);
|
|
3978
|
+
const report = {
|
|
3979
|
+
name: name.name,
|
|
3980
|
+
scope,
|
|
3981
|
+
path: display(target),
|
|
3982
|
+
dryRun: Boolean(args["dry-run"]),
|
|
3983
|
+
content,
|
|
3984
|
+
warnings
|
|
3985
|
+
};
|
|
3986
|
+
if (!report.dryRun) {
|
|
3987
|
+
mkdirSync(dir, { recursive: true });
|
|
3988
|
+
writeFileSync(target, content, { flag: "wx" });
|
|
3989
|
+
report.trace = traceOf(resolveReference(name, layers, { display }), home);
|
|
3990
|
+
}
|
|
3991
|
+
if (format !== "text") writeResult(report, format);
|
|
3992
|
+
else {
|
|
3993
|
+
for (const warning of warnings) process.stderr.write(`warning: ${warning}\n`);
|
|
3994
|
+
if (report.trace) process.stdout.write(`${report.path}\n\n${renderText({ trace: report.trace })}\n`);
|
|
3995
|
+
else writeDocument(`${report.path}\n\n${content}`);
|
|
3996
|
+
}
|
|
3997
|
+
return exitCodes.success;
|
|
3998
|
+
} catch (error) {
|
|
3999
|
+
return fail(error, "Reference creation failed.");
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
});
|
|
3764
4003
|
const referenceCommand = command({
|
|
3765
4004
|
name: "reference",
|
|
3766
|
-
description: "Read on-demand reference documents by name, layered across the managed, project, user, and plugin tiers
|
|
4005
|
+
description: "Read on-demand reference documents by name, layered across the managed, project, user, and plugin tiers, and start a new one in the project or user tier.",
|
|
3767
4006
|
commands: [
|
|
3768
4007
|
referenceShowCommand,
|
|
3769
4008
|
referenceListCommand,
|
|
3770
|
-
referenceSearchCommand
|
|
4009
|
+
referenceSearchCommand,
|
|
4010
|
+
referenceWhereCommand,
|
|
4011
|
+
referenceCreateCommand
|
|
3771
4012
|
]
|
|
3772
4013
|
});
|
|
3773
4014
|
//#endregion
|
|
@@ -4638,12 +4879,26 @@ const mcpCommand = command({
|
|
|
4638
4879
|
//#endregion
|
|
4639
4880
|
//#region src/cli.ts
|
|
4640
4881
|
const version = typeof __PACKAGE_VERSION__ !== "undefined" ? __PACKAGE_VERSION__ : JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
4882
|
+
/** Exported for `scripts/generate-llms-txt.ts`, which lists the CLI from it; `app()` must stay built from it. */
|
|
4883
|
+
const rootCommand = {
|
|
4884
|
+
name: "buddy-agent-harness",
|
|
4885
|
+
description: "Initialize agent harness skill compatibility in consumer repositories.",
|
|
4886
|
+
commands: [
|
|
4887
|
+
initCommand,
|
|
4888
|
+
doctorCommand,
|
|
4889
|
+
mcpCommand,
|
|
4890
|
+
depPluginsCommand,
|
|
4891
|
+
referenceCommand,
|
|
4892
|
+
governanceCommand
|
|
4893
|
+
]
|
|
4894
|
+
};
|
|
4641
4895
|
function app() {
|
|
4642
|
-
|
|
4643
|
-
|
|
4896
|
+
const [first, ...rest] = rootCommand.commands;
|
|
4897
|
+
return rest.reduce((builder, command) => builder.command(command), cli({
|
|
4898
|
+
name: rootCommand.name,
|
|
4644
4899
|
version,
|
|
4645
|
-
description:
|
|
4646
|
-
}).command(
|
|
4900
|
+
description: rootCommand.description
|
|
4901
|
+
}).command(first));
|
|
4647
4902
|
}
|
|
4648
4903
|
/**
|
|
4649
4904
|
* The application boundary: argv in, exit code out — returned rather than written, so a caller that
|