@backendkit-labs/agent-enterprise 0.3.6 → 0.4.1

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 (47) hide show
  1. package/dist/factory.d.ts.map +1 -1
  2. package/dist/factory.js +12 -15
  3. package/dist/factory.js.map +1 -1
  4. package/dist/flow/ComplianceGate.d.ts +10 -0
  5. package/dist/flow/ComplianceGate.d.ts.map +1 -1
  6. package/dist/flow/ComplianceGate.js.map +1 -1
  7. package/dist/flow/FlowRunner.d.ts +7 -0
  8. package/dist/flow/FlowRunner.d.ts.map +1 -1
  9. package/dist/flow/FlowRunner.js +9 -0
  10. package/dist/flow/FlowRunner.js.map +1 -1
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +7 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/rag/ObsidianRAGProvider.d.ts +22 -0
  16. package/dist/rag/ObsidianRAGProvider.d.ts.map +1 -1
  17. package/dist/rag/ObsidianRAGProvider.js +36 -2
  18. package/dist/rag/ObsidianRAGProvider.js.map +1 -1
  19. package/dist/rag/OllamaEmbedder.d.ts +6 -0
  20. package/dist/rag/OllamaEmbedder.d.ts.map +1 -1
  21. package/dist/rag/OllamaEmbedder.js +75 -16
  22. package/dist/rag/OllamaEmbedder.js.map +1 -1
  23. package/dist/rag/SimpleEmbedder.d.ts +24 -2
  24. package/dist/rag/SimpleEmbedder.d.ts.map +1 -1
  25. package/dist/rag/SimpleEmbedder.js +121 -22
  26. package/dist/rag/SimpleEmbedder.js.map +1 -1
  27. package/dist/rag/VaultWriter.d.ts +3 -0
  28. package/dist/rag/VaultWriter.d.ts.map +1 -1
  29. package/dist/rag/VaultWriter.js +63 -17
  30. package/dist/rag/VaultWriter.js.map +1 -1
  31. package/dist/reflection/EnterpriseReflection.d.ts +108 -0
  32. package/dist/reflection/EnterpriseReflection.d.ts.map +1 -0
  33. package/dist/reflection/EnterpriseReflection.js +296 -0
  34. package/dist/reflection/EnterpriseReflection.js.map +1 -0
  35. package/dist/reflection/GateReflectionBridge.d.ts +21 -0
  36. package/dist/reflection/GateReflectionBridge.d.ts.map +1 -0
  37. package/dist/reflection/GateReflectionBridge.js +120 -0
  38. package/dist/reflection/GateReflectionBridge.js.map +1 -0
  39. package/dist/reflection/domains.d.ts +6 -0
  40. package/dist/reflection/domains.d.ts.map +1 -0
  41. package/dist/reflection/domains.js +176 -0
  42. package/dist/reflection/domains.js.map +1 -0
  43. package/dist/reflection/index.d.ts +6 -0
  44. package/dist/reflection/index.d.ts.map +1 -0
  45. package/dist/reflection/index.js +11 -0
  46. package/dist/reflection/index.js.map +1 -0
  47. package/package.json +2 -2
@@ -5,19 +5,41 @@
5
5
  * 1. Tokenising text into lowercase alphanumeric tokens
6
6
  * 2. Mapping each token to a bucket via djb2 hash % DIMS
7
7
  * 3. Accumulating term-frequency counts in the bucket
8
- * 4. L2-normalising to a unit vector
8
+ * 4. Weighting each bucket by inverse document frequency (rarer buckets score higher)
9
+ * 5. L2-normalising to a unit vector
9
10
  *
10
11
  * Not semantically equivalent to transformer embeddings, but clusters texts
11
12
  * with shared vocabulary close together — sufficient to find notes whose
12
- * content matches the query's key terms.
13
+ * content matches the query's key terms, and the IDF term keeps common
14
+ * words (the, and, sistema, ...) from drowning out the words that actually
15
+ * distinguish one note from another.
13
16
  *
14
17
  * Use this when Ollama is not available (dev, CI, pilot). For production,
15
18
  * prefer OllamaEmbedder with nomic-embed-text for semantic accuracy.
16
19
  */
17
20
  import type { Embedder } from './ObsidianRAGProvider';
