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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +33 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/add.d.ts +3 -0
  8. package/dist/commands/add.d.ts.map +1 -0
  9. package/dist/commands/add.js +30 -0
  10. package/dist/commands/add.js.map +1 -0
  11. package/dist/commands/edit.d.ts +3 -0
  12. package/dist/commands/edit.d.ts.map +1 -0
  13. package/dist/commands/edit.js +128 -0
  14. package/dist/commands/edit.js.map +1 -0
  15. package/dist/commands/init.d.ts +3 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +20 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/onboard.d.ts +8 -0
  20. package/dist/commands/onboard.d.ts.map +1 -0
  21. package/dist/commands/onboard.js +144 -0
  22. package/dist/commands/onboard.js.map +1 -0
  23. package/dist/commands/prime.d.ts +3 -0
  24. package/dist/commands/prime.d.ts.map +1 -0
  25. package/dist/commands/prime.js +107 -0
  26. package/dist/commands/prime.js.map +1 -0
  27. package/dist/commands/prune.d.ts +3 -0
  28. package/dist/commands/prune.d.ts.map +1 -0
  29. package/dist/commands/prune.js +71 -0
  30. package/dist/commands/prune.js.map +1 -0
  31. package/dist/commands/query.d.ts +3 -0
  32. package/dist/commands/query.d.ts.map +1 -0
  33. package/dist/commands/query.js +58 -0
  34. package/dist/commands/query.js.map +1 -0
  35. package/dist/commands/record.d.ts +3 -0
  36. package/dist/commands/record.d.ts.map +1 -0
  37. package/dist/commands/record.js +206 -0
  38. package/dist/commands/record.js.map +1 -0
  39. package/dist/commands/search.d.ts +3 -0
  40. package/dist/commands/search.d.ts.map +1 -0
  41. package/dist/commands/search.js +80 -0
  42. package/dist/commands/search.js.map +1 -0
  43. package/dist/commands/setup.d.ts +29 -0
  44. package/dist/commands/setup.d.ts.map +1 -0
  45. package/dist/commands/setup.js +497 -0
  46. package/dist/commands/setup.js.map +1 -0
  47. package/dist/commands/status.d.ts +3 -0
  48. package/dist/commands/status.d.ts.map +1 -0
  49. package/dist/commands/status.js +32 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/commands/validate.d.ts +3 -0
  52. package/dist/commands/validate.d.ts.map +1 -0
  53. package/dist/commands/validate.js +62 -0
  54. package/dist/commands/validate.js.map +1 -0
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +2 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/schemas/config.d.ts +17 -0
  60. package/dist/schemas/config.d.ts.map +1 -0
  61. package/dist/schemas/config.js +16 -0
  62. package/dist/schemas/config.js.map +1 -0
  63. package/dist/schemas/index.d.ts +4 -0
  64. package/dist/schemas/index.d.ts.map +1 -0
  65. package/dist/schemas/index.js +2 -0
  66. package/dist/schemas/index.js.map +1 -0
  67. package/dist/schemas/record-schema.d.ts +230 -0
  68. package/dist/schemas/record-schema.d.ts.map +1 -0
  69. package/dist/schemas/record-schema.js +111 -0
  70. package/dist/schemas/record-schema.js.map +1 -0
  71. package/dist/schemas/record.d.ts +49 -0
  72. package/dist/schemas/record.d.ts.map +1 -0
  73. package/dist/schemas/record.js +2 -0
  74. package/dist/schemas/record.js.map +1 -0
  75. package/dist/utils/config.d.ts +11 -0
  76. package/dist/utils/config.d.ts.map +1 -0
  77. package/dist/utils/config.js +83 -0
  78. package/dist/utils/config.js.map +1 -0
  79. package/dist/utils/expertise.d.ts +14 -0
  80. package/dist/utils/expertise.d.ts.map +1 -0
  81. package/dist/utils/expertise.js +107 -0
  82. package/dist/utils/expertise.js.map +1 -0
  83. package/dist/utils/format.d.ts +28 -0
  84. package/dist/utils/format.d.ts.map +1 -0
  85. package/dist/utils/format.js +373 -0
  86. package/dist/utils/format.js.map +1 -0
  87. package/dist/utils/index.d.ts +4 -0
  88. package/dist/utils/index.d.ts.map +1 -0
  89. package/dist/utils/index.js +4 -0
  90. package/dist/utils/index.js.map +1 -0
  91. 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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerPruneCommand(program: Command): void;
3
+ //# sourceMappingURL=prune.d.ts.map
@@ -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":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerQueryCommand(program: Command): void;
3
+ //# sourceMappingURL=query.d.ts.map
@@ -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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerRecordCommand(program: Command): void;
3
+ //# sourceMappingURL=record.d.ts.map
@@ -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,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerSearchCommand(program: Command): void;
3
+ //# sourceMappingURL=search.d.ts.map
@@ -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"}