@jayjiang/byoao 1.1.1 → 2.0.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 (139) hide show
  1. package/dist/__tests__/plugin-config.test.js +7 -10
  2. package/dist/__tests__/plugin-config.test.js.map +1 -1
  3. package/dist/assets/obsidian-skills/byoao-conventions.md +30 -54
  4. package/dist/assets/obsidian-skills/vault-thinking.md +6 -5
  5. package/dist/assets/presets/common/AGENTS.md.hbs +29 -46
  6. package/dist/assets/presets/common/SCHEMA.md.hbs +57 -0
  7. package/dist/assets/presets/common/Start Here.md.hbs +29 -40
  8. package/dist/assets/presets/minimal/preset.json +3 -3
  9. package/dist/assets/presets/pm-tpm/preset.json +2 -2
  10. package/dist/assets/skills/ask.md +133 -0
  11. package/dist/assets/skills/challenge.md +132 -0
  12. package/dist/assets/skills/connect.md +125 -0
  13. package/dist/assets/skills/cook.md +167 -0
  14. package/dist/assets/skills/diagnose.md +131 -0
  15. package/dist/assets/skills/drift.md +122 -0
  16. package/dist/assets/skills/health.md +63 -0
  17. package/dist/assets/skills/ideas.md +173 -0
  18. package/dist/assets/skills/organize.md +107 -0
  19. package/dist/assets/skills/prep.md +63 -0
  20. package/dist/assets/skills/trace.md +141 -0
  21. package/dist/assets/skills/wiki.md +126 -0
  22. package/dist/cli/cli-program.js +17 -14
  23. package/dist/cli/cli-program.js.map +1 -1
  24. package/dist/cli/installer.js +47 -6
  25. package/dist/cli/installer.js.map +1 -1
  26. package/dist/hooks/idle-suggestions.js +4 -4
  27. package/dist/hooks/idle-suggestions.js.map +1 -1
  28. package/dist/hooks/system-transform.js +35 -1
  29. package/dist/hooks/system-transform.js.map +1 -1
  30. package/dist/index.js +397 -884
  31. package/dist/index.js.map +1 -1
  32. package/dist/plugin-config.js +6 -32
  33. package/dist/plugin-config.js.map +1 -1
  34. package/dist/tools/init-vault.js +8 -38
  35. package/dist/tools/init-vault.js.map +1 -1
  36. package/dist/tools/vault-doctor.js +1 -1
  37. package/dist/tools/vault-doctor.js.map +1 -1
  38. package/dist/tools/vault-status.js +1 -1
  39. package/dist/tools/vault-status.js.map +1 -1
  40. package/dist/vault/__tests__/create.test.js +48 -116
  41. package/dist/vault/__tests__/create.test.js.map +1 -1
  42. package/dist/vault/__tests__/doctor.test.js +14 -2
  43. package/dist/vault/__tests__/doctor.test.js.map +1 -1
  44. package/dist/vault/__tests__/manifest.test.js +2 -2
  45. package/dist/vault/__tests__/manifest.test.js.map +1 -1
  46. package/dist/vault/__tests__/status.test.js +13 -8
  47. package/dist/vault/__tests__/status.test.js.map +1 -1
  48. package/dist/vault/__tests__/upgrade.test.js +3 -3
  49. package/dist/vault/__tests__/upgrade.test.js.map +1 -1
  50. package/dist/vault/__tests__/vault-detect.test.js +1 -13
  51. package/dist/vault/__tests__/vault-detect.test.js.map +1 -1
  52. package/dist/vault/create.js +76 -229
  53. package/dist/vault/create.js.map +1 -1
  54. package/dist/vault/doctor.js +49 -0
  55. package/dist/vault/doctor.js.map +1 -1
  56. package/dist/vault/manifest.js +1 -1
  57. package/dist/vault/preset.js +10 -4
  58. package/dist/vault/preset.js.map +1 -1
  59. package/dist/vault/self-update.js +1 -1
  60. package/dist/vault/status.js +24 -3
  61. package/dist/vault/status.js.map +1 -1
  62. package/dist/vault/upgrade.js +121 -18
  63. package/dist/vault/upgrade.js.map +1 -1
  64. package/dist/vault/vault-detect.js +2 -4
  65. package/dist/vault/vault-detect.js.map +1 -1
  66. package/package.json +1 -1
  67. package/src/assets/obsidian-skills/byoao-conventions.md +30 -54
  68. package/src/assets/obsidian-skills/vault-thinking.md +6 -5
  69. package/src/assets/presets/common/AGENTS.md.hbs +29 -46
  70. package/src/assets/presets/common/SCHEMA.md.hbs +57 -0
  71. package/src/assets/presets/common/Start Here.md.hbs +29 -40
  72. package/src/assets/presets/minimal/preset.json +3 -3
  73. package/src/assets/presets/pm-tpm/preset.json +2 -2
  74. package/src/skills/ask.md +133 -0
  75. package/src/skills/challenge.md +79 -115
  76. package/src/skills/connect.md +75 -156
  77. package/src/skills/cook.md +167 -0
  78. package/src/skills/diagnose.md +99 -41
  79. package/src/skills/drift.md +64 -159
  80. package/src/skills/health.md +63 -0
  81. package/src/skills/ideas.md +19 -12
  82. package/src/skills/organize.md +56 -156
  83. package/src/skills/prep.md +63 -0
  84. package/src/skills/trace.md +76 -84
  85. package/src/skills/wiki.md +126 -0
  86. package/dist/assets/presets/common/Glossary.md.hbs +0 -16
  87. package/dist/assets/presets/common/obsidian/daily-notes.json +0 -5
  88. package/dist/assets/presets/common/obsidian/templates.json +0 -3
  89. package/dist/assets/presets/common/templates/Daily Note.md +0 -19
  90. package/dist/assets/presets/common/templates/Decision Record.md +0 -32
  91. package/dist/assets/presets/common/templates/Investigation.md +0 -34
  92. package/dist/assets/presets/common/templates/Meeting Notes.md +0 -25
  93. package/dist/tools/add-glossary-term.js +0 -21
  94. package/dist/tools/add-glossary-term.js.map +0 -1
  95. package/dist/tools/add-person.js +0 -21
  96. package/dist/tools/add-person.js.map +0 -1
  97. package/dist/tools/add-project.js +0 -24
  98. package/dist/tools/add-project.js.map +0 -1
  99. package/dist/tools/graph-health.js +0 -25
  100. package/dist/tools/graph-health.js.map +0 -1
  101. package/dist/tools/note-read.js +0 -19
  102. package/dist/tools/note-read.js.map +0 -1
  103. package/dist/tools/search-vault.js +0 -22
  104. package/dist/tools/search-vault.js.map +0 -1
  105. package/dist/vault/__tests__/glossary.test.js +0 -68
  106. package/dist/vault/__tests__/glossary.test.js.map +0 -1
  107. package/dist/vault/__tests__/graph-health.test.js +0 -102
  108. package/dist/vault/__tests__/graph-health.test.js.map +0 -1
  109. package/dist/vault/__tests__/member.test.js +0 -85
  110. package/dist/vault/__tests__/member.test.js.map +0 -1
  111. package/dist/vault/__tests__/note-read.test.js +0 -71
  112. package/dist/vault/__tests__/note-read.test.js.map +0 -1
  113. package/dist/vault/__tests__/obsidian-cli.test.js +0 -108
  114. package/dist/vault/__tests__/obsidian-cli.test.js.map +0 -1
  115. package/dist/vault/__tests__/search-vault.test.js +0 -93
  116. package/dist/vault/__tests__/search-vault.test.js.map +0 -1
  117. package/dist/vault/glossary.js +0 -27
  118. package/dist/vault/glossary.js.map +0 -1
  119. package/dist/vault/graph-health.js +0 -83
  120. package/dist/vault/graph-health.js.map +0 -1
  121. package/dist/vault/member.js +0 -67
  122. package/dist/vault/member.js.map +0 -1
  123. package/dist/vault/note-read.js +0 -70
  124. package/dist/vault/note-read.js.map +0 -1
  125. package/dist/vault/project.js +0 -68
  126. package/dist/vault/project.js.map +0 -1
  127. package/dist/vault/retrieval-types.js +0 -5
  128. package/dist/vault/retrieval-types.js.map +0 -1
  129. package/dist/vault/search-vault.js +0 -87
  130. package/dist/vault/search-vault.js.map +0 -1
  131. package/src/assets/presets/common/Glossary.md.hbs +0 -16
  132. package/src/assets/presets/common/obsidian/daily-notes.json +0 -5
  133. package/src/assets/presets/common/obsidian/templates.json +0 -3
  134. package/src/assets/presets/common/templates/Daily Note.md +0 -19
  135. package/src/assets/presets/common/templates/Decision Record.md +0 -32
  136. package/src/assets/presets/common/templates/Investigation.md +0 -34
  137. package/src/assets/presets/common/templates/Meeting Notes.md +0 -25
  138. package/src/skills/emerge.md +0 -161
  139. package/src/skills/weave.md +0 -282