18
21
  export declare class SimpleEmbedder implements Embedder {
22
+ private readonly statsPath?;
19
23
  readonly model = "simple-tfidf-256";
24
+ private docCount;
25
+ private readonly docFreq;
26
+ private loaded;
27
+ /**
28
+ * @param statsPath Optional path to persist document-frequency stats across
29
+ * process restarts. Without it, IDF starts fresh (pure TF) every time the
30
+ * process starts and improves as more text gets embedded during that run.
31
+ */
32
+ constructor(statsPath?: string | undefined);
33
+ private ensureLoaded;
34
+ private persist;
35
+ /** Smoothed IDF — always positive, well-defined even when a bucket has never been seen (df=0). */
36
+ private idf;
37
+ private vectorise;
38
+ /** Registers `text` as a corpus document (updates docFreq/docCount), then vectorises it against the updated stats. */
39
+ private observe;
40
+ /** Indexing path — each text counts toward the corpus's document-frequency stats. */
20
41
  embed(texts: string[]): Promise<number[][]>;
42
+ /** Query path — a search query is not a new corpus document, so it's weighted read-only against current stats, never counted. */
21
43
  embedOne(text: string): Promise<number[]>;
22
44
  }
23
45
  //# sourceMappingURL=SimpleEmbedder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleEmbedder.d.ts","sourceRoot":"","sources":["../../src/rag/SimpleEmbedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAyCtD,qBAAa,cAAe,YAAW,QAAQ;IAC3C,QAAQ,CAAC,KAAK,sBAAsB;IAE9B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAI3C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAGlD"}
