mulch-cli 0.1.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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +33 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +30 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/edit.d.ts +3 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +128 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +20 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/onboard.d.ts +8 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +144 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/prime.d.ts +3 -0
- package/dist/commands/prime.d.ts.map +1 -0
- package/dist/commands/prime.js +107 -0
- package/dist/commands/prime.js.map +1 -0
- package/dist/commands/prune.d.ts +3 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +71 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/commands/query.d.ts +3 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +58 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/record.d.ts +3 -0
- package/dist/commands/record.d.ts.map +1 -0
- package/dist/commands/record.js +206 -0
- package/dist/commands/record.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +80 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +497 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +32 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +62 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/config.d.ts +17 -0
- package/dist/schemas/config.d.ts.map +1 -0
- package/dist/schemas/config.js +16 -0
- package/dist/schemas/config.js.map +1 -0
- package/dist/schemas/index.d.ts +4 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/record-schema.d.ts +230 -0
- package/dist/schemas/record-schema.d.ts.map +1 -0
- package/dist/schemas/record-schema.js +111 -0
- package/dist/schemas/record-schema.js.map +1 -0
- package/dist/schemas/record.d.ts +49 -0
- package/dist/schemas/record.d.ts.map +1 -0
- package/dist/schemas/record.js +2 -0
- package/dist/schemas/record.js.map +1 -0
- package/dist/utils/config.d.ts +11 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +83 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/expertise.d.ts +14 -0
- package/dist/utils/expertise.d.ts.map +1 -0
- package/dist/utils/expertise.js +107 -0
- package/dist/utils/expertise.js.map +1 -0
- package/dist/utils/format.d.ts +28 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +373 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { Option } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { readConfig, getExpertisePath } from "../utils/config.js";
|
|
5
|
+
import { readExpertiseFile, getFileModTime } from "../utils/expertise.js";
|
|
6
|
+
import { formatDomainExpertise, formatPrimeOutput, formatDomainExpertiseXml, formatPrimeOutputXml, formatDomainExpertisePlain, formatPrimeOutputPlain, formatDomainExpertiseCompact, formatPrimeOutputCompact, formatMcpOutput, } from "../utils/format.js";
|
|
7
|
+
export function registerPrimeCommand(program) {
|
|
8
|
+
program
|
|
9
|
+
.command("prime")
|
|
10
|
+
.description("Generate a priming prompt from expertise records")
|
|
11
|
+
.argument("[domains...]", "optional domain(s) to scope output to")
|
|
12
|
+
.option("--full", "include full record details (classification, evidence)")
|
|
13
|
+
.option("--compact", "one-liner per record, no section headers")
|
|
14
|
+
.option("--mcp", "output in MCP-compatible JSON format")
|
|
15
|
+
.option("--domain <domains...>", "domain(s) to include")
|
|
16
|
+
.addOption(new Option("--format <format>", "output format")
|
|
17
|
+
.choices(["markdown", "xml", "plain"])
|
|
18
|
+
.default("markdown"))
|
|
19
|
+
.option("--export <path>", "export output to a file")
|
|
20
|
+
.action(async (domainsArg, options) => {
|
|
21
|
+
try {
|
|
22
|
+
const config = await readConfig();
|
|
23
|
+
const format = options.format ?? "markdown";
|
|
24
|
+
const requested = [...domainsArg, ...(options.domain ?? [])];
|
|
25
|
+
const unique = [...new Set(requested)];
|
|
26
|
+
for (const d of unique) {
|
|
27
|
+
if (!config.domains.includes(d)) {
|
|
28
|
+
console.error(`Error: Domain "${d}" not found in config. Available domains: ${config.domains.join(", ")}`);
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const targetDomains = unique.length > 0
|
|
34
|
+
? unique
|
|
35
|
+
: config.domains;
|
|
36
|
+
let output;
|
|
37
|
+
if (options.mcp) {
|
|
38
|
+
const domains = [];
|
|
39
|
+
for (const domain of targetDomains) {
|
|
40
|
+
const filePath = getExpertisePath(domain);
|
|
41
|
+
const records = await readExpertiseFile(filePath);
|
|
42
|
+
domains.push({ domain, entry_count: records.length, records });
|
|
43
|
+
}
|
|
44
|
+
output = formatMcpOutput(domains);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const domainSections = [];
|
|
48
|
+
for (const domain of targetDomains) {
|
|
49
|
+
const filePath = getExpertisePath(domain);
|
|
50
|
+
const records = await readExpertiseFile(filePath);
|
|
51
|
+
const lastUpdated = await getFileModTime(filePath);
|
|
52
|
+
if (options.compact) {
|
|
53
|
+
domainSections.push(formatDomainExpertiseCompact(domain, records, lastUpdated));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
switch (format) {
|
|
57
|
+
case "xml":
|
|
58
|
+
domainSections.push(formatDomainExpertiseXml(domain, records, lastUpdated));
|
|
59
|
+
break;
|
|
60
|
+
case "plain":
|
|
61
|
+
domainSections.push(formatDomainExpertisePlain(domain, records, lastUpdated));
|
|
62
|
+
break;
|
|
63
|
+
default:
|
|
64
|
+
domainSections.push(formatDomainExpertise(domain, records, lastUpdated, {
|
|
65
|
+
full: options.full,
|
|
66
|
+
}));
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (options.compact) {
|
|
72
|
+
output = formatPrimeOutputCompact(domainSections);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
switch (format) {
|
|
76
|
+
case "xml":
|
|
77
|
+
output = formatPrimeOutputXml(domainSections);
|
|
78
|
+
break;
|
|
79
|
+
case "plain":
|
|
80
|
+
output = formatPrimeOutputPlain(domainSections);
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
output = formatPrimeOutput(domainSections);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (options.export) {
|
|
89
|
+
await writeFile(options.export, output + "\n", "utf-8");
|
|
90
|
+
console.log(chalk.green(`Exported to ${options.export}`));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(output);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (err.code === "ENOENT") {
|
|
98
|
+
console.error("Error: No .mulch/ directory found. Run `mulch init` first.");
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
console.error(`Error: ${err.message}`);
|
|
102
|
+
}
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=prime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prime.js","sourceRoot":"","sources":["../../src/commands/prime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwCpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgE3D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { readConfig, getExpertisePath } from "../utils/config.js";
|
|
3
|
+
import { readExpertiseFile, writeExpertiseFile } from "../utils/expertise.js";
|
|
4
|
+
function isStale(record, now, shelfLife) {
|
|
5
|
+
const classification = record.classification;
|
|
6
|
+
if (classification === "foundational") {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const recordedAt = new Date(record.recorded_at);
|
|
10
|
+
const ageInDays = Math.floor((now.getTime() - recordedAt.getTime()) / (1000 * 60 * 60 * 24));
|
|
11
|
+
if (classification === "tactical") {
|
|
12
|
+
return ageInDays > shelfLife.tactical;
|
|
13
|
+
}
|
|
14
|
+
if (classification === "observational") {
|
|
15
|
+
return ageInDays > shelfLife.observational;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
export function registerPruneCommand(program) {
|
|
20
|
+
program
|
|
21
|
+
.command("prune")
|
|
22
|
+
.description("Remove outdated or low-value expertise records")
|
|
23
|
+
.option("--dry-run", "Show what would be pruned without removing", false)
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
const config = await readConfig();
|
|
26
|
+
const now = new Date();
|
|
27
|
+
const shelfLife = config.classification_defaults.shelf_life;
|
|
28
|
+
const results = [];
|
|
29
|
+
let totalPruned = 0;
|
|
30
|
+
for (const domain of config.domains) {
|
|
31
|
+
const filePath = getExpertisePath(domain);
|
|
32
|
+
const records = await readExpertiseFile(filePath);
|
|
33
|
+
if (records.length === 0) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const kept = [];
|
|
37
|
+
let pruned = 0;
|
|
38
|
+
for (const record of records) {
|
|
39
|
+
if (isStale(record, now, shelfLife)) {
|
|
40
|
+
pruned++;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
kept.push(record);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (pruned > 0) {
|
|
47
|
+
results.push({
|
|
48
|
+
domain,
|
|
49
|
+
before: records.length,
|
|
50
|
+
pruned,
|
|
51
|
+
after: kept.length,
|
|
52
|
+
});
|
|
53
|
+
totalPruned += pruned;
|
|
54
|
+
if (!options.dryRun) {
|
|
55
|
+
await writeExpertiseFile(filePath, kept);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (totalPruned === 0) {
|
|
60
|
+
console.log(chalk.green("No stale entries found. All records are current."));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const label = options.dryRun ? "Would prune" : "Pruned";
|
|
64
|
+
const prefix = options.dryRun ? chalk.yellow("[DRY RUN] ") : "";
|
|
65
|
+
for (const result of results) {
|
|
66
|
+
console.log(`${prefix}${chalk.cyan(result.domain)}: ${label} ${chalk.red(String(result.pruned))} of ${result.before} entries (${result.after} remaining)`);
|
|
67
|
+
}
|
|
68
|
+
console.log(`\n${prefix}${chalk.bold(`Total: ${label.toLowerCase()} ${totalPruned} stale ${totalPruned === 1 ? "entry" : "entries"}.`)}`);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAU9E,SAAS,OAAO,CACd,MAAuB,EACvB,GAAS,EACT,SAAsD;IAEtD,MAAM,cAAc,GAAmB,MAAM,CAAC,cAAc,CAAC;IAE7D,IAAI,cAAc,KAAK,cAAc,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAC1B,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAC/D,CAAC;IAEF,IAAI,cAAc,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC;IACxC,CAAC;IAED,IAAI,cAAc,KAAK,eAAe,EAAE,CAAC;QACvC,OAAO,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,WAAW,EAAE,4CAA4C,EAAE,KAAK,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,CAAC,uBAAuB,CAAC,UAAU,CAAC;QAC5D,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAElD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,MAAM,IAAI,GAAsB,EAAE,CAAC;YACnC,IAAI,MAAM,GAAG,CAAC,CAAC;YAEf,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;oBACpC,MAAM,EAAE,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC;oBACX,MAAM;oBACN,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,MAAM;oBACN,KAAK,EAAE,IAAI,CAAC,MAAM;iBACnB,CAAC,CAAC;gBACH,WAAW,IAAI,MAAM,CAAC;gBAEtB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,MAAM,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEhE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,aAAa,MAAM,CAAC,KAAK,aAAa,CAC9I,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,GAAG,CACT,KAAK,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,WAAW,EAAE,IAAI,WAAW,UAAU,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAC7H,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuD3D"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readConfig, getExpertisePath } from "../utils/config.js";
|
|
2
|
+
import { readExpertiseFile, getFileModTime, filterByType } from "../utils/expertise.js";
|
|
3
|
+
import { formatDomainExpertise } from "../utils/format.js";
|
|
4
|
+
export function registerQueryCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command("query")
|
|
7
|
+
.argument("[domain]", "expertise domain to query")
|
|
8
|
+
.description("Query expertise records")
|
|
9
|
+
.option("--type <type>", "filter by record type")
|
|
10
|
+
.option("--all", "show all domains")
|
|
11
|
+
.action(async (domain, options) => {
|
|
12
|
+
try {
|
|
13
|
+
const config = await readConfig();
|
|
14
|
+
const domainsToQuery = [];
|
|
15
|
+
if (options.all) {
|
|
16
|
+
domainsToQuery.push(...config.domains);
|
|
17
|
+
if (domainsToQuery.length === 0) {
|
|
18
|
+
console.log("No domains configured. Run `mulch add <domain>` to get started.");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (domain) {
|
|
23
|
+
if (!config.domains.includes(domain)) {
|
|
24
|
+
console.error(`Error: Domain "${domain}" not found in config. Available domains: ${config.domains.join(", ") || "(none)"}`);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
domainsToQuery.push(domain);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
console.error("Error: Please specify a domain or use --all to query all domains.");
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const sections = [];
|
|
36
|
+
for (const d of domainsToQuery) {
|
|
37
|
+
const filePath = getExpertisePath(d);
|
|
38
|
+
let records = await readExpertiseFile(filePath);
|
|
39
|
+
const lastUpdated = await getFileModTime(filePath);
|
|
40
|
+
if (options.type) {
|
|
41
|
+
records = filterByType(records, options.type);
|
|
42
|
+
}
|
|
43
|
+
sections.push(formatDomainExpertise(d, records, lastUpdated));
|
|
44
|
+
}
|
|
45
|
+
console.log(sections.join("\n\n"));
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err.code === "ENOENT") {
|
|
49
|
+
console.error("Error: No .mulch/ directory found. Run `mulch init` first.");
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.error(`Error: ${err.message}`);
|
|
53
|
+
}
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,QAAQ,CAAC,UAAU,EAAE,2BAA2B,CAAC;SACjD,WAAW,CAAC,yBAAyB,CAAC;SACtC,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC;SAChD,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,MAA0B,EAAE,OAAgC,EAAE,EAAE;QAC7E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;YAElC,MAAM,cAAc,GAAa,EAAE,CAAC;YAEpC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChB,cAAc,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;gBACvC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAChC,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;oBAC/E,OAAO;gBACT,CAAC;YACH,CAAC;iBAAM,IAAI,MAAM,EAAE,CAAC;gBAClB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACrC,OAAO,CAAC,KAAK,CAAC,kBAAkB,MAAM,6CAA6C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;oBAC5H,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;oBACrB,OAAO;gBACT,CAAC;gBACD,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;gBACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;gBACrC,IAAI,OAAO,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAChD,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAEnD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjB,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,IAAc,CAAC,CAAC;gBAC1D,CAAC;gBAED,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC9E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,UAAW,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/commands/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAmB5C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyQ5D"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Option } from "commander";
|
|
2
|
+
import _Ajv from "ajv";
|
|
3
|
+
const Ajv = _Ajv.default ?? _Ajv;
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { readConfig, getExpertisePath } from "../utils/config.js";
|
|
6
|
+
import { appendRecord, readExpertiseFile, writeExpertiseFile, findDuplicate, } from "../utils/expertise.js";
|
|
7
|
+
import { recordSchema } from "../schemas/record-schema.js";
|
|
8
|
+
export function registerRecordCommand(program) {
|
|
9
|
+
program
|
|
10
|
+
.command("record")
|
|
11
|
+
.argument("<domain>", "expertise domain")
|
|
12
|
+
.argument("[content]", "record content")
|
|
13
|
+
.description("Record an expertise entry")
|
|
14
|
+
.addOption(new Option("--type <type>", "record type")
|
|
15
|
+
.choices(["convention", "pattern", "failure", "decision", "reference", "guide"])
|
|
16
|
+
.makeOptionMandatory())
|
|
17
|
+
.addOption(new Option("--classification <classification>", "classification level")
|
|
18
|
+
.choices(["foundational", "tactical", "observational"])
|
|
19
|
+
.default("tactical"))
|
|
20
|
+
.option("--name <name>", "name of the convention or pattern")
|
|
21
|
+
.option("--description <description>", "description of the record")
|
|
22
|
+
.option("--resolution <resolution>", "resolution for failure records")
|
|
23
|
+
.option("--title <title>", "title for decision records")
|
|
24
|
+
.option("--rationale <rationale>", "rationale for decision records")
|
|
25
|
+
.option("--files <files>", "related files (comma-separated)")
|
|
26
|
+
.option("--tags <tags>", "comma-separated tags")
|
|
27
|
+
.option("--evidence-commit <commit>", "evidence: commit hash")
|
|
28
|
+
.option("--evidence-issue <issue>", "evidence: issue reference")
|
|
29
|
+
.option("--evidence-file <file>", "evidence: file path")
|
|
30
|
+
.option("--force", "force recording even if duplicate exists")
|
|
31
|
+
.action(async (domain, content, options) => {
|
|
32
|
+
const config = await readConfig();
|
|
33
|
+
if (!config.domains.includes(domain)) {
|
|
34
|
+
console.error(chalk.red(`Error: domain "${domain}" not found in config.`));
|
|
35
|
+
console.error(chalk.red(`Available domains: ${config.domains.join(", ") || "(none)"}`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const recordType = options.type;
|
|
39
|
+
const classification = options.classification ?? "tactical";
|
|
40
|
+
const recordedAt = new Date().toISOString();
|
|
41
|
+
// Build evidence if any evidence option is provided
|
|
42
|
+
let evidence;
|
|
43
|
+
if (options.evidenceCommit || options.evidenceIssue || options.evidenceFile) {
|
|
44
|
+
evidence = {};
|
|
45
|
+
if (options.evidenceCommit)
|
|
46
|
+
evidence.commit = options.evidenceCommit;
|
|
47
|
+
if (options.evidenceIssue)
|
|
48
|
+
evidence.issue = options.evidenceIssue;
|
|
49
|
+
if (options.evidenceFile)
|
|
50
|
+
evidence.file = options.evidenceFile;
|
|
51
|
+
}
|
|
52
|
+
const tags = typeof options.tags === "string"
|
|
53
|
+
? options.tags
|
|
54
|
+
.split(",")
|
|
55
|
+
.map((t) => t.trim())
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
: undefined;
|
|
58
|
+
let record;
|
|
59
|
+
switch (recordType) {
|
|
60
|
+
case "convention": {
|
|
61
|
+
const conventionContent = content ?? options.description;
|
|
62
|
+
if (!conventionContent) {
|
|
63
|
+
console.error(chalk.red("Error: convention records require content (positional argument or --description)."));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
record = {
|
|
67
|
+
type: "convention",
|
|
68
|
+
content: conventionContent,
|
|
69
|
+
classification,
|
|
70
|
+
recorded_at: recordedAt,
|
|
71
|
+
...(evidence && { evidence }),
|
|
72
|
+
...(tags && tags.length > 0 && { tags }),
|
|
73
|
+
};
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "pattern": {
|
|
77
|
+
const patternName = options.name;
|
|
78
|
+
const patternDesc = options.description ?? content;
|
|
79
|
+
if (!patternName || !patternDesc) {
|
|
80
|
+
console.error(chalk.red("Error: pattern records require --name and --description (or positional content)."));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
record = {
|
|
84
|
+
type: "pattern",
|
|
85
|
+
name: patternName,
|
|
86
|
+
description: patternDesc,
|
|
87
|
+
classification,
|
|
88
|
+
recorded_at: recordedAt,
|
|
89
|
+
...(evidence && { evidence }),
|
|
90
|
+
...(typeof options.files === "string" && {
|
|
91
|
+
files: options.files.split(","),
|
|
92
|
+
}),
|
|
93
|
+
...(tags && tags.length > 0 && { tags }),
|
|
94
|
+
};
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
case "failure": {
|
|
98
|
+
const failureDesc = options.description;
|
|
99
|
+
const failureResolution = options.resolution;
|
|
100
|
+
if (!failureDesc || !failureResolution) {
|
|
101
|
+
console.error(chalk.red("Error: failure records require --description and --resolution."));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
record = {
|
|
105
|
+
type: "failure",
|
|
106
|
+
description: failureDesc,
|
|
107
|
+
resolution: failureResolution,
|
|
108
|
+
classification,
|
|
109
|
+
recorded_at: recordedAt,
|
|
110
|
+
...(evidence && { evidence }),
|
|
111
|
+
...(tags && tags.length > 0 && { tags }),
|
|
112
|
+
};
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case "decision": {
|
|
116
|
+
const decisionTitle = options.title;
|
|
117
|
+
const decisionRationale = options.rationale;
|
|
118
|
+
if (!decisionTitle || !decisionRationale) {
|
|
119
|
+
console.error(chalk.red("Error: decision records require --title and --rationale."));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
record = {
|
|
123
|
+
type: "decision",
|
|
124
|
+
title: decisionTitle,
|
|
125
|
+
rationale: decisionRationale,
|
|
126
|
+
classification,
|
|
127
|
+
recorded_at: recordedAt,
|
|
128
|
+
...(evidence && { evidence }),
|
|
129
|
+
...(tags && tags.length > 0 && { tags }),
|
|
130
|
+
};
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "reference": {
|
|
134
|
+
const refName = options.name;
|
|
135
|
+
const refDesc = options.description ?? content;
|
|
136
|
+
if (!refName || !refDesc) {
|
|
137
|
+
console.error(chalk.red("Error: reference records require --name and --description (or positional content)."));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
record = {
|
|
141
|
+
type: "reference",
|
|
142
|
+
name: refName,
|
|
143
|
+
description: refDesc,
|
|
144
|
+
classification,
|
|
145
|
+
recorded_at: recordedAt,
|
|
146
|
+
...(evidence && { evidence }),
|
|
147
|
+
...(typeof options.files === "string" && {
|
|
148
|
+
files: options.files.split(","),
|
|
149
|
+
}),
|
|
150
|
+
...(tags && tags.length > 0 && { tags }),
|
|
151
|
+
};
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "guide": {
|
|
155
|
+
const guideName = options.name;
|
|
156
|
+
const guideDesc = options.description ?? content;
|
|
157
|
+
if (!guideName || !guideDesc) {
|
|
158
|
+
console.error(chalk.red("Error: guide records require --name and --description (or positional content)."));
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
record = {
|
|
162
|
+
type: "guide",
|
|
163
|
+
name: guideName,
|
|
164
|
+
description: guideDesc,
|
|
165
|
+
classification,
|
|
166
|
+
recorded_at: recordedAt,
|
|
167
|
+
...(evidence && { evidence }),
|
|
168
|
+
...(tags && tags.length > 0 && { tags }),
|
|
169
|
+
};
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Validate against JSON schema
|
|
174
|
+
const ajv = new Ajv();
|
|
175
|
+
const validate = ajv.compile(recordSchema);
|
|
176
|
+
if (!validate(record)) {
|
|
177
|
+
console.error(chalk.red("Error: record failed schema validation:"));
|
|
178
|
+
for (const err of validate.errors ?? []) {
|
|
179
|
+
console.error(chalk.red(` ${err.instancePath} ${err.message}`));
|
|
180
|
+
}
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
const filePath = getExpertisePath(domain);
|
|
184
|
+
const existing = await readExpertiseFile(filePath);
|
|
185
|
+
const dup = findDuplicate(existing, record);
|
|
186
|
+
if (dup && !options.force) {
|
|
187
|
+
const isNamed = record.type === "pattern" || record.type === "decision" ||
|
|
188
|
+
record.type === "reference" || record.type === "guide";
|
|
189
|
+
if (isNamed) {
|
|
190
|
+
// Upsert: replace in place
|
|
191
|
+
existing[dup.index] = record;
|
|
192
|
+
await writeExpertiseFile(filePath, existing);
|
|
193
|
+
console.log(chalk.green(`\u2714 Updated existing ${recordType} in ${domain} (record #${dup.index + 1})`));
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Exact match: skip
|
|
197
|
+
console.log(chalk.yellow(`Duplicate ${recordType} already exists in ${domain} (record #${dup.index + 1}). Use --force to add anyway.`));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
await appendRecord(filePath, record);
|
|
202
|
+
console.log(chalk.green(`\u2714 Recorded ${recordType} in ${domain}`));
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/commands/record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAM5C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6F5D"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Option } from "commander";
|
|
2
|
+
import { readConfig, getExpertisePath } from "../utils/config.js";
|
|
3
|
+
import { readExpertiseFile, getFileModTime, filterByType } from "../utils/expertise.js";
|
|
4
|
+
import { searchRecords } from "../utils/expertise.js";
|
|
5
|
+
import { formatDomainExpertise } from "../utils/format.js";
|
|
6
|
+
export function registerSearchCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command("search")
|
|
9
|
+
.argument("[query]", "search string (case-insensitive substring match)")
|
|
10
|
+
.description("Search expertise records across domains")
|
|
11
|
+
.option("--domain <domain>", "limit search to a specific domain")
|
|
12
|
+
.addOption(new Option("--type <type>", "filter by record type").choices([
|
|
13
|
+
"convention",
|
|
14
|
+
"pattern",
|
|
15
|
+
"failure",
|
|
16
|
+
"decision",
|
|
17
|
+
"reference",
|
|
18
|
+
"guide",
|
|
19
|
+
]))
|
|
20
|
+
.option("--tag <tag>", "filter by tag")
|
|
21
|
+
.action(async (query, options) => {
|
|
22
|
+
try {
|
|
23
|
+
if (!query && !options.type && !options.domain && !options.tag) {
|
|
24
|
+
console.error("Error: Provide a search query or use --type, --domain, or --tag to filter.");
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const config = await readConfig();
|
|
29
|
+
let domainsToSearch;
|
|
30
|
+
if (options.domain) {
|
|
31
|
+
if (!config.domains.includes(options.domain)) {
|
|
32
|
+
console.error(`Error: Domain "${options.domain}" not found in config. Available domains: ${config.domains.join(", ")}`);
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
domainsToSearch = [options.domain];
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
domainsToSearch = config.domains;
|
|
40
|
+
}
|
|
41
|
+
const sections = [];
|
|
42
|
+
let totalMatches = 0;
|
|
43
|
+
for (const domain of domainsToSearch) {
|
|
44
|
+
const filePath = getExpertisePath(domain);
|
|
45
|
+
let records = await readExpertiseFile(filePath);
|
|
46
|
+
const lastUpdated = await getFileModTime(filePath);
|
|
47
|
+
if (options.type) {
|
|
48
|
+
records = filterByType(records, options.type);
|
|
49
|
+
}
|
|
50
|
+
if (options.tag) {
|
|
51
|
+
const tagLower = options.tag.toLowerCase();
|
|
52
|
+
records = records.filter((r) => r.tags?.some((t) => t.toLowerCase() === tagLower));
|
|
53
|
+
}
|
|
54
|
+
const matches = query ? searchRecords(records, query) : records;
|
|
55
|
+
if (matches.length > 0) {
|
|
56
|
+
totalMatches += matches.length;
|
|
57
|
+
sections.push(formatDomainExpertise(domain, matches, lastUpdated));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const label = query ? `matching "${query}"` : "matching filters";
|
|
61
|
+
if (sections.length === 0) {
|
|
62
|
+
console.log(`No records ${label} found.`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(sections.join("\n\n"));
|
|
66
|
+
console.log(`\n${totalMatches} match${totalMatches === 1 ? "" : "es"} found.`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
if (err.code === "ENOENT") {
|
|
71
|
+
console.error("Error: No .mulch/ directory found. Run `mulch init` first.");
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.error(`Error: ${err.message}`);
|
|
75
|
+
}
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/** Supported provider names. */
|
|
3
|
+
declare const SUPPORTED_PROVIDERS: readonly ["claude", "cursor", "codex", "gemini", "windsurf", "aider"];
|
|
4
|
+
type Provider = (typeof SUPPORTED_PROVIDERS)[number];
|
|
5
|
+
/** Result of a provider recipe operation. */
|
|
6
|
+
interface RecipeResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
declare const MULCH_HOOK_SECTION = "# mulch:start\n# Run mulch validate before committing\nif command -v mulch >/dev/null 2>&1; then\n mulch validate\n if [ $? -ne 0 ]; then\n echo \"mulch validate failed. Commit aborted.\"\n exit 1\n fi\nfi\n# mulch:end";
|
|
11
|
+
declare function installGitHook(cwd: string): Promise<RecipeResult>;
|
|
12
|
+
declare function checkGitHook(cwd: string): Promise<RecipeResult>;
|
|
13
|
+
declare function removeGitHook(cwd: string): Promise<RecipeResult>;
|
|
14
|
+
interface ProviderRecipe {
|
|
15
|
+
/** Install the integration (idempotent). */
|
|
16
|
+
install(cwd: string): Promise<RecipeResult>;
|
|
17
|
+
/** Check whether the integration is installed. */
|
|
18
|
+
check(cwd: string): Promise<RecipeResult>;
|
|
19
|
+
/** Remove the integration. */
|
|
20
|
+
remove(cwd: string): Promise<RecipeResult>;
|
|
21
|
+
}
|
|
22
|
+
declare const CLAUDE_HOOK_COMMAND = "mulch prime";
|
|
23
|
+
declare const CURSOR_RULE_CONTENT = "---\ndescription: Mulch expertise integration\nglobs: *\nalwaysApply: true\n---\n\n# Mulch Expertise\n\nAt the start of every session, run the following command to load project expertise:\n\n```\nmulch prime\n```\n\nWhen you learn something new about this project (conventions, patterns, failures, decisions),\nrecord it with:\n\n```\nmulch record <domain> --type <convention|pattern|failure|decision> [options]\n```\n\nRun `mulch --help` for full usage.\n";
|
|
24
|
+
declare const CODEX_SECTION = "<!-- mulch:start -->\n## Mulch Expertise\n\nAt the start of every session, run `mulch prime` to load project expertise.\n\nWhen you learn something new about this project, record it with:\n\n```\nmulch record <domain> --type <convention|pattern|failure|decision> [options]\n```\n<!-- mulch:end -->";
|
|
25
|
+
declare const recipes: Record<Provider, ProviderRecipe>;
|
|
26
|
+
export { recipes, SUPPORTED_PROVIDERS, CURSOR_RULE_CONTENT, CODEX_SECTION, CLAUDE_HOOK_COMMAND, MULCH_HOOK_SECTION, installGitHook, checkGitHook, removeGitHook, };
|
|
27
|
+
export type { Provider, ProviderRecipe };
|
|
28
|
+
export declare function registerSetupCommand(program: Command): void;
|
|
29
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,gCAAgC;AAChC,QAAA,MAAM,mBAAmB,uEAOf,CAAC;AAEX,KAAK,QAAQ,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAMrD,6CAA6C;AAC7C,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AASD,QAAA,MAAM,kBAAkB,wOASL,CAAC;AAEpB,iBAAe,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA6BhE;AAED,iBAAe,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAY9D;AAED,iBAAe,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyB/D;AAMD,UAAU,cAAc;IACtB,4CAA4C;IAC5C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5C,kDAAkD;IAClD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,8BAA8B;IAC9B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5C;AAqBD,QAAA,MAAM,mBAAmB,gBAAgB,CAAC;AAuI1C,QAAA,MAAM,mBAAmB,6cAsBxB,CAAC;AAkDF,QAAA,MAAM,aAAa,8SAUS,CAAC;AAkK7B,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAO7C,CAAC;AAIF,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,aAAa,GACd,CAAC;AAEF,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;AAIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmG3D"}
|