package/dist/index.js CHANGED
@@ -4682,13 +4682,13 @@ var require_ast = __commonJS({
4682
4682
  helperExpression: function helperExpression(node) {
4683
4683
  return node.type === "SubExpression" || (node.type === "MustacheStatement" || node.type === "BlockStatement") && !!(node.params && node.params.length || node.hash);
4684
4684
  },
4685
- scopedId: function scopedId(path17) {
4686
- return /^\.|this\b/.test(path17.original);
4685
+ scopedId: function scopedId(path13) {
4686
+ return /^\.|this\b/.test(path13.original);
4687
4687
  },
4688
4688
  // an ID is simple if it only has one part, and that part is not
4689
4689
  // `..` or `this`.
4690
- simpleId: function simpleId(path17) {
4691
- return path17.parts.length === 1 && !AST.helpers.scopedId(path17) && !path17.depth;
4690
+ simpleId: function simpleId(path13) {
4691
+ return path13.parts.length === 1 && !AST.helpers.scopedId(path13) && !path13.depth;
4692
4692
  }
4693
4693
  }
4694
4694
  };
@@ -5758,12 +5758,12 @@ var require_helpers2 = __commonJS({
5758
5758
  loc
5759
5759
  };
5760
5760
  }
5761
- function prepareMustache(path17, params, hash2, open, strip, locInfo) {
5761
+ function prepareMustache(path13, params, hash2, open, strip, locInfo) {
5762
5762
  var escapeFlag = open.charAt(3) || open.charAt(2), escaped = escapeFlag !== "{" && escapeFlag !== "&";
5763
5763
  var decorator = /\*/.test(open);
5764
5764
  return {
5765
5765
  type: decorator ? "Decorator" : "MustacheStatement",
5766
- path: path17,
5766
+ path: path13,
5767
5767
  params,
5768
5768
  hash: hash2,
5769
5769
  escaped,
@@ -6033,9 +6033,9 @@ var require_compiler = __commonJS({
6033
6033
  },
6034
6034
  DecoratorBlock: function DecoratorBlock(decorator) {
6035
6035
  var program = decorator.program && this.compileProgram(decorator.program);
6036
- var params = this.setupFullMustacheParams(decorator, program, void 0), path17 = decorator.path;
6036
+ var params = this.setupFullMustacheParams(decorator, program, void 0), path13 = decorator.path;
6037
6037
  this.useDecorators = true;
6038
- this.opcode("registerDecorator", params.length, path17.original);
6038
+ this.opcode("registerDecorator", params.length, path13.original);
6039
6039
  },
6040
6040
  PartialStatement: function PartialStatement(partial2) {
6041
6041
  this.usePartial = true;
@@ -6099,46 +6099,46 @@ var require_compiler = __commonJS({
6099
6099
  }
6100
6100
  },
6101
6101
  ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
6102
- var path17 = sexpr.path, name = path17.parts[0], isBlock = program != null || inverse != null;
6103
- this.opcode("getContext", path17.depth);
6102
+ var path13 = sexpr.path, name = path13.parts[0], isBlock = program != null || inverse != null;
6103
+ this.opcode("getContext", path13.depth);
6104
6104
  this.opcode("pushProgram", program);
6105
6105
  this.opcode("pushProgram", inverse);
6106
- path17.strict = true;
6107
- this.accept(path17);
6106
+ path13.strict = true;
6107
+ this.accept(path13);
6108
6108
  this.opcode("invokeAmbiguous", name, isBlock);
6109
6109
  },
6110
6110
  simpleSexpr: function simpleSexpr(sexpr) {
6111
- var path17 = sexpr.path;
6112
- path17.strict = true;
6113
- this.accept(path17);
6111
+ var path13 = sexpr.path;
6112
+ path13.strict = true;
6113
+ this.accept(path13);
6114
6114
  this.opcode("resolvePossibleLambda");
6115
6115
  },
6116
6116
  helperSexpr: function helperSexpr(sexpr, program, inverse) {
6117
- var params = this.setupFullMustacheParams(sexpr, program, inverse), path17 = sexpr.path, name = path17.parts[0];
6117
+ var params = this.setupFullMustacheParams(sexpr, program, inverse), path13 = sexpr.path, name = path13.parts[0];
6118
6118
  if (this.options.knownHelpers[name]) {
6119
6119
  this.opcode("invokeKnownHelper", params.length, name);
6120
6120
  } else if (this.options.knownHelpersOnly) {
6121
6121
  throw new _exception2["default"]("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
6122
6122
  } else {
6123
- path17.strict = true;
6124
- path17.falsy = true;
6125
- this.accept(path17);
6126
- this.opcode("invokeHelper", params.length, path17.original, _ast2["default"].helpers.simpleId(path17));
6123
+ path13.strict = true;
6124
+ path13.falsy = true;
6125
+ this.accept(path13);
6126
+ this.opcode("invokeHelper", params.length, path13.original, _ast2["default"].helpers.simpleId(path13));
6127
6127
  }
6128
6128
  },
6129
- PathExpression: function PathExpression(path17) {
6130
- this.addDepth(path17.depth);
6131
- this.opcode("getContext", path17.depth);
6132
- var name = path17.parts[0], scoped = _ast2["default"].helpers.scopedId(path17), blockParamId = !path17.depth && !scoped && this.blockParamIndex(name);
6129
+ PathExpression: function PathExpression(path13) {
6130
+ this.addDepth(path13.depth);
6131
+ this.opcode("getContext", path13.depth);
6132
+ var name = path13.parts[0], scoped = _ast2["default"].helpers.scopedId(path13), blockParamId = !path13.depth && !scoped && this.blockParamIndex(name);
6133
6133
  if (blockParamId) {
6134
- this.opcode("lookupBlockParam", blockParamId, path17.parts);
6134
+ this.opcode("lookupBlockParam", blockParamId, path13.parts);
6135
6135
  } else if (!name) {
6136
6136
  this.opcode("pushContext");
6137
- } else if (path17.data) {
6137
+ } else if (path13.data) {
6138
6138
  this.options.data = true;
6139
- this.opcode("lookupData", path17.depth, path17.parts, path17.strict);
6139
+ this.opcode("lookupData", path13.depth, path13.parts, path13.strict);
6140
6140
  } else {
6141
- this.opcode("lookupOnContext", path17.parts, path17.falsy, path17.strict, scoped);
6141
+ this.opcode("lookupOnContext", path13.parts, path13.falsy, path13.strict, scoped);
6142
6142
  }
6143
6143
  },
6144
6144
  StringLiteral: function StringLiteral(string4) {
@@ -6488,16 +6488,16 @@ var require_util = __commonJS({
6488
6488
  }
6489
6489
  exports2.urlGenerate = urlGenerate;
6490
6490
  function normalize(aPath) {
6491
- var path17 = aPath;
6491
+ var path13 = aPath;
6492
6492
  var url2 = urlParse(aPath);
6493
6493
  if (url2) {
6494
6494
  if (!url2.path) {
6495
6495
  return aPath;
6496
6496
  }
6497
- path17 = url2.path;
6497
+ path13 = url2.path;
6498
6498
  }
6499
- var isAbsolute = exports2.isAbsolute(path17);
6500
- var parts = path17.split(/\/+/);
6499
+ var isAbsolute = exports2.isAbsolute(path13);
6500
+ var parts = path13.split(/\/+/);
6501
6501
  for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
6502
6502
  part = parts[i];
6503
6503
  if (part === ".") {
@@ -6514,15 +6514,15 @@ var require_util = __commonJS({
6514
6514
  }
6515
6515
  }
6516
6516
  }
6517
- path17 = parts.join("/");
6518
- if (path17 === "") {
6519
- path17 = isAbsolute ? "/" : ".";
6517
+ path13 = parts.join("/");
6518
+ if (path13 === "") {
6519
+ path13 = isAbsolute ? "/" : ".";
6520
6520
  }
6521
6521
  if (url2) {
6522
- url2.path = path17;
6522
+ url2.path = path13;
6523
6523
  return urlGenerate(url2);
6524
6524
  }
6525
- return path17;
6525
+ return path13;
6526
6526
  }
6527
6527
  exports2.normalize = normalize;
6528
6528
  function join2(aRoot, aPath) {
@@ -9303,8 +9303,8 @@ var require_printer = __commonJS({
9303
9303
  return this.accept(sexpr.path) + " " + params + hash2;
9304
9304
  };
9305
9305
  PrintVisitor.prototype.PathExpression = function(id) {
9306
- var path17 = id.parts.join("/");
9307
- return (id.data ? "@" : "") + "PATH:" + path17;
9306
+ var path13 = id.parts.join("/");
9307
+ return (id.data ? "@" : "") + "PATH:" + path13;
9308
9308
  };
9309
9309
  PrintVisitor.prototype.StringLiteral = function(string4) {
9310
9310
  return '"' + string4.value + '"';
@@ -12015,10 +12015,10 @@ function mergeDefs(...defs) {
12015
12015
  function cloneDef(schema) {
12016
12016
  return mergeDefs(schema._zod.def);
12017
12017
  }
12018
- function getElementAtPath(obj, path17) {
12019
- if (!path17)
12018
+ function getElementAtPath(obj, path13) {
12019
+ if (!path13)
12020
12020
  return obj;
12021
- return path17.reduce((acc, key) => acc?.[key], obj);
12021
+ return path13.reduce((acc, key) => acc?.[key], obj);
12022
12022
  }
12023
12023
  function promiseAllObject(promisesObj) {
12024
12024
  const keys = Object.keys(promisesObj);
@@ -12379,11 +12379,11 @@ function aborted(x, startIndex = 0) {
12379
12379
  }
12380
12380
  return false;
12381
12381
  }
12382
- function prefixIssues(path17, issues) {
12382
+ function prefixIssues(path13, issues) {
12383
12383
  return issues.map((iss) => {
12384
12384
  var _a;
12385
12385
  (_a = iss).path ?? (_a.path = []);
12386
- iss.path.unshift(path17);
12386
+ iss.path.unshift(path13);
12387
12387
  return iss;
12388
12388
  });
12389
12389
  }
@@ -12551,7 +12551,7 @@ function treeifyError(error45, _mapper) {
12551
12551
  return issue2.message;
12552
12552
  };
12553
12553
  const result = { errors: [] };
12554
- const processError = (error46, path17 = []) => {
12554
+ const processError = (error46, path13 = []) => {
12555
12555
  var _a, _b;
12556
12556
  for (const issue2 of error46.issues) {
12557
12557
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12561,7 +12561,7 @@ function treeifyError(error45, _mapper) {
12561
12561
  } else if (issue2.code === "invalid_element") {
12562
12562
  processError({ issues: issue2.issues }, issue2.path);
12563
12563
  } else {
12564
- const fullpath = [...path17, ...issue2.path];
12564
+ const fullpath = [...path13, ...issue2.path];
12565
12565
  if (fullpath.length === 0) {
12566
12566
  result.errors.push(mapper(issue2));
12567
12567
  continue;
@@ -12593,8 +12593,8 @@ function treeifyError(error45, _mapper) {
12593
12593
  }
12594
12594
  function toDotPath(_path) {
12595
12595
  const segs = [];
12596
- const path17 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12597
- for (const seg of path17) {
12596
+ const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12597
+ for (const seg of path13) {
12598
12598
  if (typeof seg === "number")
12599
12599
  segs.push(`[${seg}]`);
12600
12600
  else if (typeof seg === "symbol")
@@ -23791,9 +23791,6 @@ function renderTemplate(templateStr, data) {
23791
23791
  }
23792
23792
  return compiled(data);
23793
23793
  }
23794
- function today() {
23795
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23796
- }
23797
23794
 
23798
23795
  // dist/vault/preset.js
23799
23796
  import path from "node:path";
@@ -24276,8 +24273,8 @@ function getErrorMap2() {
24276
24273
 
24277
24274
  // node_modules/zod/v3/helpers/parseUtil.js
24278
24275
  var makeIssue = (params) => {
24279
- const { data, path: path17, errorMaps, issueData } = params;
24280
- const fullPath = [...path17, ...issueData.path || []];
24276
+ const { data, path: path13, errorMaps, issueData } = params;
24277
+ const fullPath = [...path13, ...issueData.path || []];
24281
24278
  const fullIssue = {
24282
24279
  ...issueData,
24283
24280
  path: fullPath
@@ -24393,11 +24390,11 @@ var errorUtil;
24393
24390
 
24394
24391
  // node_modules/zod/v3/types.js
24395
24392
  var ParseInputLazyPath = class {
24396
- constructor(parent, value, path17, key) {
24393
+ constructor(parent, value, path13, key) {
24397
24394
  this._cachedPath = [];
24398
24395
  this.parent = parent;
24399
24396
  this.data = value;
24400
- this._path = path17;
24397
+ this._path = path13;
24401
24398
  this._key = key;
24402
24399
  }
24403
24400
  get path() {
@@ -27840,52 +27837,26 @@ var coerce = {
27840
27837
  var NEVER2 = INVALID;
27841
27838
 
27842
27839
  // dist/plugin-config.js
27843
- var MemberSchema = external_exports2.object({
27844
- name: external_exports2.string(),
27845
- role: external_exports2.string().default("")
27846
- });
27847
- var ProjectSchema = external_exports2.object({
27848
- name: external_exports2.string(),
27849
- description: external_exports2.string().default("")
27850
- });
27851
- var GlossaryEntrySchema = external_exports2.object({
27840
+ var TaxonomyEntrySchema = external_exports2.object({
27852
27841
  term: external_exports2.string(),
27853
27842
  definition: external_exports2.string(),
27854
- domain: external_exports2.string().default("")
27843
+ domain: external_exports2.string().default(""),
27844
+ tags: external_exports2.array(external_exports2.string()).default([])
27855
27845
  });
27856
27846
  var VaultConfigSchema = external_exports2.object({
27857
27847
  kbName: external_exports2.string().min(1),
27858
27848
  ownerName: external_exports2.string().default(""),
27859
27849
  vaultPath: external_exports2.string(),
27860
- members: external_exports2.array(MemberSchema).default([]),
27861
- projects: external_exports2.array(ProjectSchema).default([]),
27862
- glossaryEntries: external_exports2.array(GlossaryEntrySchema).default([]),
27863
- jiraHost: external_exports2.string().default(""),
27864
- jiraProject: external_exports2.string().default(""),
27865
27850
  preset: external_exports2.string().default("minimal"),
27866
27851
  provider: external_exports2.enum(["copilot", "gemini", "skip"]).default("skip"),
27867
27852
  /** GCP Project ID — used for BigQuery MCP env and Gemini provider config */
27868
27853
  gcpProjectId: external_exports2.string().default(""),
27869
27854
  /** MCP server names to skip (user deselected in init flow) */
27870
- mcpSkip: external_exports2.array(external_exports2.string()).default([])
27871
- });
27872
- var AddMemberSchema = external_exports2.object({
27873
- vaultPath: external_exports2.string(),
27874
- name: external_exports2.string(),
27875
- role: external_exports2.string().default(""),
27876
- team: external_exports2.string().default("")
27877
- });
27878
- var AddProjectSchema = external_exports2.object({
27879
- vaultPath: external_exports2.string(),
27880
- name: external_exports2.string(),
27881
- description: external_exports2.string().default(""),
27882
- team: external_exports2.string().default("")
27883
- });
27884
- var AddGlossaryTermSchema = external_exports2.object({
27885
- vaultPath: external_exports2.string(),
27886
- term: external_exports2.string(),
27887
- definition: external_exports2.string(),
27888
- domain: external_exports2.string().default("")
27855
+ mcpSkip: external_exports2.array(external_exports2.string()).default([]),
27856
+ /** What domain this knowledge base covers (used in SCHEMA.md generation) */
27857
+ wikiDomain: external_exports2.string().default(""),
27858
+ /** Agent autonomy level: auto = agent applies changes, review = agent reports first */
27859
+ compilationMode: external_exports2.enum(["auto", "review"]).default("review")
27889
27860
  });
27890
27861
  var VaultStatusSchema = external_exports2.object({
27891
27862
  vaultPath: external_exports2.string()
@@ -27921,15 +27892,19 @@ var VaultDoctorSchema = external_exports2.object({
27921
27892
 
27922
27893
  // dist/vault/preset.js
27923
27894
  function getPresetsDir() {
27895
+ const distAssets = path.resolve(import.meta.dirname, "assets", "presets");
27924
27896
  const srcPresets = path.resolve(import.meta.dirname, "..", "assets", "presets");
27925
- const distPresets = path.resolve(import.meta.dirname, "..", "..", "src", "assets", "presets");
27897
+ const devPresets = path.resolve(import.meta.dirname, "..", "..", "src", "assets", "presets");
27898
+ if (fs.existsSync(distAssets))
27899
+ return distAssets;
27926
27900
  if (fs.existsSync(srcPresets))
27927
27901
  return srcPresets;
27928
- if (fs.existsSync(distPresets))
27929
- return distPresets;
27902
+ if (fs.existsSync(devPresets))
27903
+ return devPresets;
27930
27904
  throw new Error(`Cannot find presets directory. Looked in:
27905
+ ${distAssets}
27931
27906
  ${srcPresets}
27932
- ${distPresets}`);
27907
+ ${devPresets}`);
27933
27908
  }
27934
27909
  function listPresets() {
27935
27910
  const presetsDir = getPresetsDir();
@@ -28287,7 +28262,7 @@ async function configureProvider(provider, gcpProjectId) {
28287
28262
 
28288
28263
  // dist/vault/manifest.js
28289
28264
  import path4 from "node:path";
28290
- var PKG_VERSION = "1.1.1";
28265
+ var PKG_VERSION = "2.0.0";
28291
28266
  var InfrastructureSchema = external_exports2.object({
28292
28267
  skills: external_exports2.array(external_exports2.string()).default([]),
28293
28268
  commands: external_exports2.array(external_exports2.string()).default([]),
@@ -28303,7 +28278,7 @@ var ManifestSchema = external_exports2.object({
28303
28278
  });
28304
28279
  var MANIFEST_DIR = ".byoao";
28305
28280
  var MANIFEST_FILE = "manifest.json";
28306
- function today2() {
28281
+ function today() {
28307
28282
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
28308
28283
  }
28309
28284
  function manifestPath(vaultPath) {
@@ -28326,8 +28301,8 @@ async function writeManifest(vaultPath, preset, installedFiles, versionOverride)
28326
28301
  const manifest = {
28327
28302
  version: versionOverride ?? PKG_VERSION,
28328
28303
  preset,
28329
- createdAt: existing?.createdAt ?? today2(),
28330
- updatedAt: today2(),
28304
+ createdAt: existing?.createdAt ?? today(),
28305
+ updatedAt: today(),
28331
28306
  infrastructure: {
28332
28307
  skills: installedFiles.skills,
28333
28308
  commands: installedFiles.commands,
@@ -28354,8 +28329,7 @@ function detectVaultContext(dir) {
28354
28329
  continue;
28355
28330
  const hasAgentsMd = fs.existsSync(path5.join(candidate, "AGENTS.md"));
28356
28331
  const hasAgentMdFallback = fs.existsSync(path5.join(candidate, "AGENT.md"));
28357
- const hasGlossary = fs.existsSync(path5.join(candidate, "Knowledge", "Glossary.md"));
28358
- if (hasAgentsMd || hasAgentMdFallback || hasGlossary) {
28332
+ if (hasAgentsMd || hasAgentMdFallback) {
28359
28333
  return candidate;
28360
28334
  }
28361
28335
  }
@@ -28389,11 +28363,6 @@ function countWikilinks(content) {
28389
28363
  const matches = stripped.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g);
28390
28364
  return matches ? matches.length : 0;
28391
28365
  }
28392
- var MINIMAL_DIRECTORIES = [
28393
- "Daily",
28394
- "Knowledge",
28395
- "Knowledge/templates"
28396
- ];
28397
28366
  function makeContext(vaultPath, kbName, preserveObsidian = false) {
28398
28367
  return {
28399
28368
  vaultPath,
@@ -28415,11 +28384,7 @@ var MCP_DISPLAY_NAMES = {
28415
28384
  atlassian: { name: "Atlassian", description: "Jira issues, Confluence pages" },
28416
28385
  bigquery: { name: "BigQuery", description: "Data warehouse queries and analysis" }
28417
28386
  };
28418
- async function createMinimalCore(ctx, glossaryEntries = []) {
28419
- for (const dir of MINIMAL_DIRECTORIES) {
28420
- await fs.ensureDir(path6.join(ctx.vaultPath, dir));
28421
- }
28422
- ctx.directories.push(...MINIMAL_DIRECTORIES);
28387
+ async function createMinimalCore(ctx) {
28423
28388
  if (!ctx.preserveObsidian) {
28424
28389
  await fs.ensureDir(path6.join(ctx.vaultPath, ".obsidian"));
28425
28390
  const obsidianSrc = path6.join(ctx.commonDir, "obsidian");
@@ -28432,31 +28397,6 @@ async function createMinimalCore(ctx, glossaryEntries = []) {
28432
28397
  }
28433
28398
  }
28434
28399
  }
28435
- const templateDest = path6.join(ctx.vaultPath, "Knowledge/templates");
28436
- const commonTemplatesDir = path6.join(ctx.commonDir, "templates");
28437
- if (await fs.pathExists(commonTemplatesDir)) {
28438
- const files = await fs.readdir(commonTemplatesDir);
28439
- for (const file2 of files) {
28440
- await fs.copy(path6.join(commonTemplatesDir, file2), path6.join(templateDest, file2), { overwrite: false });
28441
- ctx.filesCreated++;
28442
- ctx.installedFiles.templates.push(`Knowledge/templates/${file2}`);
28443
- }
28444
- }
28445
- const glossaryTemplate = await fs.readFile(path6.join(ctx.commonDir, "Glossary.md.hbs"), "utf-8");
28446
- let glossaryRows = "";
28447
- if (glossaryEntries.length > 0) {
28448
- glossaryRows = glossaryEntries.map((e) => `| **${e.term}** | ${e.definition} | ${e.domain} |`).join("\n");
28449
- }
28450
- const glossaryContent = renderTemplate(glossaryTemplate, {
28451
- KB_NAME: ctx.kbName,
28452
- date: today(),
28453
- GLOSSARY_ENTRIES: glossaryRows
28454
- });
28455
- const glossaryPath = path6.join(ctx.vaultPath, "Knowledge/Glossary.md");
28456
- if (!await fs.pathExists(glossaryPath)) {
28457
- await fs.writeFile(glossaryPath, glossaryContent);
28458
- ctx.filesCreated++;
28459
- }
28460
28400
  const startHereTemplate = await fs.readFile(path6.join(ctx.commonDir, "Start Here.md.hbs"), "utf-8");
28461
28401
  const startHereContent = renderTemplate(startHereTemplate, {
28462
28402
  KB_NAME: ctx.kbName,
@@ -28469,23 +28409,51 @@ async function createMinimalCore(ctx, glossaryEntries = []) {
28469
28409
  ctx.filesCreated++;
28470
28410
  }
28471
28411
  }
28472
- async function createAgentsMd(ctx, ownerName, presetConfig, presetDir, projects, jiraHost, jiraProject) {
28412
+ async function createLlmWikiCore(ctx, wikiDomain = "") {
28413
+ const agentDirs = ["entities", "concepts", "comparisons", "queries"];
28414
+ for (const dir of agentDirs) {
28415
+ const dirPath = path6.join(ctx.vaultPath, dir);
28416
+ if (!await fs.pathExists(dirPath)) {
28417
+ await fs.ensureDir(dirPath);
28418
+ ctx.filesCreated++;
28419
+ ctx.directories.push(dir);
28420
+ }
28421
+ }
28422
+ const schemaTemplatePath = path6.join(ctx.commonDir, "SCHEMA.md.hbs");
28423
+ if (await fs.pathExists(schemaTemplatePath)) {
28424
+ const schemaTemplate = await fs.readFile(schemaTemplatePath, "utf-8");
28425
+ const schemaContent = renderTemplate(schemaTemplate, {
28426
+ KB_NAME: ctx.kbName,
28427
+ WIKI_DOMAIN: wikiDomain || ""
28428
+ });
28429
+ const schemaPath = path6.join(ctx.vaultPath, "SCHEMA.md");
28430
+ if (!await fs.pathExists(schemaPath)) {
28431
+ await fs.writeFile(schemaPath, schemaContent);
28432
+ ctx.filesCreated++;
28433
+ }
28434
+ }
28435
+ const logContent = `# Agent Activity Log
28436
+
28437
+ Entries are appended here during /cook operations.
28438
+
28439
+ `;
28440
+ const logPath = path6.join(ctx.vaultPath, "log.md");
28441
+ if (!await fs.pathExists(logPath)) {
28442
+ await fs.writeFile(logPath, logContent);
28443
+ ctx.filesCreated++;
28444
+ }
28445
+ }
28446
+ async function createAgentsMd(ctx, ownerName, presetConfig, presetDir) {
28473
28447
  const agentsTemplate = await fs.readFile(path6.join(ctx.commonDir, "AGENTS.md.hbs"), "utf-8");
28474
28448
  let roleSection = "";
28475
28449
  const agentSectionPath = path6.join(presetDir, "agent-section.hbs");
28476
28450
  if (await fs.pathExists(agentSectionPath)) {
28477
28451
  const agentSectionTemplate = await fs.readFile(agentSectionPath, "utf-8");
28478
- let projectsList;
28479
- if (projects.length > 0) {
28480
- projectsList = projects.map((p) => `- [[${p.name}]] \u2014 ${p.description}`).join("\n");
28481
- } else {
28482
- projectsList = "(No projects added yet \u2014 create notes in Projects/)";
28483
- }
28484
28452
  roleSection = renderTemplate(agentSectionTemplate, {
28485
- PROJECTS: projectsList,
28486
- JIRA_HOST: jiraHost,
28487
- JIRA_PROJECT: jiraProject,
28488
- HAS_JIRA: !!(jiraHost && jiraProject)
28453
+ PROJECTS: "(Use /cook to discover projects from your notes)",
28454
+ JIRA_HOST: "",
28455
+ JIRA_PROJECT: "",
28456
+ HAS_JIRA: false
28489
28457
  });
28490
28458
  }
28491
28459
  const agentsContent = renderTemplate(agentsTemplate, {
@@ -28504,127 +28472,24 @@ async function applyPresetOverlay(ctx, presetConfig, presetDir) {
28504
28472
  await fs.ensureDir(path6.join(ctx.vaultPath, dir));
28505
28473
  }
28506
28474
  ctx.directories.push(...presetConfig.directories);
28507
- const templateDest = path6.join(ctx.vaultPath, "Knowledge/templates");
28508
28475
  const allTemplateNames = [];
28509
- if (await fs.pathExists(templateDest)) {
28510
- const existing = await fs.readdir(templateDest);
28511
- for (const file2 of existing) {
28512
- if (file2.endsWith(".md")) {
28513
- allTemplateNames.push(file2.replace(/\.md$/, ""));
28514
- }
28515
- }
28516
- }
28517
28476
  const presetTemplatesDir = path6.join(presetDir, "templates");
28518
28477
  if (await fs.pathExists(presetTemplatesDir)) {
28478
+ const templateDest = path6.join(ctx.vaultPath, "templates");
28479
+ await fs.ensureDir(templateDest);
28519
28480
  const files = await fs.readdir(presetTemplatesDir);
28520
28481
  for (const file2 of files) {
28521
28482
  await fs.copy(path6.join(presetTemplatesDir, file2), path6.join(templateDest, file2), { overwrite: false });
28522
28483
  allTemplateNames.push(file2.replace(/\.md$/, ""));
28523
28484
  ctx.filesCreated++;
28524
- ctx.installedFiles.templates.push(`Knowledge/templates/${file2}`);
28485
+ ctx.installedFiles.templates.push(`templates/${file2}`);
28525
28486
  }
28526
28487
  }
28527
28488
  return allTemplateNames;
28528
28489
  }
28529
- async function createPeopleNotes(ctx, members) {
28530
- if (members.length === 0)
28531
- return;
28532
- await fs.ensureDir(path6.join(ctx.vaultPath, "People"));
28533
- if (!ctx.directories.includes("People")) {
28534
- ctx.directories.push("People");
28535
- }
28536
- for (const member of members) {
28537
- const content = `---
28538
- title: "${member.name}"
28539
- type: person
28540
- team: "${ctx.kbName}"
28541
- role: "${member.role}"
28542
- status: active
28543
- tags: [person]
28544
- ---
28545
-
28546
- # ${member.name}
28547
-
28548
- **Role**: ${member.role}
28549
- **Team**: ${ctx.kbName}
28550
- `;
28551
- const memberPath = path6.join(ctx.vaultPath, `People/${member.name}.md`);
28552
- if (!await fs.pathExists(memberPath)) {
28553
- await fs.writeFile(memberPath, content);
28554
- ctx.filesCreated++;
28555
- }
28556
- }
28557
- }
28558
- async function createProjectNotes(ctx, projects) {
28559
- if (projects.length === 0)
28560
- return;
28561
- await fs.ensureDir(path6.join(ctx.vaultPath, "Projects"));
28562
- if (!ctx.directories.includes("Projects")) {
28563
- ctx.directories.push("Projects");
28564
- }
28565
- for (const project of projects) {
28566
- const content = `---
28567
- title: "${project.name}"
28568
- type: feature
28569
- status: active
28570
- date: ${today()}
28571
- team: "${ctx.kbName}"
28572
- jira: ""
28573
- stakeholders: []
28574
- priority: ""
28575
- tags: [project]
28576
- ---
28577
-
28578
- # ${project.name}
28579
-
28580
- ${project.description}
28581
- `;
28582
- const projectPath = path6.join(ctx.vaultPath, `Projects/${project.name}.md`);
28583
- if (!await fs.pathExists(projectPath)) {
28584
- await fs.writeFile(projectPath, content);
28585
- ctx.filesCreated++;
28586
- }
28587
- }
28588
- }
28589
- async function createTeamIndex(ctx, members, projects) {
28590
- await fs.ensureDir(path6.join(ctx.vaultPath, "People"));
28591
- if (!ctx.directories.includes("People")) {
28592
- ctx.directories.push("People");
28593
- }
28594
- let teamIndexContent = `---
28595
- title: "${ctx.kbName} Team"
28596
- type: reference
28597
- team: "${ctx.kbName}"
28598
- tags: [team]
28599
- ---
28600
-
28601
- # ${ctx.kbName} Team
28602
-
28603
- ## Members
28604
-
28605
- `;
28606
- if (members.length > 0) {
28607
- teamIndexContent += "| Name | Role |\n|------|------|\n";
28608
- teamIndexContent += members.map((m) => `| [[${m.name}]] | ${m.role} |`).join("\n");
28609
- } else {
28610
- teamIndexContent += "(No members added yet)";
28611
- }
28612
- teamIndexContent += "\n\n## Active Projects\n\n";
28613
- if (projects.length > 0) {
28614
- teamIndexContent += projects.map((p) => `- [[${p.name}]] \u2014 ${p.description}`).join("\n");
28615
- } else {
28616
- teamIndexContent += "(No projects added yet)";
28617
- }
28618
- teamIndexContent += "\n";
28619
- const teamIndexPath = path6.join(ctx.vaultPath, `People/${ctx.kbName} Team.md`);
28620
- if (!await fs.pathExists(teamIndexPath)) {
28621
- await fs.writeFile(teamIndexPath, teamIndexContent);
28622
- ctx.filesCreated++;
28623
- }
28624
- }
28625
28490
  async function createVault(config2) {
28626
- const { kbName, vaultPath, members, projects, glossaryEntries, jiraHost, jiraProject, preset } = config2;
28627
- const presetName = preset ?? "pm-tpm";
28491
+ const { kbName, vaultPath, preset } = config2;
28492
+ const presetName = preset ?? "minimal";
28628
28493
  const { config: presetConfig, presetsDir } = loadPreset(presetName);
28629
28494
  const presetDir = path6.join(presetsDir, presetName);
28630
28495
  const initMode = detectInitMode(vaultPath);
@@ -28637,15 +28502,10 @@ async function createVault(config2) {
28637
28502
  ctx.mcpServices.push(info);
28638
28503
  }
28639
28504
  }
28640
- await createMinimalCore(ctx, glossaryEntries);
28641
- const allTemplateNames = await applyPresetOverlay(ctx, presetConfig, presetDir);
28642
- await createAgentsMd(ctx, config2.ownerName, presetConfig, presetDir, projects, jiraHost, jiraProject);
28643
- await createPeopleNotes(ctx, members);
28644
- await createProjectNotes(ctx, projects);
28645
- const hasPeopleDir = presetConfig.directories.includes("People") || members.length > 0;
28646
- if (hasPeopleDir) {
28647
- await createTeamIndex(ctx, members, projects);
28648
- }
28505
+ await createMinimalCore(ctx);
28506
+ await createLlmWikiCore(ctx, config2.wikiDomain);
28507
+ await applyPresetOverlay(ctx, presetConfig, presetDir);
28508
+ await createAgentsMd(ctx, config2.ownerName, presetConfig, presetDir);
28649
28509
  await configureOpenCodeProject(ctx.vaultPath, ctx.installedFiles);
28650
28510
  const mcpOptions = {};
28651
28511
  if (config2.mcpSkip && config2.mcpSkip.length > 0) {
@@ -28726,13 +28586,16 @@ async function configureOpenCodeProject(vaultPath, installedFiles) {
28726
28586
  }
28727
28587
  }
28728
28588
  function resolveAssetsDir() {
28589
+ const distAssets = path6.resolve(import.meta.dirname, "assets");
28729
28590
  const srcAssets = path6.resolve(import.meta.dirname, "..", "assets");
28730
- const distAssets = path6.resolve(import.meta.dirname, "..", "..", "src", "assets");
28731
- if (fs.existsSync(srcAssets))
28732
- return srcAssets;
28591
+ const devAssets = path6.resolve(import.meta.dirname, "..", "..", "src", "assets");
28733
28592
  if (fs.existsSync(distAssets))
28734
28593
  return distAssets;
28735
- return srcAssets;
28594
+ if (fs.existsSync(srcAssets))
28595
+ return srcAssets;
28596
+ if (fs.existsSync(devAssets))
28597
+ return devAssets;
28598
+ return distAssets;
28736
28599
  }
28737
28600
 
28738
28601
  // dist/vault/obsidian-check.js
@@ -28852,26 +28715,13 @@ function formatObsidianStatus(status) {
28852
28715
  import path7 from "node:path";
28853
28716
  import os3 from "node:os";
28854
28717
  var byoao_init_vault = tool({
28855
- description: "Create a personal knowledge base in Obsidian. Creates directory structure, templates, glossary, agent routing file (AGENTS.md), and optional people/project notes with wikilinks. Checks that Obsidian is installed first.",
28718
+ description: "Create an LLM Wiki knowledge base in Obsidian. Sets up agent directories (entities/, concepts/, comparisons/, queries/), SCHEMA.md, log.md, and AI routing (AGENTS.md). Your existing notes become raw material for /cook.",
28856
28719
  args: {
28857
28720
  kbName: tool.schema.string().describe(`Knowledge base name (e.g. "Jay's KB")`),
28858
28721
  ownerName: tool.schema.string().optional().describe("Owner's name"),
28859
28722
  vaultPath: tool.schema.string().optional().describe("Where to create the vault. Defaults to ~/Documents/{kbName}"),
28860
- members: tool.schema.array(tool.schema.object({
28861
- name: tool.schema.string().describe("Person's name"),
28862
- role: tool.schema.string().optional().describe("Person's role")
28863
- })).optional().describe("People to create notes for"),
28864
- projects: tool.schema.array(tool.schema.object({
28865
- name: tool.schema.string().describe("Project name"),
28866
- description: tool.schema.string().optional().describe("One-line description")
28867
- })).optional().describe("Active projects to create project notes for"),
28868
- glossaryEntries: tool.schema.array(tool.schema.object({
28869
- term: tool.schema.string().describe("Domain term"),
28870
- definition: tool.schema.string().describe("Brief definition")
28871
- })).optional().describe("Domain terms to add to the glossary"),
28872
- jiraHost: tool.schema.string().optional().describe("JIRA host (e.g. 'mycompany.atlassian.net')"),
28873
- jiraProject: tool.schema.string().optional().describe("JIRA project key (e.g. 'HDR')"),
28874
- preset: tool.schema.string().optional().describe("Role preset (default: 'minimal'). Use 'pm-tpm' for project management.")
28723
+ preset: tool.schema.string().optional().describe("Work profile (default: 'minimal'). Use 'pm-tpm' for PM/TPM with Atlassian + BigQuery."),
28724
+ wikiDomain: tool.schema.string().optional().describe("What domain this knowledge base covers (e.g. 'AI/ML research', 'product management')")
28875
28725
  },
28876
28726
  async execute(args) {
28877
28727
  const obsidianStatus = checkObsidian();
@@ -28885,12 +28735,8 @@ Please install Obsidian first, then try again.`;
28885
28735
  kbName: args.kbName,
28886
28736
  ownerName: args.ownerName || "",
28887
28737
  vaultPath: resolvedPath,
28888
- members: args.members || [],
28889
- projects: args.projects || [],
28890
- glossaryEntries: args.glossaryEntries || [],
28891
- jiraHost: args.jiraHost || "",
28892
- jiraProject: args.jiraProject || "",
28893
- preset: args.preset || "minimal"
28738
+ preset: args.preset || "minimal",
28739
+ wikiDomain: args.wikiDomain || ""
28894
28740
  });
28895
28741
  const result = await createVault(config2);
28896
28742
  let output = `\u2713 Knowledge base created at: ${result.vaultPath}
@@ -28990,235 +28836,18 @@ Open in Obsidian: "Open folder as vault" \u2192 select "${result.vaultPath}"`;
28990
28836
  if (result.initMode === "existing" || result.initMode === "obsidian-vault") {
28991
28837
  output += `
28992
28838
 
28993
- \u2192 Next step: run /weave now \u2014 it will scan your existing notes, add frontmatter metadata (including dates), create wikilinks between related content, and build your Glossary from frequently mentioned concepts.`;
28839
+ \u2192 Next step: run /cook now \u2014 it will scan your existing notes, identify entities and concepts, and compile them into structured knowledge pages.`;
28994
28840
  } else {
28995
28841
  output += `
28996
28842
 
28997
- \u2192 Next step: add a few notes, then run /weave to connect them into a knowledge graph. See "Start Here" in the vault for details.`;
28843
+ \u2192 Next step: add a few notes, then run /cook to compile them into knowledge pages. See "Start Here" in the vault for details.`;
28998
28844
  }
28999
28845
  return output;
29000
28846
  }
29001
28847
  });
29002
28848
 
29003
- // dist/vault/member.js
29004
- import path8 from "node:path";
29005
- async function addMember(input) {
29006
- const { vaultPath, name, role, team } = input;
29007
- let wikilinksAdded = 0;
29008
- const personPath = path8.join(vaultPath, `People/${name}.md`);
29009
- if (await fs.pathExists(personPath)) {
29010
- throw new Error(`Person note already exists: ${personPath}`);
29011
- }
29012
- const content = `---
29013
- title: "${name}"
29014
- type: person
29015
- team: "${team}"
29016
- role: "${role}"
29017
- status: active
29018
- tags: [person]
29019
- ---
29020
-
29021
- # ${name}
29022
-
29023
- **Role**: ${role}
29024
- **Team**: ${team}
29025
- `;
29026
- await fs.writeFile(personPath, content);
29027
- const teamFiles = await fs.readdir(path8.join(vaultPath, "People"));
29028
- const teamIndexFile = teamFiles.find((f) => f.endsWith("Team.md"));
29029
- if (teamIndexFile) {
29030
- const teamIndexPath = path8.join(vaultPath, "People", teamIndexFile);
29031
- let teamContent = await fs.readFile(teamIndexPath, "utf-8");
29032
- const tableRow = `| [[${name}]] | ${role} |`;
29033
- if (teamContent.includes("|------|------|")) {
29034
- teamContent = teamContent.replace(/(^\|------|------\|$)/m, `$1
29035
- ${tableRow}`);
29036
- wikilinksAdded++;
29037
- }
29038
- await fs.writeFile(teamIndexPath, teamContent);
29039
- }
29040
- for (const agentFile of ["AGENTS.md", "AGENT.md"]) {
29041
- const agentPath = path8.join(vaultPath, agentFile);
29042
- if (await fs.pathExists(agentPath)) {
29043
- let agentContent = await fs.readFile(agentPath, "utf-8");
29044
- if (agentContent.includes("(No members added yet")) {
29045
- const table = `| Name | Role |
29046
- |------|------|
29047
- | [[${name}]] | ${role} |`;
29048
- agentContent = agentContent.replace(/\(No members added yet[^)]*\)/, table);
29049
- wikilinksAdded++;
29050
- } else if (agentContent.includes("|------|------|")) {
29051
- const teamSectionMatch = agentContent.match(/## Team[^\n]*\n[\s\S]*?(\|------|------\|[^\n]*(?:\n\|[^\n]*)*)/);
29052
- if (teamSectionMatch) {
29053
- const existingTable = teamSectionMatch[1];
29054
- const newTable = existingTable + `
29055
- | [[${name}]] | ${role} |`;
29056
- agentContent = agentContent.replace(existingTable, newTable);
29057
- wikilinksAdded++;
29058
- }
29059
- }
29060
- await fs.writeFile(agentPath, agentContent);
29061
- }
29062
- }
29063
- return { filePath: personPath, wikilinksAdded };
29064
- }
29065
-
29066
- // dist/tools/add-person.js
29067
- var byoao_add_person = tool({
29068
- description: "Add a person note to an existing vault. Creates a person note in People/ and updates the team index and AGENTS.md wikilinks.",
29069
- args: {
29070
- vaultPath: tool.schema.string().describe("Path to the Obsidian vault"),
29071
- name: tool.schema.string().describe("Person's full name"),
29072
- role: tool.schema.string().optional().describe("Person's role/title"),
29073
- team: tool.schema.string().optional().describe("Team or KB name")
29074
- },
29075
- async execute(args) {
29076
- const result = await addMember({
29077
- vaultPath: args.vaultPath,
29078
- name: args.name,
29079
- role: args.role || "",
29080
- team: args.team || ""
29081
- });
29082
- return `Added person: ${args.name}
29083
- File: ${result.filePath}
29084
- Wikilinks updated: ${result.wikilinksAdded}`;
29085
- }
29086
- });
29087
-
29088
- // dist/vault/project.js
29089
- import path9 from "node:path";
29090
- async function addProject(input) {
29091
- const { vaultPath, name, description, team } = input;
29092
- let wikilinksAdded = 0;
29093
- const projectPath = path9.join(vaultPath, `Projects/${name}.md`);
29094
- if (await fs.pathExists(projectPath)) {
29095
- throw new Error(`Project note already exists: ${projectPath}`);
29096
- }
29097
- const content = `---
29098
- title: "${name}"
29099
- type: feature
29100
- status: active
29101
- date: ${today()}
29102
- team: "${team}"
29103
- jira: ""
29104
- stakeholders: []
29105
- priority: ""
29106
- tags: [project]
29107
- ---
29108
-
29109
- # ${name}
29110
-
29111
- ${description}
29112
- `;
29113
- await fs.writeFile(projectPath, content);
29114
- const peoplePath = path9.join(vaultPath, "People");
29115
- if (await fs.pathExists(peoplePath)) {
29116
- const teamFiles = await fs.readdir(peoplePath);
29117
- const teamIndexFile = teamFiles.find((f) => f.endsWith("Team.md"));
29118
- if (teamIndexFile) {
29119
- const teamIndexPath = path9.join(peoplePath, teamIndexFile);
29120
- let teamContent = await fs.readFile(teamIndexPath, "utf-8");
29121
- const projectLine = `- [[${name}]] \u2014 ${description}`;
29122
- if (teamContent.includes("(No projects added yet)")) {
29123
- teamContent = teamContent.replace("(No projects added yet)", projectLine);
29124
- } else if (teamContent.includes("## Active Projects")) {
29125
- teamContent = teamContent.replace(/(## Active Projects\n\n)([\s\S]*?)(\n\n|$)/, `$1$2
29126
- ${projectLine}$3`);
29127
- }
29128
- wikilinksAdded++;
29129
- await fs.writeFile(teamIndexPath, teamContent);
29130
- }
29131
- }
29132
- for (const agentFile of ["AGENTS.md", "AGENT.md"]) {
29133
- const agentPath = path9.join(vaultPath, agentFile);
29134
- if (await fs.pathExists(agentPath)) {
29135
- let agentContent = await fs.readFile(agentPath, "utf-8");
29136
- const projectLine = `- [[${name}]] \u2014 ${description}`;
29137
- if (agentContent.includes("(No projects added yet")) {
29138
- agentContent = agentContent.replace(/\(No projects added yet[^)]*\)/, projectLine);
29139
- wikilinksAdded++;
29140
- } else if (agentContent.includes("## Active Projects")) {
29141
- agentContent = agentContent.replace(/(## Active Projects[^\n]*\n\n)([\s\S]*?)(\n\n|$)/, `$1$2
29142
- ${projectLine}$3`);
29143
- wikilinksAdded++;
29144
- }
29145
- await fs.writeFile(agentPath, agentContent);
29146
- }
29147
- }
29148
- return { filePath: projectPath, wikilinksAdded };
29149
- }
29150
-
29151
- // dist/tools/add-project.js
29152
- var byoao_add_project = tool({
29153
- description: "Add a new project note to an existing vault. Creates a project note in Projects/ and updates the team index and AGENTS.md wikilinks.",
29154
- args: {
29155
- vaultPath: tool.schema.string().describe("Path to the Obsidian vault"),
29156
- name: tool.schema.string().describe("Project name"),
29157
- description: tool.schema.string().optional().describe("One-line project description"),
29158
- team: tool.schema.string().optional().describe("Team name")
29159
- },
29160
- async execute(args) {
29161
- const result = await addProject({
29162
- vaultPath: args.vaultPath,
29163
- name: args.name,
29164
- description: args.description || "",
29165
- team: args.team || ""
29166
- });
29167
- return `\u2713 Added project: ${args.name}
29168
- File: ${result.filePath}
29169
- Wikilinks updated: ${result.wikilinksAdded}`;
29170
- }
29171
- });
29172
-
29173
- // dist/vault/glossary.js
29174
- import path10 from "node:path";
29175
- async function addGlossaryTerm(input) {
29176
- const { vaultPath, term, definition, domain: domain2 } = input;
29177
- const glossaryPath = path10.join(vaultPath, "Knowledge/Glossary.md");
29178
- if (!await fs.pathExists(glossaryPath)) {
29179
- throw new Error(`Glossary not found at: ${glossaryPath}`);
29180
- }
29181
- let content = await fs.readFile(glossaryPath, "utf-8");
29182
- const newRow = `| **${term}** | ${definition} | ${domain2 ?? ""} |`;
29183
- const tableMatch = content.match(/(\| Term \| Definition \| Domain \|\n\|------\|-----------|--------\|\n)([\s\S]*?)(\n*$)/);
29184
- if (tableMatch) {
29185
- const [fullMatch, tableHeader, existingRows, trailing] = tableMatch;
29186
- const updatedRows = existingRows.trim() ? `${existingRows.trim()}
29187
- ${newRow}` : newRow;
29188
- content = content.replace(fullMatch, `${tableHeader}${updatedRows}
29189
- `);
29190
- } else {
29191
- content = content.trimEnd() + `
29192
- ${newRow}
29193
- `;
29194
- }
29195
- await fs.writeFile(glossaryPath, content);
29196
- return { glossaryPath, termAdded: term };
29197
- }
29198
-
29199
- // dist/tools/add-glossary-term.js
29200
- var byoao_add_glossary_term = tool({
29201
- description: "Add a new term to the vault's Glossary.md. Appends a row to the Core Terms table.",
29202
- args: {
29203
- vaultPath: tool.schema.string().describe("Path to the Obsidian vault"),
29204
- term: tool.schema.string().describe("The domain term to add"),
29205
- definition: tool.schema.string().describe("Brief definition (1-2 sentences)"),
29206
- domain: tool.schema.string().optional().describe("Knowledge domain (e.g. analytics, infrastructure)")
29207
- },
29208
- async execute(args) {
29209
- const result = await addGlossaryTerm({
29210
- vaultPath: args.vaultPath,
29211
- term: args.term,
29212
- definition: args.definition,
29213
- domain: args.domain ?? ""
29214
- });
29215
- return `\u2713 Added glossary term: ${result.termAdded}
29216
- File: ${result.glossaryPath}`;
29217
- }
29218
- });
29219
-
29220
28849
  // dist/vault/status.js
29221
- import path11 from "node:path";
28850
+ import path8 from "node:path";
29222
28851
  async function getAllMarkdownFiles(dirPath) {
29223
28852
  const results = [];
29224
28853
  async function walk(dir) {
@@ -29226,7 +28855,7 @@ async function getAllMarkdownFiles(dirPath) {
29226
28855
  return;
29227
28856
  const entries = await fs.readdir(dir, { withFileTypes: true });
29228
28857
  for (const entry of entries) {
29229
- const fullPath = path11.join(dir, entry.name);
28858
+ const fullPath = path8.join(dir, entry.name);
29230
28859
  if (entry.isDirectory()) {
29231
28860
  if (!entry.name.startsWith(".")) {
29232
28861
  await walk(fullPath);
@@ -29258,11 +28887,14 @@ async function getVaultStatus(vaultPath) {
29258
28887
  directories: {},
29259
28888
  hasObsidianConfig: false,
29260
28889
  hasAgentMd: false,
29261
- hasGlossary: false
28890
+ agentPages: { entities: 0, concepts: 0, comparisons: 0, queries: 0 },
28891
+ hasSchema: false,
28892
+ hasLog: false,
28893
+ hasIndexBase: false
29262
28894
  };
29263
28895
  }
29264
28896
  const allFiles = await getAllMarkdownFiles(vaultPath);
29265
- const noteNames = new Set(allFiles.map((f) => path11.basename(f, ".md")));
28897
+ const noteNames = new Set(allFiles.map((f) => path8.basename(f, ".md")));
29266
28898
  let wikilinkCount = 0;
29267
28899
  const brokenLinksSet = /* @__PURE__ */ new Set();
29268
28900
  for (const file2 of allFiles) {
@@ -29287,12 +28919,24 @@ async function getVaultStatus(vaultPath) {
29287
28919
  "Daily"
29288
28920
  ];
29289
28921
  for (const dir of topDirs) {
29290
- const dirPath = path11.join(vaultPath, dir);
28922
+ const dirPath = path8.join(vaultPath, dir);
29291
28923
  if (await fs.pathExists(dirPath)) {
29292
28924
  const files = await getAllMarkdownFiles(dirPath);
29293
28925
  directories[dir] = files.length;
29294
28926
  }
29295
28927
  }
28928
+ const agentDirNames = ["entities", "concepts", "comparisons", "queries"];
28929
+ const agentPages = {
28930
+ entities: 0,
28931
+ concepts: 0,
28932
+ comparisons: 0,
28933
+ queries: 0
28934
+ };
28935
+ for (const name of agentDirNames) {
28936
+ const dirPath = path8.join(vaultPath, name);
28937
+ const mdFiles = await getAllMarkdownFiles(dirPath);
28938
+ agentPages[name] = mdFiles.length;
28939
+ }
29296
28940
  return {
29297
28941
  exists: true,
29298
28942
  vaultPath,
@@ -29300,9 +28944,12 @@ async function getVaultStatus(vaultPath) {
29300
28944
  wikilinkCount,
29301
28945
  brokenLinks: Array.from(brokenLinksSet),
29302
28946
  directories,
29303
- hasObsidianConfig: await fs.pathExists(path11.join(vaultPath, ".obsidian")),
29304
- hasAgentMd: await fs.pathExists(path11.join(vaultPath, "AGENTS.md")) || await fs.pathExists(path11.join(vaultPath, "AGENT.md")),
29305
- hasGlossary: await fs.pathExists(path11.join(vaultPath, "Knowledge/Glossary.md"))
28947
+ hasObsidianConfig: await fs.pathExists(path8.join(vaultPath, ".obsidian")),
28948
+ hasAgentMd: await fs.pathExists(path8.join(vaultPath, "AGENTS.md")) || await fs.pathExists(path8.join(vaultPath, "AGENT.md")),
28949
+ agentPages,
28950
+ hasSchema: await fs.pathExists(path8.join(vaultPath, "SCHEMA.md")),
28951
+ hasLog: await fs.pathExists(path8.join(vaultPath, "log.md")),
28952
+ hasIndexBase: await fs.pathExists(path8.join(vaultPath, "INDEX.base"))
29306
28953
  };
29307
28954
  }
29308
28955
  function formatVaultStatus(status) {
@@ -29322,7 +28969,10 @@ function formatVaultStatus(status) {
29322
28969
  lines.push("");
29323
28970
  lines.push(`Config: ${status.hasObsidianConfig ? "\u2713" : "\u2717"} .obsidian/`);
29324
28971
  lines.push(`Agent: ${status.hasAgentMd ? "\u2713" : "\u2717"} AGENTS.md`);
29325
- lines.push(`Glossary: ${status.hasGlossary ? "\u2713" : "\u2717"} Glossary.md`);
28972
+ lines.push("");
28973
+ lines.push("LLM Wiki v2 (agent pages):");
28974
+ lines.push(` entities: ${status.agentPages.entities} \xB7 concepts: ${status.agentPages.concepts} \xB7 comparisons: ${status.agentPages.comparisons} \xB7 queries: ${status.agentPages.queries}`);
28975
+ lines.push(` SCHEMA.md: ${status.hasSchema ? "\u2713" : "\u2717"} \xB7 log.md: ${status.hasLog ? "\u2713" : "\u2717"} \xB7 INDEX.base: ${status.hasIndexBase ? "\u2713" : "\u2717"}`);
29326
28976
  if (status.brokenLinks.length > 0) {
29327
28977
  lines.push("");
29328
28978
  lines.push(`\u26A0\uFE0F Broken links (${status.brokenLinks.length}):`);
@@ -29340,7 +28990,7 @@ function formatVaultStatus(status) {
29340
28990
 
29341
28991
  // dist/tools/vault-status.js
29342
28992
  var byoao_vault_status = tool({
29343
- description: "Check the health of an Obsidian vault \u2014 note count, wikilink count, broken links, directory breakdown, and Obsidian installation status.",
28993
+ description: "Check the health of an Obsidian vault \u2014 note count, wikilink count, broken links, directory breakdown, Obsidian installation status, and LLM Wiki v2 signals: per-directory markdown counts under entities/, concepts/, comparisons/, queries/, plus presence of SCHEMA.md, log.md, and INDEX.base at the vault root.",
29344
28994
  args: {
29345
28995
  vaultPath: tool.schema.string().describe("Path to the Obsidian vault")
29346
28996
  },
@@ -29355,12 +29005,18 @@ var byoao_vault_status = tool({
29355
29005
  });
29356
29006
 
29357
29007
  // dist/vault/doctor.js
29358
- import path12 from "node:path";
29008
+ import path9 from "node:path";
29009
+ import { stat } from "node:fs/promises";
29010
+ var LLM_WIKI_V2_AGENT_DIRS = ["entities", "concepts", "comparisons", "queries"];
29011
+ function isAgentWikiPage(relativePath) {
29012
+ const top = relativePath.split(path9.sep)[0];
29013
+ return LLM_WIKI_V2_AGENT_DIRS.includes(top);
29014
+ }
29359
29015
  async function collectMarkdownFiles(dir) {
29360
29016
  const results = [];
29361
29017
  const entries = await fs.readdir(dir, { withFileTypes: true });
29362
29018
  for (const entry of entries) {
29363
- const fullPath = path12.join(dir, entry.name);
29019
+ const fullPath = path9.join(dir, entry.name);
29364
29020
  if (entry.isDirectory()) {
29365
29021
  if (entry.name === ".obsidian" || entry.name === ".git")
29366
29022
  continue;
@@ -29381,10 +29037,10 @@ function extractWikilinks2(content) {
29381
29037
  async function getVaultDiagnosis(vaultPath) {
29382
29038
  const issues = [];
29383
29039
  const allFiles = await collectMarkdownFiles(vaultPath);
29384
- const noteNames = new Set(allFiles.map((f) => path12.basename(f, ".md")));
29040
+ const noteNames = new Set(allFiles.map((f) => path9.basename(f, ".md")));
29385
29041
  let healthyNotes = 0;
29386
29042
  for (const filePath of allFiles) {
29387
- const relativePath = path12.relative(vaultPath, filePath);
29043
+ const relativePath = path9.relative(vaultPath, filePath);
29388
29044
  if (relativePath.startsWith("Knowledge/templates/"))
29389
29045
  continue;
29390
29046
  const content = await fs.readFile(filePath, "utf-8");
@@ -29418,15 +29074,26 @@ async function getVaultDiagnosis(vaultPath) {
29418
29074
  hasIssue = true;
29419
29075
  }
29420
29076
  }
29077
+ const contra = data?.contradictions;
29078
+ const contraList = Array.isArray(contra) && contra.some((x) => x != null && String(x).trim() !== "");
29079
+ const contraStr = typeof contra === "string" && contra.trim() !== "";
29080
+ if (contraList || contraStr) {
29081
+ issues.push({
29082
+ severity: "warning",
29083
+ category: "contradiction",
29084
+ file: relativePath,
29085
+ message: "Note lists `contradictions` in frontmatter \u2014 review conflicting claims against linked agent pages"
29086
+ });
29087
+ }
29421
29088
  if (!hasIssue)
29422
29089
  healthyNotes++;
29423
29090
  }
29424
29091
  let agentContent = null;
29425
- let agentResolvedPath = path12.join(vaultPath, "AGENTS.md");
29092
+ let agentResolvedPath = path9.join(vaultPath, "AGENTS.md");
29426
29093
  if (await fs.pathExists(agentResolvedPath)) {
29427
29094
  agentContent = await fs.readFile(agentResolvedPath, "utf-8");
29428
29095
  } else {
29429
- agentResolvedPath = path12.join(vaultPath, "AGENT.md");
29096
+ agentResolvedPath = path9.join(vaultPath, "AGENT.md");
29430
29097
  if (await fs.pathExists(agentResolvedPath)) {
29431
29098
  agentContent = await fs.readFile(agentResolvedPath, "utf-8");
29432
29099
  }
@@ -29443,24 +29110,54 @@ async function getVaultDiagnosis(vaultPath) {
29443
29110
  }
29444
29111
  }
29445
29112
  }
29113
+ for (const dirName of LLM_WIKI_V2_AGENT_DIRS) {
29114
+ const dirPath = path9.join(vaultPath, dirName);
29115
+ const exists = await fs.pathExists(dirPath);
29116
+ const isDir = exists && (await stat(dirPath)).isDirectory();
29117
+ if (!isDir) {
29118
+ issues.push({
29119
+ severity: "warning",
29120
+ category: "agent-drift",
29121
+ message: `LLM Wiki v2: expected agent directory \`${dirName}/\` at vault root`
29122
+ });
29123
+ }
29124
+ }
29125
+ const schemaPath = path9.join(vaultPath, "SCHEMA.md");
29126
+ if (!await fs.pathExists(schemaPath)) {
29127
+ issues.push({
29128
+ severity: "warning",
29129
+ category: "agent-drift",
29130
+ message: "LLM Wiki v2: missing SCHEMA.md at vault root"
29131
+ });
29132
+ }
29133
+ const logMdPath = path9.join(vaultPath, "log.md");
29134
+ if (!await fs.pathExists(logMdPath)) {
29135
+ issues.push({
29136
+ severity: "warning",
29137
+ category: "agent-drift",
29138
+ message: "LLM Wiki v2: missing log.md at vault root"
29139
+ });
29140
+ }
29446
29141
  const allLinksMap = /* @__PURE__ */ new Map();
29447
29142
  const incomingLinks = /* @__PURE__ */ new Set();
29448
29143
  for (const filePath of allFiles) {
29449
29144
  const content = await fs.readFile(filePath, "utf-8");
29450
29145
  const links = extractWikilinks2(content);
29451
- const name = path12.basename(filePath, ".md");
29146
+ const name = path9.basename(filePath, ".md");
29452
29147
  allLinksMap.set(name, new Set(links));
29453
29148
  for (const link of links) {
29454
29149
  incomingLinks.add(link);
29455
29150
  }
29456
29151
  }
29457
29152
  for (const filePath of allFiles) {
29458
- const relativePath = path12.relative(vaultPath, filePath);
29153
+ const relativePath = path9.relative(vaultPath, filePath);
29459
29154
  if (relativePath.startsWith("Knowledge/templates/"))
29460
29155
  continue;
29461
29156
  if (relativePath === "AGENT.md" || relativePath === "AGENTS.md")
29462
29157
  continue;
29463
- const name = path12.basename(filePath, ".md");
29158
+ if (isAgentWikiPage(relativePath))
29159
+ continue;
29160
+ const name = path9.basename(filePath, ".md");
29464
29161
  const outgoing = allLinksMap.get(name) || /* @__PURE__ */ new Set();
29465
29162
  const hasIncoming = incomingLinks.has(name);
29466
29163
  const hasOutgoing = outgoing.size > 0;
@@ -29474,7 +29171,7 @@ async function getVaultDiagnosis(vaultPath) {
29474
29171
  }
29475
29172
  }
29476
29173
  for (const filePath of allFiles) {
29477
- const relativePath = path12.relative(vaultPath, filePath);
29174
+ const relativePath = path9.relative(vaultPath, filePath);
29478
29175
  const content = await fs.readFile(filePath, "utf-8");
29479
29176
  const links = extractWikilinks2(content);
29480
29177
  for (const link of links) {
@@ -29500,7 +29197,7 @@ async function getVaultDiagnosis(vaultPath) {
29500
29197
 
29501
29198
  // dist/tools/vault-doctor.js
29502
29199
  var byoao_vault_doctor = tool({
29503
- description: "Scan an Obsidian vault and produce a diagnostic report. Checks: missing frontmatter, missing type/tags, AGENTS.md drift, orphan notes, broken wikilinks.",
29200
+ description: "Scan an Obsidian vault and produce a diagnostic report. Checks: missing frontmatter, missing type/tags, AGENTS.md drift, orphan notes (user notes only; agent pages under entities/, concepts/, comparisons/, queries/ are excluded), broken wikilinks, LLM Wiki v2 layout (agent directories, SCHEMA.md, log.md at vault root), and notes with contradictions frontmatter.",
29504
29201
  args: {
29505
29202
  vaultPath: tool.schema.string().describe("Absolute path to the Obsidian vault")
29506
29203
  },
@@ -29566,323 +29263,16 @@ var byoao_switch_provider = tool({
29566
29263
  }
29567
29264
  });
29568
29265
 
29569
- // dist/vault/search-vault.js
29570
- import path13 from "node:path";
29571
-
29572
- // dist/vault/obsidian-cli.js
29573
- import { execFileSync, execSync as execSync3 } from "node:child_process";
29574
- import { platform as platform2 } from "node:os";
29575
- var _cliAvailableCache = null;
29576
- function isObsidianCliAvailable() {
29577
- if (_cliAvailableCache !== null)
29578
- return _cliAvailableCache;
29579
- const os5 = platform2();
29580
- try {
29581
- if (os5 === "darwin") {
29582
- execSync3("pgrep -x Obsidian", { stdio: "pipe", timeout: 3e3 });
29583
- _cliAvailableCache = true;
29584
- } else if (os5 === "linux") {
29585
- execSync3("pgrep -x obsidian", { stdio: "pipe", timeout: 3e3 });
29586
- _cliAvailableCache = true;
29587
- } else if (os5 === "win32") {
29588
- const result = execSync3('tasklist /FI "IMAGENAME eq Obsidian.exe" /NH', { stdio: "pipe", timeout: 3e3, encoding: "utf-8" });
29589
- _cliAvailableCache = result.includes("Obsidian.exe");
29590
- } else {
29591
- _cliAvailableCache = false;
29592
- }
29593
- } catch {
29594
- _cliAvailableCache = false;
29595
- }
29596
- return _cliAvailableCache;
29597
- }
29598
- function execObsidianCmd(args) {
29599
- try {
29600
- const output = execFileSync("obsidian", args, {
29601
- stdio: "pipe",
29602
- encoding: "utf-8",
29603
- timeout: 1e4
29604
- });
29605
- return { success: true, output: output.trim() };
29606
- } catch (err) {
29607
- const msg = err instanceof Error ? err.message : String(err);
29608
- return { success: false, output: "", error: msg };
29609
- }
29610
- }
29611
-
29612
- // dist/vault/retrieval-types.js
29613
- var DEFAULT_RESULT_LIMIT = 20;
29614
- var MAX_SNIPPET_LENGTH = 240;
29615
-
29616
- // dist/vault/search-vault.js
29617
- async function searchVault(input) {
29618
- const { vaultPath, query, limit = DEFAULT_RESULT_LIMIT } = input;
29619
- const mode = "search:context";
29620
- const base = {
29621
- mode,
29622
- vault: vaultPath,
29623
- fallback: "none"
29624
- };
29625
- if (!isObsidianCliAvailable()) {
29626
- return {
29627
- ...base,
29628
- status: "runtime_unavailable",
29629
- summary: "Obsidian CLI not available",
29630
- results: [],
29631
- truncated: false,
29632
- diagnostics: ["Obsidian CLI not available"]
29633
- };
29634
- }
29635
- const cliResult = execObsidianCmd([
29636
- "search:context",
29637
- "--vault",
29638
- vaultPath,
29639
- query
29640
- ]);
29641
- if (!cliResult.success) {
29642
- return {
29643
- ...base,
29644
- status: "runtime_unavailable",
29645
- summary: "Obsidian CLI command failed",
29646
- results: [],
29647
- truncated: false,
29648
- diagnostics: [cliResult.error ?? "Unknown CLI error"]
29649
- };
29650
- }
29651
- const lines = cliResult.output.split("\n").filter((l) => l.trim().length > 0);
29652
- if (lines.length === 0) {
29653
- return {
29654
- ...base,
29655
- status: "no_results",
29656
- summary: `No matches for "${query}"`,
29657
- results: [],
29658
- truncated: false,
29659
- diagnostics: []
29660
- };
29661
- }
29662
- const allItems = [];
29663
- for (const line of lines) {
29664
- const colonIdx = line.indexOf(":");
29665
- if (colonIdx === -1)
29666
- continue;
29667
- const filePath = line.substring(0, colonIdx);
29668
- const snippet = line.substring(colonIdx + 1).trim();
29669
- const title = path13.basename(filePath, ".md");
29670
- allItems.push({
29671
- title,
29672
- path: filePath,
29673
- file: title,
29674
- snippet: snippet.length > MAX_SNIPPET_LENGTH ? snippet.substring(0, MAX_SNIPPET_LENGTH) : snippet
29675
- });
29676
- }
29677
- const truncated = allItems.length > limit;
29678
- const results = allItems.slice(0, limit);
29679
- return {
29680
- ...base,
29681
- status: "ok",
29682
- summary: `${allItems.length} matching notes for "${query}"`,
29683
- results,
29684
- truncated,
29685
- totalMatches: allItems.length,
29686
- diagnostics: []
29687
- };
29688
- }
29689
-
29690
- // dist/tools/search-vault.js
29691
- var byoao_search_vault = tool({
29692
- description: "Search an Obsidian vault for notes matching a text query. Uses Obsidian CLI search:context for vault-aware results. Preferred over grep/rg for Obsidian vault knowledge queries about notes, tags, and content.",
29693
- args: {
29694
- vaultPath: tool.schema.string().describe("Absolute path to the Obsidian vault"),
29695
- query: tool.schema.string().describe("Text query to search for in vault notes"),
29696
- limit: tool.schema.number().optional().describe("Maximum number of results to return (default: 20)")
29697
- },
29698
- async execute(args) {
29699
- const result = await searchVault({
29700
- vaultPath: args.vaultPath,
29701
- query: args.query,
29702
- limit: args.limit
29703
- });
29704
- return JSON.stringify(result, null, 2);
29705
- }
29706
- });
29707
-
29708
- // dist/vault/note-read.js
29709
- async function readNote(input) {
29710
- const { vaultPath, file: file2 } = input;
29711
- const mode = "read";
29712
- const base = {
29713
- mode,
29714
- vault: vaultPath,
29715
- fallback: "none"
29716
- };
29717
- if (!isObsidianCliAvailable()) {
29718
- return {
29719
- ...base,
29720
- status: "runtime_unavailable",
29721
- summary: "Obsidian CLI not available",
29722
- results: [],
29723
- truncated: false,
29724
- diagnostics: ["Obsidian CLI not available"]
29725
- };
29726
- }
29727
- const cliResult = execObsidianCmd(["read", "--vault", vaultPath, file2]);
29728
- if (!cliResult.success) {
29729
- return {
29730
- ...base,
29731
- status: "runtime_unavailable",
29732
- summary: `Failed to read note "${file2}"`,
29733
- results: [],
29734
- truncated: false,
29735
- diagnostics: [cliResult.error ?? "Unknown CLI error"]
29736
- };
29737
- }
29738
- const content = cliResult.output.trim();
29739
- if (content.length === 0) {
29740
- return {
29741
- ...base,
29742
- status: "no_results",
29743
- summary: `Note "${file2}" is empty or not found`,
29744
- results: [],
29745
- truncated: false,
29746
- diagnostics: []
29747
- };
29748
- }
29749
- const snippet = content.length > MAX_SNIPPET_LENGTH ? content.substring(0, MAX_SNIPPET_LENGTH) : content;
29750
- return {
29751
- ...base,
29752
- status: "ok",
29753
- summary: `Read note "${file2}" (${content.length} chars)`,
29754
- results: [
29755
- {
29756
- title: file2,
29757
- path: "",
29758
- file: file2,
29759
- snippet
29760
- }
29761
- ],
29762
- truncated: false,
29763
- diagnostics: []
29764
- };
29765
- }
29766
-
29767
- // dist/tools/note-read.js
29768
- var byoao_note_read = tool({
29769
- description: "Read a specific note from an Obsidian vault by name. Uses Obsidian CLI to resolve and read the note. Preferred over cat/Read for Obsidian vault notes.",
29770
- args: {
29771
- vaultPath: tool.schema.string().describe("Absolute path to the Obsidian vault"),
29772
- file: tool.schema.string().describe("Note name to read (without .md extension, e.g. 'Refund Automation')")
29773
- },
29774
- async execute(args) {
29775
- const result = await readNote({
29776
- vaultPath: args.vaultPath,
29777
- file: args.file
29778
- });
29779
- return JSON.stringify(result, null, 2);
29780
- }
29781
- });
29782
-
29783
- // dist/vault/graph-health.js
29784
- import path14 from "node:path";
29785
- var ALL_CHECKS = ["orphans", "unresolved", "deadends"];
29786
- function parseCheckOutput(check2, output) {
29787
- const lines = output.split("\n").filter((l) => l.trim().length > 0);
29788
- return lines.map((line) => {
29789
- const trimmed = line.trim();
29790
- const isPath = trimmed.includes("/") || trimmed.endsWith(".md");
29791
- const title = isPath ? path14.basename(trimmed, ".md") : trimmed;
29792
- return {
29793
- title,
29794
- path: isPath ? trimmed : "",
29795
- file: title,
29796
- metadata: { check: check2 }
29797
- };
29798
- });
29799
- }
29800
- async function getGraphHealth(input) {
29801
- const { vaultPath, check: check2 = "all", limit = DEFAULT_RESULT_LIMIT } = input;
29802
- const mode = "graph-health";
29803
- const base = {
29804
- mode,
29805
- vault: vaultPath,
29806
- fallback: "none"
29807
- };
29808
- if (!isObsidianCliAvailable()) {
29809
- return {
29810
- ...base,
29811
- status: "runtime_unavailable",
29812
- summary: "Obsidian CLI not available",
29813
- results: [],
29814
- truncated: false,
29815
- diagnostics: ["Obsidian CLI not available"]
29816
- };
29817
- }
29818
- const checks = check2 === "all" ? ALL_CHECKS : [check2];
29819
- const allItems = [];
29820
- const diagnostics = [];
29821
- for (const checkType of checks) {
29822
- const cliResult = execObsidianCmd([checkType, "--vault", vaultPath]);
29823
- if (!cliResult.success) {
29824
- diagnostics.push(`${checkType} check failed: ${cliResult.error ?? "unknown error"}`);
29825
- continue;
29826
- }
29827
- if (cliResult.output.trim().length > 0) {
29828
- allItems.push(...parseCheckOutput(checkType, cliResult.output));
29829
- }
29830
- }
29831
- if (allItems.length === 0 && diagnostics.length === 0) {
29832
- return {
29833
- ...base,
29834
- status: "no_results",
29835
- summary: "No issues found \u2014 vault graph is healthy",
29836
- results: [],
29837
- truncated: false,
29838
- diagnostics
29839
- };
29840
- }
29841
- const truncated = allItems.length > limit;
29842
- const results = allItems.slice(0, limit);
29843
- return {
29844
- ...base,
29845
- status: allItems.length > 0 ? "ok" : "no_results",
29846
- summary: `Found ${allItems.length} graph issues across ${checks.join(", ")} checks`,
29847
- results,
29848
- truncated,
29849
- totalMatches: allItems.length,
29850
- diagnostics
29851
- };
29852
- }
29853
-
29854
- // dist/tools/graph-health.js
29855
- var byoao_graph_health = tool({
29856
- description: "Diagnose Obsidian vault graph health \u2014 find orphan notes (no links in or out), unresolved links (broken wikilinks), and dead-end notes. Uses Obsidian CLI for vault-aware analysis.",
29857
- args: {
29858
- vaultPath: tool.schema.string().describe("Absolute path to the Obsidian vault"),
29859
- check: tool.schema.enum(["all", "orphans", "unresolved", "deadends"]).optional().describe("Which check to run: 'all' (default), 'orphans', 'unresolved', or 'deadends'"),
29860
- limit: tool.schema.number().optional().describe("Maximum number of results to return (default: 20)")
29861
- },
29862
- async execute(args) {
29863
- const result = await getGraphHealth({
29864
- vaultPath: args.vaultPath,
29865
- check: args.check,
29866
- limit: args.limit
29867
- });
29868
- return JSON.stringify(result, null, 2);
29869
- }
29870
- });
29871
-
29872
29266
  // dist/vault/upgrade.js
29873
- import path15 from "node:path";
29874
- var OBSIDIAN_CONFIG_FILES = [
29875
- "core-plugins.json",
29876
- "daily-notes.json",
29877
- "templates.json"
29878
- ];
29267
+ import path10 from "node:path";
29268
+ var OBSIDIAN_CONFIG_FILES = ["core-plugins.json"];
29879
29269
  async function scanInstalledAssets(vaultPath) {
29880
29270
  const skills = await scanSkillDirs(vaultPath);
29881
29271
  const commands = await scanDir(vaultPath, ".opencode/commands", ".md");
29882
29272
  const templates = await scanDir(vaultPath, "Knowledge/templates", ".md");
29883
29273
  const obsidianConfig = [];
29884
29274
  for (const file2 of OBSIDIAN_CONFIG_FILES) {
29885
- const abs = path15.join(vaultPath, ".obsidian", file2);
29275
+ const abs = path10.join(vaultPath, ".obsidian", file2);
29886
29276
  if (await fs.pathExists(abs)) {
29887
29277
  obsidianConfig.push(`.obsidian/${file2}`);
29888
29278
  }
@@ -29890,21 +29280,21 @@ async function scanInstalledAssets(vaultPath) {
29890
29280
  return { skills, commands, obsidianConfig, templates };
29891
29281
  }
29892
29282
  async function scanDir(vaultPath, relDir, ext) {
29893
- const absDir = path15.join(vaultPath, relDir);
29283
+ const absDir = path10.join(vaultPath, relDir);
29894
29284
  if (!await fs.pathExists(absDir))
29895
29285
  return [];
29896
29286
  const files = await fs.readdir(absDir);
29897
29287
  return files.filter((f) => f.endsWith(ext)).map((f) => `${relDir}/${f}`);
29898
29288
  }
29899
29289
  async function scanSkillDirs(vaultPath) {
29900
- const skillsRoot = path15.join(vaultPath, ".opencode", "skills");
29290
+ const skillsRoot = path10.join(vaultPath, ".opencode", "skills");
29901
29291
  if (!await fs.pathExists(skillsRoot))
29902
29292
  return [];
29903
29293
  const results = [];
29904
29294
  const entries = await fs.readdir(skillsRoot, { withFileTypes: true });
29905
29295
  for (const entry of entries) {
29906
29296
  if (entry.isDirectory()) {
29907
- const skillMd = path15.join(skillsRoot, entry.name, "SKILL.md");
29297
+ const skillMd = path10.join(skillsRoot, entry.name, "SKILL.md");
29908
29298
  if (await fs.pathExists(skillMd)) {
29909
29299
  results.push(`.opencode/skills/${entry.name}/SKILL.md`);
29910
29300
  }
@@ -29912,7 +29302,7 @@ async function scanSkillDirs(vaultPath) {
29912
29302
  }
29913
29303
  return results;
29914
29304
  }
29915
- var DEFAULT_PRESET = "pm-tpm";
29305
+ var DEFAULT_PRESET = "minimal";
29916
29306
  async function bootstrapManifest(vaultPath, preset) {
29917
29307
  const installedFiles = await scanInstalledAssets(vaultPath);
29918
29308
  await writeManifest(vaultPath, preset ?? DEFAULT_PRESET, installedFiles, "0.0.0");
@@ -29933,7 +29323,7 @@ function buildUpgradePlan(vaultPath, manifest, packageAssets) {
29933
29323
  const installed = new Set(manifest.infrastructure[key]);
29934
29324
  const shippedPaths = new Set(shipped.map((s) => s.relativePath));
29935
29325
  for (const entry of shipped) {
29936
- const onDisk = fs.existsSync(path15.join(vaultPath, entry.relativePath));
29326
+ const onDisk = fs.existsSync(path10.join(vaultPath, entry.relativePath));
29937
29327
  items.push({
29938
29328
  file: entry.relativePath,
29939
29329
  action: onDisk ? "update" : "add",
@@ -29956,23 +29346,103 @@ function buildUpgradePlan(vaultPath, manifest, packageAssets) {
29956
29346
  items
29957
29347
  };
29958
29348
  }
29349
+ var LLM_WIKI_AGENT_DIRS = ["entities", "concepts", "comparisons", "queries"];
29350
+ var LOG_MD_PLACEHOLDER = `# Agent Activity Log
29351
+
29352
+ Entries are appended here during /cook operations.
29353
+
29354
+ `;
29355
+ async function migrateV1ToV2Infrastructure(vaultPath) {
29356
+ for (const dir of LLM_WIKI_AGENT_DIRS) {
29357
+ const dirPath = path10.join(vaultPath, dir);
29358
+ if (!await fs.pathExists(dirPath)) {
29359
+ await fs.ensureDir(dirPath);
29360
+ }
29361
+ }
29362
+ const schemaPath = path10.join(vaultPath, "SCHEMA.md");
29363
+ if (!await fs.pathExists(schemaPath)) {
29364
+ const commonDir = getCommonDir();
29365
+ const schemaTemplatePath = path10.join(commonDir, "SCHEMA.md.hbs");
29366
+ let content;
29367
+ if (await fs.pathExists(schemaTemplatePath)) {
29368
+ const schemaTemplate = await fs.readFile(schemaTemplatePath, "utf-8");
29369
+ content = renderTemplate(schemaTemplate, {
29370
+ KB_NAME: path10.basename(vaultPath),
29371
+ WIKI_DOMAIN: ""
29372
+ });
29373
+ } else {
29374
+ content = `# SCHEMA
29375
+
29376
+ This file describes the vault knowledge schema. Update it as your model evolves.
29377
+
29378
+ `;
29379
+ }
29380
+ await fs.writeFile(schemaPath, content, "utf-8");
29381
+ }
29382
+ const logPath = path10.join(vaultPath, "log.md");
29383
+ if (!await fs.pathExists(logPath)) {
29384
+ await fs.writeFile(logPath, LOG_MD_PLACEHOLDER, "utf-8");
29385
+ }
29386
+ }
29387
+ async function collectV1DeprecatedInfrastructureItems(vaultPath) {
29388
+ const items = [];
29389
+ const templatesDir = path10.join(vaultPath, "Knowledge", "templates");
29390
+ if (await fs.pathExists(templatesDir)) {
29391
+ const files = await fs.readdir(templatesDir);
29392
+ for (const f of files) {
29393
+ if (f.endsWith(".md")) {
29394
+ items.push({
29395
+ file: `Knowledge/templates/${f}`,
29396
+ action: "deprecated",
29397
+ category: "templates"
29398
+ });
29399
+ }
29400
+ }
29401
+ }
29402
+ for (const cmd of ["weave.md", "emerge.md"]) {
29403
+ const rel = `.opencode/commands/${cmd}`;
29404
+ if (await fs.pathExists(path10.join(vaultPath, rel))) {
29405
+ items.push({
29406
+ file: rel,
29407
+ action: "deprecated",
29408
+ category: "commands"
29409
+ });
29410
+ }
29411
+ }
29412
+ return items;
29413
+ }
29414
+ function mergeForcedDeprecatedIntoPlan(items, forced) {
29415
+ const forcedFiles = new Set(forced.map((i) => i.file));
29416
+ const filtered = items.filter((i) => !(forcedFiles.has(i.file) && (i.action === "add" || i.action === "update")));
29417
+ const byFile = new Map(filtered.map((i) => [i.file, i]));
29418
+ for (const f of forced) {
29419
+ byFile.set(f.file, f);
29420
+ }
29421
+ return [...byFile.values()];
29422
+ }
29959
29423
  function resolveAssetsDir2() {
29960
- const srcAssets = path15.resolve(import.meta.dirname, "..", "assets");
29961
- const distAssets = path15.resolve(import.meta.dirname, "..", "..", "src", "assets");
29962
- if (fs.existsSync(srcAssets))
29963
- return srcAssets;
29424
+ const distAssets = path10.resolve(import.meta.dirname, "assets");
29425
+ const srcAssets = path10.resolve(import.meta.dirname, "..", "assets");
29426
+ const devAssets = path10.resolve(import.meta.dirname, "..", "..", "src", "assets");
29964
29427
  if (fs.existsSync(distAssets))
29965
29428
  return distAssets;
29966
- return srcAssets;
29429
+ if (fs.existsSync(srcAssets))
29430
+ return srcAssets;
29431
+ if (fs.existsSync(devAssets))
29432
+ return devAssets;
29433
+ return distAssets;
29967
29434
  }
29968
29435
  function resolveSkillsDir() {
29969
- const srcSkills = path15.resolve(import.meta.dirname, "..", "skills");
29970
- const distSkills = path15.resolve(import.meta.dirname, "..", "..", "src", "skills");
29971
- if (fs.existsSync(srcSkills))
29972
- return srcSkills;
29436
+ const distSkills = path10.resolve(import.meta.dirname, "assets", "skills");
29437
+ const srcSkills = path10.resolve(import.meta.dirname, "..", "skills");
29438
+ const devSkills = path10.resolve(import.meta.dirname, "..", "..", "src", "skills");
29973
29439
  if (fs.existsSync(distSkills))
29974
29440
  return distSkills;
29975
- return srcSkills;
29441
+ if (fs.existsSync(srcSkills))
29442
+ return srcSkills;
29443
+ if (fs.existsSync(devSkills))
29444
+ return devSkills;
29445
+ return distSkills;
29976
29446
  }
29977
29447
  function resolvePackageAssets(preset) {
29978
29448
  const assetsDir = resolveAssetsDir2();
@@ -29982,14 +29452,14 @@ function resolvePackageAssets(preset) {
29982
29452
  const commands = [];
29983
29453
  const obsidianConfig = [];
29984
29454
  const templates = [];
29985
- const obsidianSkillsDir = path15.join(assetsDir, "obsidian-skills");
29455
+ const obsidianSkillsDir = path10.join(assetsDir, "obsidian-skills");
29986
29456
  if (fs.existsSync(obsidianSkillsDir)) {
29987
29457
  for (const file2 of fs.readdirSync(obsidianSkillsDir)) {
29988
29458
  if (file2.endsWith(".md")) {
29989
29459
  const skillName = file2.replace(/\.md$/, "");
29990
29460
  skills.push({
29991
29461
  relativePath: `.opencode/skills/${skillName}/SKILL.md`,
29992
- sourcePath: path15.join(obsidianSkillsDir, file2)
29462
+ sourcePath: path10.join(obsidianSkillsDir, file2)
29993
29463
  });
29994
29464
  }
29995
29465
  }
@@ -29999,15 +29469,15 @@ function resolvePackageAssets(preset) {
29999
29469
  if (file2.endsWith(".md")) {
30000
29470
  commands.push({
30001
29471
  relativePath: `.opencode/commands/${file2}`,
30002
- sourcePath: path15.join(skillsDir, file2)
29472
+ sourcePath: path10.join(skillsDir, file2)
30003
29473
  });
30004
29474
  }
30005
29475
  }
30006
29476
  }
30007
- const obsidianSrcDir = path15.join(commonDir, "obsidian");
29477
+ const obsidianSrcDir = path10.join(commonDir, "obsidian");
30008
29478
  if (fs.existsSync(obsidianSrcDir)) {
30009
29479
  for (const file2 of OBSIDIAN_CONFIG_FILES) {
30010
- const srcPath = path15.join(obsidianSrcDir, file2);
29480
+ const srcPath = path10.join(obsidianSrcDir, file2);
30011
29481
  if (fs.existsSync(srcPath)) {
30012
29482
  obsidianConfig.push({
30013
29483
  relativePath: `.obsidian/${file2}`,
@@ -30016,26 +29486,26 @@ function resolvePackageAssets(preset) {
30016
29486
  }
30017
29487
  }
30018
29488
  }
30019
- const commonTemplatesDir = path15.join(commonDir, "templates");
29489
+ const commonTemplatesDir = path10.join(commonDir, "templates");
30020
29490
  if (fs.existsSync(commonTemplatesDir)) {
30021
29491
  for (const file2 of fs.readdirSync(commonTemplatesDir)) {
30022
29492
  if (file2.endsWith(".md")) {
30023
29493
  templates.push({
30024
29494
  relativePath: `Knowledge/templates/${file2}`,
30025
- sourcePath: path15.join(commonTemplatesDir, file2)
29495
+ sourcePath: path10.join(commonTemplatesDir, file2)
30026
29496
  });
30027
29497
  }
30028
29498
  }
30029
29499
  }
30030
29500
  try {
30031
29501
  const { presetsDir } = loadPreset(preset);
30032
- const presetTemplatesDir = path15.join(presetsDir, preset, "templates");
29502
+ const presetTemplatesDir = path10.join(presetsDir, preset, "templates");
30033
29503
  if (fs.existsSync(presetTemplatesDir)) {
30034
29504
  for (const file2 of fs.readdirSync(presetTemplatesDir)) {
30035
29505
  if (file2.endsWith(".md")) {
30036
29506
  templates.push({
30037
29507
  relativePath: `Knowledge/templates/${file2}`,
30038
- sourcePath: path15.join(presetTemplatesDir, file2)
29508
+ sourcePath: path10.join(presetTemplatesDir, file2)
30039
29509
  });
30040
29510
  }
30041
29511
  }
@@ -30048,7 +29518,7 @@ async function upgradeVault(vaultPath, options2) {
30048
29518
  const { preset, dryRun = false, force = false } = options2 ?? {};
30049
29519
  const detectedPath = detectVaultContext(vaultPath);
30050
29520
  if (!detectedPath) {
30051
- throw new Error(`No BYOAO vault detected at "${vaultPath}". Expected .obsidian/ and AGENTS.md or Knowledge/Glossary.md.`);
29521
+ throw new Error(`No BYOAO vault detected at "${vaultPath}". Expected .obsidian/ and AGENTS.md.`);
30052
29522
  }
30053
29523
  let manifest = await readManifest(vaultPath);
30054
29524
  if (!manifest) {
@@ -30067,14 +29537,21 @@ async function upgradeVault(vaultPath, options2) {
30067
29537
  dryRun
30068
29538
  };
30069
29539
  }
30070
- const legacyAgentMd = path15.join(vaultPath, "AGENT.md");
30071
- const newAgentsMd = path15.join(vaultPath, "AGENTS.md");
29540
+ const legacyAgentMd = path10.join(vaultPath, "AGENT.md");
29541
+ const newAgentsMd = path10.join(vaultPath, "AGENTS.md");
30072
29542
  if (!dryRun && await fs.pathExists(legacyAgentMd) && !await fs.pathExists(newAgentsMd)) {
30073
29543
  await fs.rename(legacyAgentMd, newAgentsMd);
30074
29544
  }
29545
+ if (!dryRun) {
29546
+ await migrateV1ToV2Infrastructure(vaultPath);
29547
+ }
30075
29548
  const effectivePreset = preset ?? manifest.preset;
30076
29549
  const packageAssets = resolvePackageAssets(effectivePreset);
30077
- const plan = buildUpgradePlan(vaultPath, manifest, packageAssets);
29550
+ let plan = buildUpgradePlan(vaultPath, manifest, packageAssets);
29551
+ plan = {
29552
+ ...plan,
29553
+ items: mergeForcedDeprecatedIntoPlan(plan.items, await collectV1DeprecatedInfrastructureItems(vaultPath))
29554
+ };
30078
29555
  const added = [];
30079
29556
  const updated = [];
30080
29557
  const deprecated = [];
@@ -30091,8 +29568,8 @@ async function upgradeVault(vaultPath, options2) {
30091
29568
  if (item.action === "add" || item.action === "update") {
30092
29569
  const source = sourceMap.get(item.file);
30093
29570
  if (source) {
30094
- const dest = path15.join(vaultPath, item.file);
30095
- await fs.ensureDir(path15.dirname(dest));
29571
+ const dest = path10.join(vaultPath, item.file);
29572
+ await fs.ensureDir(path10.dirname(dest));
30096
29573
  await fs.copy(source, dest, { overwrite: true });
30097
29574
  if (item.action === "add") {
30098
29575
  added.push(item.file);
@@ -30187,17 +29664,17 @@ var byoao_vault_upgrade = tool({
30187
29664
  });
30188
29665
 
30189
29666
  // dist/tools/mcp-auth.js
30190
- import { spawn, execSync as execSync4 } from "node:child_process";
30191
- import path16 from "node:path";
29667
+ import { spawn, execSync as execSync3 } from "node:child_process";
29668
+ import path11 from "node:path";
30192
29669
  import os4 from "node:os";
30193
29670
  function findOpencodeBinary() {
30194
29671
  const candidates = [
30195
- path16.join(os4.homedir(), ".opencode/bin/opencode"),
29672
+ path11.join(os4.homedir(), ".opencode/bin/opencode"),
30196
29673
  "/usr/local/bin/opencode"
30197
29674
  ];
30198
29675
  for (const p of candidates) {
30199
29676
  try {
30200
- execSync4(`test -x "${p}"`, { stdio: "pipe" });
29677
+ execSync3(`test -x "${p}"`, { stdio: "pipe" });
30201
29678
  return p;
30202
29679
  } catch {
30203
29680
  }
@@ -30295,10 +29772,13 @@ The user may need to:
30295
29772
  }
30296
29773
  });
30297
29774
 
29775
+ // dist/hooks/system-transform.js
29776
+ import path12 from "node:path";
29777
+
30298
29778
  // dist/lib/logger.js
30299
29779
  import { join } from "node:path";
30300
29780
  import { homedir } from "node:os";
30301
- import { appendFile, stat, rename as rename3, mkdir as mkdir2, readFile as readFile2, unlink } from "node:fs/promises";
29781
+ import { appendFile, stat as stat2, rename as rename3, mkdir as mkdir2, readFile as readFile2, unlink } from "node:fs/promises";
30302
29782
  var LOG_DIR = process.env.BYOAO_LOG_DIR || join(homedir(), ".byoao", "logs");
30303
29783
  var LOG_FILE = join(LOG_DIR, "error.log");
30304
29784
  var MAX_LOG_SIZE = 512 * 1024;
@@ -30341,7 +29821,7 @@ async function ensureLogDir() {
30341
29821
  }
30342
29822
  async function rotateIfNeeded() {
30343
29823
  try {
30344
- const s = await stat(LOG_FILE);
29824
+ const s = await stat2(LOG_FILE);
30345
29825
  if (s.size >= MAX_LOG_SIZE) {
30346
29826
  await rename3(LOG_FILE, ROTATED_FILE);
30347
29827
  }
@@ -30372,6 +29852,20 @@ async function log(level, source, message, options2) {
30372
29852
  }
30373
29853
 
30374
29854
  // dist/hooks/system-transform.js
29855
+ function readVaultMarkdown(vaultPath, fileName) {
29856
+ const full = path12.join(vaultPath, fileName);
29857
+ if (!fs.existsSync(full))
29858
+ return null;
29859
+ try {
29860
+ return fs.readFileSync(full, "utf-8");
29861
+ } catch {
29862
+ void log("warn", "hook:system-transform", `Failed to read ${fileName}`, {
29863
+ context: { path: full }
29864
+ }).catch(() => {
29865
+ });
29866
+ return null;
29867
+ }
29868
+ }
30375
29869
  async function buildMcpAuthGuidance() {
30376
29870
  try {
30377
29871
  const config2 = await readOpencodeConfig();
@@ -30409,6 +29903,31 @@ async function buildMcpAuthGuidance() {
30409
29903
  }
30410
29904
  }
30411
29905
  async function systemTransformHook(_input, output) {
29906
+ const vaultPath = detectVaultContext(process.cwd());
29907
+ if (vaultPath) {
29908
+ let agentsTitle = "## AGENTS.md";
29909
+ let agents = readVaultMarkdown(vaultPath, "AGENTS.md");
29910
+ if (!agents) {
29911
+ agents = readVaultMarkdown(vaultPath, "AGENT.md");
29912
+ if (agents)
29913
+ agentsTitle = "## AGENT.md";
29914
+ }
29915
+ if (agents) {
29916
+ output.system.push(`
29917
+ ---
29918
+ ${agentsTitle}
29919
+
29920
+ ${agents}`);
29921
+ }
29922
+ const schema = readVaultMarkdown(vaultPath, "SCHEMA.md");
29923
+ if (schema) {
29924
+ output.system.push(`
29925
+ ---
29926
+ ## SCHEMA.md
29927
+
29928
+ ${schema}`);
29929
+ }
29930
+ }
30412
29931
  const mcpGuidance = await buildMcpAuthGuidance();
30413
29932
  if (mcpGuidance) {
30414
29933
  output.system.push(mcpGuidance);
@@ -30418,15 +29937,15 @@ async function systemTransformHook(_input, output) {
30418
29937
  // dist/hooks/idle-suggestions.js
30419
29938
  function getIdleSuggestion() {
30420
29939
  const suggestions = [
30421
- "Tip: run /weave to connect your notes with frontmatter and wikilinks",
29940
+ "Tip: run /cook to compile your notes into structured knowledge pages",
29941
+ "Tip: run /health to check knowledge page health",
29942
+ "Tip: run /wiki to regenerate INDEX.base",
30422
29943
  "Tip: run /trace to see how an idea evolved over time",
30423
- "Tip: run /emerge to discover patterns across your notes",
30424
29944
  "Tip: run /connect to bridge two topics using your vault's link graph",
30425
29945
  "Tip: run /ideas to generate actionable insights from your vault",
30426
29946
  "Tip: run /challenge to pressure-test a belief against your own notes",
30427
29947
  "Tip: run /drift to compare intentions vs actions over the past month",
30428
- "Tip: run /diagnose to check knowledge graph health",
30429
- "Tip: run /explain to document a codebase system in your vault"
29948
+ "Tip: run /diagnose to check overall vault health"
30430
29949
  ];
30431
29950
  const idx = (/* @__PURE__ */ new Date()).getMinutes() % suggestions.length;
30432
29951
  return suggestions[idx];
@@ -30437,15 +29956,9 @@ var BYOAOPlugin = async (ctx) => {
30437
29956
  const { client } = ctx;
30438
29957
  const tools = {
30439
29958
  byoao_init_vault,
30440
- byoao_add_person,
30441
- byoao_add_project,
30442
- byoao_add_glossary_term,
30443
29959
  byoao_vault_status,
30444
29960
  byoao_vault_doctor,
30445
29961
  byoao_switch_provider,
30446
- byoao_search_vault,
30447
- byoao_note_read,
30448
- byoao_graph_health,
30449
29962
  byoao_vault_upgrade,
30450
29963
  byoao_mcp_auth
30451
29964
  };