1
+ {"version":3,"file":"SimpleEmbedder.d.ts","sourceRoot":"","sources":["../../src/rag/SimpleEmbedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AA4BtD,qBAAa,cAAe,YAAW,QAAQ;IAY/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAXvC,QAAQ,CAAC,KAAK,sBAAsB;IAEpC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;OAIG;gBAC0B,SAAS,CAAC,EAAE,MAAM,YAAA;YAEjC,YAAY;YAgBZ,OAAO;IAUrB,kGAAkG;IAClG,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,SAAS;IAuBjB,sHAAsH;IACtH,OAAO,CAAC,OAAO;IAOf,qFAAqF;IAC/E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAOjD,iIAAiI;IAC3H,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAIlD"}
@@ -6,17 +6,54 @@
6
6
  * 1. Tokenising text into lowercase alphanumeric tokens
7
7
  * 2. Mapping each token to a bucket via djb2 hash % DIMS
8
8
  * 3. Accumulating term-frequency counts in the bucket
9
- * 4. L2-normalising to a unit vector
9
+ * 4. Weighting each bucket by inverse document frequency (rarer buckets score higher)
10
+ * 5. L2-normalising to a unit vector
10
11
  *
11
12
  * Not semantically equivalent to transformer embeddings, but clusters texts
12
13
  * with shared vocabulary close together — sufficient to find notes whose
13
- * content matches the query's key terms.
14
+ * content matches the query's key terms, and the IDF term keeps common
15
+ * words (the, and, sistema, ...) from drowning out the words that actually
16
+ * distinguish one note from another.
14
17
  *
15
18
  * Use this when Ollama is not available (dev, CI, pilot). For production,
16
19
  * prefer OllamaEmbedder with nomic-embed-text for semantic accuracy.
17
20
  */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
18
54
  Object.defineProperty(exports, "__esModule", { value: true });
19
55
  exports.SimpleEmbedder = void 0;
56
+ const fs = __importStar(require("fs/promises"));
20
57
  const DIMS = 256;
21
58
  function djb2(str) {
22
59
  let h = 5381;
@@ -33,32 +70,94 @@ function tokenise(text) {
33
70
  .split(/[^a-z0-9]+/)
34
71
  .filter(t => t.length > 2); // skip 1-2 char noise tokens
35
72
  }
36
- function vectorise(text) {
37
- const vec = new Array(DIMS).fill(0);
38
- const tokens = tokenise(text);
39
- if (tokens.length === 0)
73
+ class SimpleEmbedder {
74
+ statsPath;
75
+ model = 'simple-tfidf-256';
76
+ docCount = 0;
77
+ docFreq = new Map();
78
+ loaded = false;
79
+ /**
80
+ * @param statsPath Optional path to persist document-frequency stats across
81
+ * process restarts. Without it, IDF starts fresh (pure TF) every time the
82
+ * process starts and improves as more text gets embedded during that run.
83
+ */
84
+ constructor(statsPath) {
85
+ this.statsPath = statsPath;
86
+ }
87
+ async ensureLoaded() {
88
+ if (this.loaded)
89
+ return;
90
+ this.loaded = true;
91
+ if (!this.statsPath)
92
+ return;
93
+ try {
94
+ const raw = await fs.readFile(this.statsPath, 'utf-8');
95
+ const data = JSON.parse(raw);
96
+ this.docCount = data.docCount;
97
+ for (const [bucket, count] of Object.entries(data.docFreq)) {
98
+ this.docFreq.set(Number(bucket), count);
99
+ }
100
+ }
101
+ catch {
102
+ // No stats file yet — start fresh.
103
+ }
104
+ }
105
+ async persist() {
106
+ if (!this.statsPath)
107
+ return;
108
+ const data = {
109
+ version: 1,
110
+ docCount: this.docCount,
111
+ docFreq: Object.fromEntries(this.docFreq),
112
+ };
113
+ await fs.writeFile(this.statsPath, JSON.stringify(data), 'utf-8');
114
+ }
115
+ /** Smoothed IDF — always positive, well-defined even when a bucket has never been seen (df=0). */
116
+ idf(bucket) {
117
+ const df = this.docFreq.get(bucket) ?? 0;
118
+ return Math.log((this.docCount + 1) / (df + 1)) + 1;
119
+ }
120
+ vectorise(text) {
121
+ const vec = new Array(DIMS).fill(0);
122
+ const tokens = tokenise(text);
123
+ if (tokens.length === 0)
124
+ return vec;
125
+ for (const t of tokens) {
126
+ vec[djb2(t) % DIMS] += 1;
127
+ }
128
+ // Weight each occupied bucket by IDF, then L2-normalise.
129
+ let norm = 0;
130
+ for (let i = 0; i < DIMS; i++) {
131
+ if (vec[i] > 0)
132
+ vec[i] *= this.idf(i);
133
+ norm += vec[i] * vec[i];
134
+ }
135
+ norm = Math.sqrt(norm);
136
+ if (norm > 0) {
137
+ for (let i = 0; i < DIMS; i++)
138
+ vec[i] /= norm;
139
+ }
40
140
  return vec;
41
- for (const t of tokens) {
42
- vec[djb2(t) % DIMS] += 1;
43
141
  }
44
- // L2 normalise
45
- let norm = 0;
46
- for (const v of vec)
47
- norm += v * v;
48
- norm = Math.sqrt(norm);
49
- if (norm > 0) {
50
- for (let i = 0; i < DIMS; i++)
51
- vec[i] /= norm;
142
+ /** Registers `text` as a corpus document (updates docFreq/docCount), then vectorises it against the updated stats. */
143
+ observe(text) {
144
+ const buckets = new Set(tokenise(text).map(t => djb2(t) % DIMS));
145
+ for (const b of buckets)
146
+ this.docFreq.set(b, (this.docFreq.get(b) ?? 0) + 1);
147
+ this.docCount++;
148
+ return this.vectorise(text);
52
149
  }
53
- return vec;
54
- }
55
- class SimpleEmbedder {
56
- model = 'simple-tfidf-256';
150
+ /** Indexing path — each text counts toward the corpus's document-frequency stats. */
57
151
  async embed(texts) {
58
- return texts.map(vectorise);
152
+ await this.ensureLoaded();
153
+ const vectors = texts.map(t => this.observe(t));
154
+ await this.persist();
155
+ return vectors;
59
156
  }
157
+ /** Query path — a search query is not a new corpus document, so it's weighted read-only against current stats, never counted. */
60
158
  async embedOne(text) {
61
- return vectorise(text);
159
+ await this.ensureLoaded();
160
+ return this.vectorise(text);
62
161
  }
63
162
  }
64
163
  exports.SimpleEmbedder = SimpleEmbedder;
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleEmbedder.js","sourceRoot":"","sources":["../../src/rag/SimpleEmbedder.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAIH,MAAM,IAAI,GAAG,GAAG,CAAC;AAEjB,SAAS,IAAI,CAAC,GAAW;IACrB,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC1B,OAAO,IAAI;SACN,WAAW,EAAE;SACb,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAG,mBAAmB;SAC3C,KAAK,CAAC,YAAY,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAS,6BAA6B;AACzE,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC3B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEpC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACrB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,eAAe;IACf,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAClD,CAAC;IAED,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAa,cAAc;IACd,KAAK,GAAG,kBAAkB,CAAC;IAEpC,KAAK,CAAC,KAAK,CAAC,KAAe;QACvB,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACvB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;CACJ;AAVD,wCAUC"}
1
+ {"version":3,"file":"SimpleEmbedder.js","sourceRoot":"","sources":["../../src/rag/SimpleEmbedder.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,9 @@ export interface WriteNoteParams {
19
19
  * Notes use standard YAML frontmatter so the VaultIndexer picks them up
20
20
  * on the next incremental index() call, making them immediately searchable
21
21
  * by any agent or human that queries the vault.
22
+ *
23
+ * Concurrent writes are serialized with a per-file lock (wx atomic open)
24
+ * so multiple agents writing simultaneously cannot corrupt each other's notes.
22
25
  */
23
26
  export declare class VaultWriter {
24
27
  private readonly vaultPath;
@@ -1 +1 @@
1
- {"version":3,"file":"VaultWriter.d.ts","sourceRoot":"","sources":["../../src/rag/VaultWriter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,WAAW,kBAAkB;IAC/B,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,IAAI,EAAE,kBAAkB;IAK9B,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAuCzD;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;CAgC9C"}
1
+ {"version":3,"file":"VaultWriter.d.ts","sourceRoot":"","sources":["../../src/rag/VaultWriter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,WAAW,kBAAkB;IAC/B,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,IAAI,EAAE,kBAAkB;IAK9B,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBzD;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;CAgC9C"}
@@ -43,6 +43,9 @@ const agent_core_1 = require("@backendkit-labs/agent-core");
43
43
  * Notes use standard YAML frontmatter so the VaultIndexer picks them up
44
44
  * on the next incremental index() call, making them immediately searchable
45
45
  * by any agent or human that queries the vault.
46
+ *
47
+ * Concurrent writes are serialized with a per-file lock (wx atomic open)
48
+ * so multiple agents writing simultaneously cannot corrupt each other's notes.
46
49
  */
47
50
  class VaultWriter {
48
51
  vaultPath;
@@ -65,24 +68,9 @@ class VaultWriter {
65
68
  const filename = `${date}-${slug}.md`;
66
69
  const dir = path.join(this.vaultPath, this.agentFolder);
67
70
  await fs.mkdir(dir, { recursive: true });
68
- const tagsLine = tags.length
69
- ? `[${tags.map(t => `"${t}"`).join(', ')}]`
70
- : '[]';
71
- const lines = [
72
- '---',
73
- `title: "${title}"`,
74
- `author: "agent/${agentId}"`,
75
- `date: ${date}`,
76
- `tags: ${tagsLine}`,
77
- ];
78
- if (description)
79
- lines.push(`description: "${description}"`);
80
- if (related_notes.length) {
81
- lines.push(`related_notes: [${related_notes.map(n => `"${n}"`).join(', ')}]`);
82
- }
83
- lines.push('---', '', content);
84
71
  const filePath = path.join(dir, filename);
85
- await fs.writeFile(filePath, lines.join('\n'), 'utf-8');
72
+ const body = buildNote({ title, content, agentId, tags, description, related_notes, date });
73
+ await withFileLock(filePath, () => fs.writeFile(filePath, body, 'utf-8'));
86
74
  return filePath;
87
75
  }
88
76
  /**
@@ -114,4 +102,62 @@ class VaultWriter {
114
102
  }
115
103
  }
116
104
  exports.VaultWriter = VaultWriter;
105
+ // ── Helpers ───────────────────────────────────────────────────────────────────
106
+ function buildNote(p) {
107
+ const tagsLine = p.tags?.length
108
+ ? `[${p.tags.map(t => `"${t}"`).join(', ')}]`
109
+ : '[]';
110
+ const lines = [
111
+ '---',
112
+ `title: "${p.title}"`,
113
+ `author: "agent/${p.agentId}"`,
114
+ `date: ${p.date}`,
115
+ `tags: ${tagsLine}`,
116
+ ];
117
+ if (p.description)
118
+ lines.push(`description: "${p.description}"`);
119
+ if (p.related_notes?.length) {
120
+ lines.push(`related_notes: [${p.related_notes.map(n => `"${n}"`).join(', ')}]`);
121
+ }
122
+ lines.push('---', '', p.content);
123
+ return lines.join('\n');
124
+ }
125
+ /**
126
+ * Serialize writes to the same file path using an adjacent .lock file.
127
+ * Uses O_EXCL (wx flag) for atomic creation — only one process/coroutine
128
+ * can hold the lock at a time. Retries with exponential backoff.
129
+ */
130
+ async function withFileLock(filePath, fn) {
131
+ const lockPath = `${filePath}.lock`;
132
+ const maxRetries = 10;
133
+ const baseDelay = 50;
134
+ let fd = null;
135
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
136
+ try {
137
+ // wx = O_WRONLY | O_CREAT | O_EXCL — fails atomically if lock exists
138
+ fd = await fs.open(lockPath, 'wx');
139
+ break;
140
+ }
141
+ catch {
142
+ if (attempt < maxRetries - 1) {
143
+ await sleep(baseDelay * 2 ** attempt + Math.random() * baseDelay);
144
+ }
145
+ else {
146
+ throw new Error(`Could not acquire lock for ${path.basename(filePath)} after ${maxRetries} attempts`);
147
+ }
148
+ }
149
+ }
150
+ try {
151
+ return await fn();
152
+ }
153
+ finally {
154
+ if (fd) {
155
+ await fd.close().catch(() => { });
156
+ await fs.unlink(lockPath).catch(() => { });
157
+ }
158
+ }
159
+ }
160
+ function sleep(ms) {
161
+ return new Promise(resolve => setTimeout(resolve, ms));
162
+ }
117
163
  //# sourceMappingURL=VaultWriter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VaultWriter.js","sourceRoot":"","sources":["../../src/rag/VaultWriter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VaultWriter.js","sourceRoot":"","sources":["../../src/rag/VaultWriter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import type { FailureRecord, DetectedPattern, ManifestPolicyRule } from '@backendkit-labs/agent-core/reflection';
2
+ import type { GateRecord } from '../flow/ComplianceGate.js';
3
+ export interface EnterpriseReflectionOptions {
4
+ /** Absolute path to the Obsidian vault. Generated manifest lives inside it. */
5
+ vaultPath: string;
6
+ /**
7
+ * App name for the catalog scope.
8
+ * MUST differ from 'deepseek-code' to avoid collision with the coding agent.
9
+ * Default: 'bk-enterprise'
10
+ */
11
+ appName?: string;
12
+ /**
13
+ * Override path for manifest.yaml.
14
+ * Default: {vaultPath}/politicas/_generated/manifest.yaml
15
+ */
16
+ manifestPath?: string;
17
+ }
18
+ export interface PendingPromotion {
19
+ pattern: DetectedPattern;
20
+ detectedAt: string;
21
+ }
22
+ /**
23
+ * Adapter that wires the ReflectionEngine (from agent-core, built for coding
24
+ * agents) to enterprise business agents — without modifying agent-core.
25
+ *
26
+ * Key differences vs the coding-agent usage:
27
+ * - Isolated catalog: appName='bk-enterprise', useGlobalDir=false
28
+ * - autoPromote=false: every promotion requires human approval
29
+ * - Threshold by severity: critical=1, high=2, medium/low=3
30
+ * - Source of incidents: ComplianceGate (evaluator≠executor guaranteed)
31
+ * - manifest.yaml lives inside the vault (auditable, versionable via git)
32
+ */
33
+ export declare class EnterpriseReflection {
34
+ private readonly engine;
35
+ private readonly registry;
36
+ private readonly manifestPath;
37
+ private readonly activeDomains;
38
+ private initialized;
39
+ private readonly pendingMap;
40
+ constructor(opts: EnterpriseReflectionOptions);
41
+ /**
42
+ * Must be called once before any other method.
43
+ * Registers enterprise domains in the DomainRegistry and initializes
44
+ * the engine catalog from disk.
45
+ */
46
+ initialize(): Promise<void>;
47
+ /**
48
+ * Records the outcome of a resolved ComplianceGate.
49
+ * Only failed criteria and process violations generate incidents.
50
+ * Passed gates produce no catalog entries.
51
+ */
52
+ recordGateOutcome(record: GateRecord): Promise<FailureRecord[]>;
53
+ /**
54
+ * Scans for patterns using per-severity thresholds.
55
+ * Does NOT promote — patterns accumulate in pendingPromotions() for human review.
56
+ */
57
+ detect(domain?: string): Promise<DetectedPattern[]>;
58
+ /**
59
+ * Returns patterns that crossed the promotion threshold but haven't been
60
+ * promoted yet (autoPromote=false). Show these to the human approver.
61
+ */
62
+ pendingPromotions(): Promise<PendingPromotion[]>;
63
+ /**
64
+ * Promotes a detected pattern to a deterministic policyRule in manifest.yaml.
65
+ * Requires an explicit approver identity — logged in the manifest metadata.
66
+ *
67
+ * After approval the pattern is removed from pendingPromotions().
68
+ */
69
+ approvePromotion(pattern: DetectedPattern, approver: string): Promise<ManifestPolicyRule>;
70
+ /**
71
+ * Rejects a promotion — removes from pending without writing to manifest.
72
+ * The reason is stored as a resolved-but-not-promoted audit note.
73
+ */
74
+ rejectPromotion(pattern: DetectedPattern, approver: string, reason: string): Promise<void>;
75
+ /**
76
+ * Returns active policyRules from manifest.yaml, optionally filtered by domain.
77
+ * Call this BEFORE executing a step to inject deterministic constraints.
78
+ */
79
+ activeRules(filter?: {
80
+ domain?: string;
81
+ }): Promise<ManifestPolicyRule[]>;
82
+ /**
83
+ * Records whether applying a rule led to a successful or failed outcome.
84
+ * Outcomes feed demotionCandidates() — rules with many failures signal
85
+ * that the rule itself may be wrong.
86
+ */
87
+ recordRuleOutcome(ruleId: string, outcome: 'success' | 'failure'): Promise<void>;
88
+ /**
89
+ * Returns rules whose failure rate exceeds minFailureRatio (default 0.5)
90
+ * with at least minTotal applications (default 4).
91
+ *
92
+ * These are candidates for human-gated demotion — symmetric with promotion:
93
+ * the rulebook only changes in either direction with human approval.
94
+ */
95
+ demotionCandidates(opts?: {
96
+ minFailureRatio?: number;
97
+ minTotal?: number;
98
+ }): Promise<ManifestPolicyRule[]>;
99
+ /**
100
+ * Removes a rule from manifest.yaml after human approval of demotion.
101
+ * Symmetric with approvePromotion — requires explicit approver.
102
+ */
103
+ approveDemotion(ruleId: string, approver: string, reason: string): Promise<boolean>;
104
+ stats(): Promise<import("@backendkit-labs/agent-core").ReflectionStats>;
105
+ private assertInitialized;
106
+ private annotateApproval;
107
+ }
108
+ //# sourceMappingURL=EnterpriseReflection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnterpriseReflection.d.ts","sourceRoot":"","sources":["../../src/reflection/EnterpriseReflection.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AACjH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAM5D,MAAM,WAAW,2BAA2B;IACxC,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAI,eAAe,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACtB;AAID;;;;;;;;;;GAUG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAW;IACzC,OAAO,CAAU,WAAW,CAAY;IAIxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;gBAEtD,IAAI,EAAE,2BAA2B;IA0B7C;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAQrE;;;OAGG;IACG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA+BzD;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOtD;;;;;OAKG;IACG,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgB/F;;;OAGG;IACG,eAAe,CACjB,OAAO,EAAG,eAAe,EACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAI,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAoBhB;;;OAGG;IACG,WAAW,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAQ9E;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtF;;;;;;OAMG;IACG,kBAAkB,CAAC,IAAI,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAanH;;;OAGG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBnF,KAAK;IAOX,OAAO,CAAC,iBAAiB;YAMX,gBAAgB;CAgBjC"}