@monoes/monomindcli 2.16.12 → 2.16.13

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 (217) hide show
  1. package/.claude/agents/core/coder.md +1 -1
  2. package/.claude/agents/engineering/engineering-devops-automator.md +1 -1
  3. package/.claude/agents/github/repo-architect.md +1 -1
  4. package/.claude/agents/testing/production-validator.md +1 -1
  5. package/.claude/agents/testing/testing-tool-evaluator.md +1 -1
  6. package/.claude/commands/github/pr-manager.md +1 -1
  7. package/.claude/helpers/pick-rank.cjs +34 -4
  8. package/.claude/skills/monolean-audit/SKILL.md +1 -1
  9. package/dist/src/commands/cleanup-data.d.ts +30 -0
  10. package/dist/src/commands/cleanup-data.d.ts.map +1 -0
  11. package/dist/src/commands/cleanup-data.js +138 -0
  12. package/dist/src/commands/cleanup-data.js.map +1 -0
  13. package/dist/src/commands/cleanup-scratch.d.ts +43 -0
  14. package/dist/src/commands/cleanup-scratch.d.ts.map +1 -0
  15. package/dist/src/commands/cleanup-scratch.js +125 -0
  16. package/dist/src/commands/cleanup-scratch.js.map +1 -0
  17. package/dist/src/commands/cleanup.d.ts +2 -39
  18. package/dist/src/commands/cleanup.d.ts.map +1 -1
  19. package/dist/src/commands/cleanup.js +5 -247
  20. package/dist/src/commands/cleanup.js.map +1 -1
  21. package/dist/src/commands/doctor-gitignore-checks.d.ts +10 -0
  22. package/dist/src/commands/doctor-gitignore-checks.d.ts.map +1 -0
  23. package/dist/src/commands/doctor-gitignore-checks.js +141 -0
  24. package/dist/src/commands/doctor-gitignore-checks.js.map +1 -0
  25. package/dist/src/commands/doctor-helpers-checks.d.ts +10 -0
  26. package/dist/src/commands/doctor-helpers-checks.d.ts.map +1 -0
  27. package/dist/src/commands/doctor-helpers-checks.js +292 -0
  28. package/dist/src/commands/doctor-helpers-checks.js.map +1 -0
  29. package/dist/src/commands/doctor-memory-checks.d.ts +47 -0
  30. package/dist/src/commands/doctor-memory-checks.d.ts.map +1 -0
  31. package/dist/src/commands/doctor-memory-checks.js +298 -0
  32. package/dist/src/commands/doctor-memory-checks.js.map +1 -0
  33. package/dist/src/commands/doctor-monograph-checks.d.ts +9 -0
  34. package/dist/src/commands/doctor-monograph-checks.d.ts.map +1 -0
  35. package/dist/src/commands/doctor-monograph-checks.js +331 -0
  36. package/dist/src/commands/doctor-monograph-checks.js.map +1 -0
  37. package/dist/src/commands/doctor-project-checks.d.ts +7 -66
  38. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  39. package/dist/src/commands/doctor-project-checks.js +10 -1331
  40. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  41. package/dist/src/commands/doctor-routing-checks.d.ts +10 -0
  42. package/dist/src/commands/doctor-routing-checks.d.ts.map +1 -0
  43. package/dist/src/commands/doctor-routing-checks.js +194 -0
  44. package/dist/src/commands/doctor-routing-checks.js.map +1 -0
  45. package/dist/src/commands/doctor-worker-checks.d.ts +17 -0
  46. package/dist/src/commands/doctor-worker-checks.d.ts.map +1 -0
  47. package/dist/src/commands/doctor-worker-checks.js +122 -0
  48. package/dist/src/commands/doctor-worker-checks.js.map +1 -0
  49. package/dist/src/commands/hooks-routing-commands.js +1 -1
  50. package/dist/src/commands/hooks-routing-commands.js.map +1 -1
  51. package/dist/src/commands/init.d.ts.map +1 -1
  52. package/dist/src/commands/init.js +6 -15
  53. package/dist/src/commands/init.js.map +1 -1
  54. package/dist/src/index.js +2 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/init/never-commit.d.ts +3 -3
  57. package/dist/src/init/types.d.ts +1 -1
  58. package/dist/src/init/types.js +1 -1
  59. package/dist/src/knowledge/document-store.js +1 -1
  60. package/dist/src/knowledge/document-store.js.map +1 -1
  61. package/dist/src/mcp-tools/hooks-edit-command.d.ts +10 -0
  62. package/dist/src/mcp-tools/hooks-edit-command.d.ts.map +1 -0
  63. package/dist/src/mcp-tools/hooks-edit-command.js +247 -0
  64. package/dist/src/mcp-tools/hooks-edit-command.js.map +1 -0
  65. package/dist/src/mcp-tools/hooks-learning.d.ts +9 -0
  66. package/dist/src/mcp-tools/hooks-learning.d.ts.map +1 -0
  67. package/dist/src/mcp-tools/hooks-learning.js +408 -0
  68. package/dist/src/mcp-tools/hooks-learning.js.map +1 -0
  69. package/dist/src/mcp-tools/hooks-metrics-list.d.ts +8 -0
  70. package/dist/src/mcp-tools/hooks-metrics-list.d.ts.map +1 -0
  71. package/dist/src/mcp-tools/hooks-metrics-list.js +205 -0
  72. package/dist/src/mcp-tools/hooks-metrics-list.js.map +1 -0
  73. package/dist/src/mcp-tools/hooks-route.d.ts +12 -0
  74. package/dist/src/mcp-tools/hooks-route.d.ts.map +1 -0
  75. package/dist/src/mcp-tools/hooks-route.js +251 -0
  76. package/dist/src/mcp-tools/hooks-route.js.map +1 -0
  77. package/dist/src/mcp-tools/hooks-routing.d.ts +6 -27
  78. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  79. package/dist/src/mcp-tools/hooks-routing.js +6 -1727
  80. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  81. package/dist/src/mcp-tools/hooks-session.d.ts +9 -0
  82. package/dist/src/mcp-tools/hooks-session.d.ts.map +1 -0
  83. package/dist/src/mcp-tools/hooks-session.js +243 -0
  84. package/dist/src/mcp-tools/hooks-session.js.map +1 -0
  85. package/dist/src/mcp-tools/hooks-task.d.ts +17 -0
  86. package/dist/src/mcp-tools/hooks-task.d.ts.map +1 -0
  87. package/dist/src/mcp-tools/hooks-task.js +427 -0
  88. package/dist/src/mcp-tools/hooks-task.js.map +1 -0
  89. package/dist/src/mcp-tools/hooks-tools.d.ts +2 -1
  90. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  91. package/dist/src/mcp-tools/hooks-tools.js +2 -1
  92. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  93. package/dist/src/mcp-tools/memory-tools.js +1 -1
  94. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  95. package/dist/src/memory/bm25-index.d.ts +2 -2
  96. package/dist/src/memory/bm25-index.js +2 -2
  97. package/dist/src/memory/embedding-operations.js +2 -2
  98. package/dist/src/memory/embedding-operations.js.map +1 -1
  99. package/dist/src/memory/entity-name-key.d.ts +1 -1
  100. package/dist/src/memory/entity-name-key.js +1 -1
  101. package/dist/src/memory/hnsw-operations.d.ts +1 -1
  102. package/dist/src/memory/hnsw-operations.js +1 -1
  103. package/dist/src/memory/memory-bridge-backend.d.ts +43 -0
  104. package/dist/src/memory/memory-bridge-backend.d.ts.map +1 -0
  105. package/dist/src/memory/memory-bridge-backend.js +363 -0
  106. package/dist/src/memory/memory-bridge-backend.js.map +1 -0
  107. package/dist/src/memory/memory-bridge-core.d.ts +42 -0
  108. package/dist/src/memory/memory-bridge-core.d.ts.map +1 -0
  109. package/dist/src/memory/memory-bridge-core.js +126 -0
  110. package/dist/src/memory/memory-bridge-core.js.map +1 -0
  111. package/dist/src/memory/memory-bridge-entries.d.ts +131 -0
  112. package/dist/src/memory/memory-bridge-entries.d.ts.map +1 -0
  113. package/dist/src/memory/memory-bridge-entries.js +227 -0
  114. package/dist/src/memory/memory-bridge-entries.js.map +1 -0
  115. package/dist/src/memory/memory-bridge-feedback.d.ts +60 -0
  116. package/dist/src/memory/memory-bridge-feedback.d.ts.map +1 -0
  117. package/dist/src/memory/memory-bridge-feedback.js +118 -0
  118. package/dist/src/memory/memory-bridge-feedback.js.map +1 -0
  119. package/dist/src/memory/memory-bridge-paths.d.ts +123 -0
  120. package/dist/src/memory/memory-bridge-paths.d.ts.map +1 -0
  121. package/dist/src/memory/memory-bridge-paths.js +335 -0
  122. package/dist/src/memory/memory-bridge-paths.js.map +1 -0
  123. package/dist/src/memory/memory-bridge-search.d.ts +48 -0
  124. package/dist/src/memory/memory-bridge-search.d.ts.map +1 -0
  125. package/dist/src/memory/memory-bridge-search.js +383 -0
  126. package/dist/src/memory/memory-bridge-search.js.map +1 -0
  127. package/dist/src/memory/memory-bridge-sessions.d.ts +38 -0
  128. package/dist/src/memory/memory-bridge-sessions.d.ts.map +1 -0
  129. package/dist/src/memory/memory-bridge-sessions.js +109 -0
  130. package/dist/src/memory/memory-bridge-sessions.js.map +1 -0
  131. package/dist/src/memory/memory-bridge-store.d.ts +58 -0
  132. package/dist/src/memory/memory-bridge-store.d.ts.map +1 -0
  133. package/dist/src/memory/memory-bridge-store.js +201 -0
  134. package/dist/src/memory/memory-bridge-store.js.map +1 -0
  135. package/dist/src/memory/memory-bridge.d.ts +10 -438
  136. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  137. package/dist/src/memory/memory-bridge.js +14 -1787
  138. package/dist/src/memory/memory-bridge.js.map +1 -1
  139. package/dist/src/memory/memory-kg-claims.d.ts +52 -0
  140. package/dist/src/memory/memory-kg-claims.d.ts.map +1 -0
  141. package/dist/src/memory/memory-kg-claims.js +99 -0
  142. package/dist/src/memory/memory-kg-claims.js.map +1 -0
  143. package/dist/src/memory/memory-kg-index.d.ts +86 -0
  144. package/dist/src/memory/memory-kg-index.d.ts.map +1 -0
  145. package/dist/src/memory/memory-kg-index.js +256 -0
  146. package/dist/src/memory/memory-kg-index.js.map +1 -0
  147. package/dist/src/memory/memory-kg-ingest.d.ts +44 -0
  148. package/dist/src/memory/memory-kg-ingest.d.ts.map +1 -0
  149. package/dist/src/memory/memory-kg-ingest.js +361 -0
  150. package/dist/src/memory/memory-kg-ingest.js.map +1 -0
  151. package/dist/src/memory/memory-kg-model.d.ts +168 -0
  152. package/dist/src/memory/memory-kg-model.d.ts.map +1 -0
  153. package/dist/src/memory/memory-kg-model.js +158 -0
  154. package/dist/src/memory/memory-kg-model.js.map +1 -0
  155. package/dist/src/memory/memory-kg-names.d.ts +64 -0
  156. package/dist/src/memory/memory-kg-names.d.ts.map +1 -0
  157. package/dist/src/memory/memory-kg-names.js +187 -0
  158. package/dist/src/memory/memory-kg-names.js.map +1 -0
  159. package/dist/src/memory/memory-kg-promote.d.ts +79 -0
  160. package/dist/src/memory/memory-kg-promote.d.ts.map +1 -0
  161. package/dist/src/memory/memory-kg-promote.js +248 -0
  162. package/dist/src/memory/memory-kg-promote.js.map +1 -0
  163. package/dist/src/memory/memory-kg-rebuild.d.ts +77 -0
  164. package/dist/src/memory/memory-kg-rebuild.d.ts.map +1 -0
  165. package/dist/src/memory/memory-kg-rebuild.js +299 -0
  166. package/dist/src/memory/memory-kg-rebuild.js.map +1 -0
  167. package/dist/src/memory/memory-kg-rollback.d.ts +47 -0
  168. package/dist/src/memory/memory-kg-rollback.d.ts.map +1 -0
  169. package/dist/src/memory/memory-kg-rollback.js +193 -0
  170. package/dist/src/memory/memory-kg-rollback.js.map +1 -0
  171. package/dist/src/memory/memory-kg-rules.d.ts +64 -0
  172. package/dist/src/memory/memory-kg-rules.d.ts.map +1 -0
  173. package/dist/src/memory/memory-kg-rules.js +251 -0
  174. package/dist/src/memory/memory-kg-rules.js.map +1 -0
  175. package/dist/src/memory/memory-kg-scan.d.ts +118 -0
  176. package/dist/src/memory/memory-kg-scan.d.ts.map +1 -0
  177. package/dist/src/memory/memory-kg-scan.js +209 -0
  178. package/dist/src/memory/memory-kg-scan.js.map +1 -0
  179. package/dist/src/memory/memory-kg-search.d.ts +80 -0
  180. package/dist/src/memory/memory-kg-search.d.ts.map +1 -0
  181. package/dist/src/memory/memory-kg-search.js +239 -0
  182. package/dist/src/memory/memory-kg-search.js.map +1 -0
  183. package/dist/src/memory/memory-kg.d.ts +19 -547
  184. package/dist/src/memory/memory-kg.d.ts.map +1 -1
  185. package/dist/src/memory/memory-kg.js +10 -2389
  186. package/dist/src/memory/memory-kg.js.map +1 -1
  187. package/dist/src/ui/org-hil.mjs +1 -1
  188. package/dist/src/ui/routes-org-agents.mjs +318 -0
  189. package/dist/src/ui/routes-org-approvals.mjs +133 -0
  190. package/dist/src/ui/routes-org-config.mjs +459 -0
  191. package/dist/src/ui/routes-org-control.mjs +300 -0
  192. package/dist/src/ui/routes-org-files.mjs +172 -0
  193. package/dist/src/ui/routes-org-helpers.mjs +84 -0
  194. package/dist/src/ui/routes-org-knowledge.mjs +262 -0
  195. package/dist/src/ui/routes-org-lifecycle.mjs +224 -0
  196. package/dist/src/ui/routes-org-live.mjs +278 -0
  197. package/dist/src/ui/routes-org-mastermind.mjs +346 -0
  198. package/dist/src/ui/routes-org-planning.mjs +398 -0
  199. package/dist/src/ui/routes-org-runs.mjs +430 -0
  200. package/dist/src/ui/routes-org-status.mjs +342 -0
  201. package/dist/src/ui/routes-org-workflows.mjs +212 -0
  202. package/dist/src/ui/routes-org.mjs +26 -3847
  203. package/dist/src/ui/server.mjs +1 -1
  204. package/dist/src/utils/native-error.d.ts +1 -1
  205. package/dist/src/utils/native-error.js +1 -1
  206. package/dist/src/utils/paths.d.ts +2 -1
  207. package/dist/src/utils/paths.d.ts.map +1 -1
  208. package/dist/src/utils/paths.js +2 -1
  209. package/dist/src/utils/paths.js.map +1 -1
  210. package/dist/tsconfig.tsbuildinfo +1 -1
  211. package/org-skills/adversarial-reviewer/SKILL.md +1 -1
  212. package/org-skills/board-deck-builder/SKILL.md +1 -1
  213. package/org-skills/code-reviewer/SKILL.md +1 -1
  214. package/org-skills/debugging-wizard/SKILL.md +1 -1
  215. package/org-skills/scientific-thinking-literature-review/SKILL.md +1 -1
  216. package/org-skills/scientific-thinking-scholar-evaluation/SKILL.md +1 -1
  217. package/package.json +8 -8
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Memory Knowledge Graph — namespaces, limits, identity (entity/edge/rule
3
+ * keys), the ingest input/result types, and scope (org ownership). Split out
4
+ * of memory-kg.ts, which re-exports the public symbols; see that module's
5
+ * header for the design.
6
+ */
7
+ import { createHash } from 'node:crypto';
8
+ export const KG_NODES_NS = 'kg:nodes';
9
+ export const KG_EDGES_NS = 'kg:edges';
10
+ export const RULES_NS = 'rules';
11
+ /** Name → entity index. Index rows are NOT claims, so they live outside the
12
+ * three claim namespaces: putting them in `kg:nodes` would make them seed
13
+ * candidates for `kgSearch` and rows in `kgStats`. */
14
+ export const KG_NAMES_NS = 'kg:names';
15
+ /** Derived adjacency index namespace (K7). See `KgNamespaces.adj`. */
16
+ export const KG_ADJ_NS = 'kg:adj';
17
+ /** Derived origin-support index namespace (K7). See `KgNamespaces.originIdx`. */
18
+ export const KG_ORIGIN_IDX_NS = 'kg:origin-idx';
19
+ /** Derived-index status namespace (K7). See `KgNamespaces.indexStatus`. */
20
+ export const KG_INDEX_STATUS_NS = 'kg:index-status';
21
+ const MAX_NAME_LEN = 200;
22
+ export const MAX_DESC_LEN = 2000;
23
+ /** Nodes/edges/rules accepted per call. Overflow is REPORTED, never sliced away
24
+ * in silence — see `KgIngestResult.nodesTruncated`. */
25
+ export const MAX_NODES_PER_CALL = 500;
26
+ export const MAX_EDGES_PER_CALL = 1000;
27
+ export const MAX_RULES_PER_CALL = 50;
28
+ /** Per-origin description contributions retained on one element.
29
+ *
30
+ * A cap has to exist — the bridge caps a stored value, and an element asserted
31
+ * by ten thousand runs would otherwise stop being writable. What must NOT
32
+ * happen is the old `origin_refs.slice(-100)`, which dropped the oldest
33
+ * provenance and left the entry claiming complete history. Past this cap the
34
+ * oldest contributions are dropped AND the entry records `origins_dropped`
35
+ * with `provenance_complete: false`, so a reader can tell that a rollback of an
36
+ * old origin may find nothing to withdraw. */
37
+ export const MAX_CLAIMS = 200;
38
+ // ── Identity ────────────────────────────────────────────────────────
39
+ /**
40
+ * Version of the identity scheme implemented by `entityId`/`edgeKey`/`ruleKey`.
41
+ *
42
+ * Bump when a derivation changes. Entries written under an older scheme are not
43
+ * orphaned: resolution probes the previous key shape and adopts the row in
44
+ * place (see `resolveEntity`), so a bump costs a second keyed lookup on the
45
+ * miss path rather than a migration.
46
+ *
47
+ * Version 1 was the name-only scheme (`n:<normalized-name>`, truncated to 200
48
+ * characters), under which `Person:Alex` and `Service:Alex` were one entity and
49
+ * two names first differing at character 250 were one entity.
50
+ */
51
+ export const KG_ID_VERSION = 2;
52
+ /** Identity-grade name normalization: the same folding as `normalizeName` but
53
+ * WITHOUT its 200-character truncation, which silently merged long names that
54
+ * differ only past the cut. `normalizeName` keeps truncating because it feeds
55
+ * tags and display, where length matters and collisions do not. */
56
+ export function canonicalName(name) {
57
+ return String(name).trim().toLowerCase().replace(/['’]/g, '').replace(/\s+/g, '_');
58
+ }
59
+ /** Types that assert nothing. A generic label must not fork an entity away from
60
+ * its typed self, so it maps to the empty discriminator and is resolved by
61
+ * name (see `resolveEntity`). */
62
+ const GENERIC_TYPES = new Set(['', 'entity', 'unknown']);
63
+ /** The identity-bearing part of a type: '' when the caller told us nothing. */
64
+ export function typeBucket(type) {
65
+ const t = canonicalName(type ?? '');
66
+ return GENERIC_TYPES.has(t) ? '' : t;
67
+ }
68
+ /** Hash a tuple injectively: every component is length-prefixed, so no
69
+ * component's content can masquerade as a delimiter or bleed into its
70
+ * neighbour, and no two distinct tuples share an input string. Same discipline
71
+ * as monograph's `symbolId`/`fileId` (packages/@monomind/monograph/src/types.ts),
72
+ * and adopted here for the same reason — the previous scheme lost distinctions
73
+ * to truncation and to an unescaped separator. */
74
+ export function hashTuple(components) {
75
+ const canonical = components.map((c) => `${Buffer.byteLength(c, 'utf8')}:${c}`).join('');
76
+ return createHash('sha256').update(canonical, 'utf8').digest('hex').slice(0, 32);
77
+ }
78
+ /** Mint an entity id from the full identity tuple.
79
+ *
80
+ * This MINTS; it does not RESOLVE. A caller that computes an id and writes to
81
+ * it bypasses the name index and re-forks the entities the index exists to
82
+ * keep together — every ingest path goes through `resolveEntity` instead. */
83
+ export function nodeKey(type, name) {
84
+ return `n:${hashTuple([String(KG_ID_VERSION), typeBucket(type), canonicalName(name)])}`;
85
+ }
86
+ /** The pre-`KG_ID_VERSION` key for a name: name-only, truncated at 200. Probed
87
+ * on a miss so existing graphs keep working without being re-keyed. */
88
+ export function legacyNodeKey(name) {
89
+ return `n:${normalizeName(name)}`;
90
+ }
91
+ /** cognee DataPoint normalization: lowercase, spaces→_, strip apostrophes. */
92
+ export function normalizeName(name) {
93
+ return String(name)
94
+ .trim()
95
+ .toLowerCase()
96
+ .replace(/['’]/g, '')
97
+ .replace(/\s+/g, '_')
98
+ .slice(0, MAX_NAME_LEN);
99
+ }
100
+ /** Edge identity: the endpoint IDs (already collision-free) plus the relation,
101
+ * hashed injectively so a relation containing the old `|` separator can no
102
+ * longer forge a different edge's key. */
103
+ export function edgeKey(srcKey, relation, dstKey) {
104
+ return `e:${hashTuple([String(KG_ID_VERSION), srcKey, canonicalName(relation), dstKey])}`;
105
+ }
106
+ /** The pre-`KG_ID_VERSION` edge key, for the same in-place adoption as
107
+ * `legacyNodeKey`. Composed from the RESOLVED endpoint keys, so it names the
108
+ * legacy edge exactly when both endpoints are themselves legacy rows. */
109
+ export function legacyEdgeKey(srcKey, relation, dstKey) {
110
+ return `e:${srcKey}|${normalizeName(relation)}|${dstKey}`;
111
+ }
112
+ /** Rule identity: the full rule text. The old key truncated the normalized rule
113
+ * at 120 characters, so two rules sharing a long preamble were one rule. */
114
+ export function ruleKey(rule) {
115
+ return `rule:${hashTuple([String(KG_ID_VERSION), canonicalName(rule)])}`;
116
+ }
117
+ export function legacyRuleKey(rule) {
118
+ return `rule:${normalizeName(rule).slice(0, 120)}`;
119
+ }
120
+ /** The namespaces a scope owns. Every read and write in this module resolves
121
+ * through here, which is what makes ownership enforced rather than advisory:
122
+ * there is no code path that reaches an org's facts without naming that org,
123
+ * and none that reaches every org at once. */
124
+ export function kgNamespaces(scope) {
125
+ const org = scope?.org?.trim();
126
+ if (!org)
127
+ return {
128
+ nodes: KG_NODES_NS,
129
+ edges: KG_EDGES_NS,
130
+ rules: RULES_NS,
131
+ names: KG_NAMES_NS,
132
+ adj: KG_ADJ_NS,
133
+ originIdx: KG_ORIGIN_IDX_NS,
134
+ indexStatus: KG_INDEX_STATUS_NS,
135
+ };
136
+ const suffix = `:org:${normalizeName(org)}`;
137
+ return {
138
+ nodes: KG_NODES_NS + suffix,
139
+ edges: KG_EDGES_NS + suffix,
140
+ rules: RULES_NS + suffix,
141
+ names: KG_NAMES_NS + suffix,
142
+ adj: KG_ADJ_NS + suffix,
143
+ originIdx: KG_ORIGIN_IDX_NS + suffix,
144
+ indexStatus: KG_INDEX_STATUS_NS + suffix,
145
+ };
146
+ }
147
+ /** Stamp the asserting org onto a provenance ref, so a claim's origin says WHO
148
+ * asserted it and not merely which run id — `run:m4x2` alone is ambiguous
149
+ * across orgs, and a promoted claim in the shared graph would otherwise carry
150
+ * an origin no one owns.
151
+ *
152
+ * Applied by the ingest/rollback entry points rather than by callers: a
153
+ * caller that forgets is exactly how ownership stopped being enforced. */
154
+ export function kgQualifyOrigin(originRef, scope) {
155
+ const org = scope?.org?.trim();
156
+ return org ? `org:${normalizeName(org)}/${originRef}` : originRef;
157
+ }
158
+ //# sourceMappingURL=memory-kg-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kg-model.js","sourceRoot":"","sources":["../../../src/memory/memory-kg-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Memory Knowledge Graph — the name index and merge index, and entity
3
+ * resolution through them (same-name candidates without name-only
4
+ * identity). Split out of memory-kg.ts, which re-exports the public
5
+ * symbols.
6
+ */
7
+ import type { KgNamespaces } from './memory-kg-model.js';
8
+ import type { FailureLog } from './memory-kg-scan.js';
9
+ /** An entity the name index knows about. */
10
+ export interface KgNameCandidate {
11
+ id: string;
12
+ /** Identity-bearing type bucket; '' for an entity asserted without a type. */
13
+ type: string;
14
+ }
15
+ /** @returns the indexed entities, or null when the backend could not be read.
16
+ *
17
+ * The null is load-bearing: an unreadable index looks exactly like an empty
18
+ * one, and treating a read failure as "no entities with this name" would make
19
+ * the next write REPLACE the row with a single entry, erasing every other
20
+ * same-name entity from the index. A later generic assertion would then see one
21
+ * candidate and adopt it — a silent wrong merge caused by a read hiccup. */
22
+ export declare function readNameIndex(name: string, ns: KgNamespaces, dbPath: string | undefined): Promise<KgNameCandidate[] | null>;
23
+ /** Persist (or clear) the index row for one name.
24
+ *
25
+ * The index is a HINT, not a source of truth: it is written after the entity
26
+ * write lands, and a row that goes stale — pointing at an entity a rollback
27
+ * removed — self-heals, because resolving onto a missing id makes the next
28
+ * ingest create that entity fresh with an empty claim ledger, which is exactly
29
+ * what a new entity is. Nothing reads the index to decide what the graph
30
+ * contains; `kgStats`, `kgSearch` and `kgRollback` all read the claim
31
+ * namespaces. */
32
+ export declare function writeNameIndex(name: string, entities: KgNameCandidate[], ns: KgNamespaces, dbPath: string | undefined, failures: FailureLog): Promise<void>;
33
+ /** What resolving a name against the index produced. */
34
+ interface ResolvedEntity {
35
+ id: string;
36
+ /** Same-name entities this assertion did NOT merge with. Reported, never
37
+ * merged away — "Alex the person" and "Alex the service" are candidates for
38
+ * a human or a consolidation pass to judge, not a merge the graph may do on
39
+ * its own. */
40
+ candidates: KgNameCandidate[];
41
+ /** Index content to persist for this name, or null when it is already
42
+ * correct. Written only after the entity write lands, so a refused write
43
+ * never leaves the index pointing at an entity that does not exist. */
44
+ index: KgNameCandidate[] | null;
45
+ }
46
+ /**
47
+ * Resolve (type, name) to the entity that should carry the assertion.
48
+ *
49
+ * Identity is the (type, name) tuple, so distinct types are distinct entities.
50
+ * The one thing name-only identity got right — a generic label must not fork an
51
+ * entity away from its typed self — is preserved here instead of in the key:
52
+ *
53
+ * - exact type-bucket match → that entity
54
+ * - generic assertion, exactly one same-name entity → adopt it
55
+ * - typed assertion, exactly one same-name entity and it is untyped → adopt it
56
+ * and promote its type (its ID does not change, so references stay valid)
57
+ * - anything else → a new entity, with the alternatives as candidates
58
+ *
59
+ * @returns null when the name index could not be read — the caller must refuse
60
+ * the assertion rather than resolve it against an index it could not see.
61
+ */
62
+ export declare function resolveEntity(name: string, type: string, ns: KgNamespaces, dbPath: string | undefined): Promise<ResolvedEntity | null>;
63
+ export {};
64
+ //# sourceMappingURL=memory-kg-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kg-names.d.ts","sourceRoot":"","sources":["../../../src/memory/memory-kg-names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AASzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;CACd;AAgBD;;;;;;6EAM6E;AAC7E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,CAMnC;AAED;;;;;;;;kBAQkB;AAClB,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,eAAe,EAAE,EAC3B,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAmDD,wDAAwD;AACxD,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX;;;mBAGe;IACf,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B;;4EAEwE;IACxE,KAAK,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA+ChC"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Memory Knowledge Graph — the name index and merge index, and entity
3
+ * resolution through them (same-name candidates without name-only
4
+ * identity). Split out of memory-kg.ts, which re-exports the public
5
+ * symbols.
6
+ */
7
+ import { mergeKey } from './entity-name-key.js';
8
+ import { bridgeDeleteEntry, bridgeGetEntry, bridgeStoreEntry } from './memory-bridge.js';
9
+ import { canonicalName, hashTuple, KG_ID_VERSION, legacyNodeKey, nodeKey, typeBucket, } from './memory-kg-model.js';
10
+ function nameIndexKey(name) {
11
+ return `nm:${hashTuple([String(KG_ID_VERSION), canonicalName(name)])}`;
12
+ }
13
+ /** A coarser, additive index alongside the exact one: bucketed by `mergeKey`
14
+ * (case/separator/plural-insensitive), so "Node.js" and "nodejs" land in the
15
+ * same bucket even though their exact `nameIndexKey`s differ. Purely a hint
16
+ * like the exact index — `resolveEntity` still applies the same (type, name)
17
+ * merge rules to whatever it finds here, so a bucket hit is a candidate,
18
+ * never an automatic cross-type merge. */
19
+ function mergeIndexKey(name) {
20
+ return `nmk:${hashTuple([String(KG_ID_VERSION), mergeKey(name)])}`;
21
+ }
22
+ /** @returns the indexed entities, or null when the backend could not be read.
23
+ *
24
+ * The null is load-bearing: an unreadable index looks exactly like an empty
25
+ * one, and treating a read failure as "no entities with this name" would make
26
+ * the next write REPLACE the row with a single entry, erasing every other
27
+ * same-name entity from the index. A later generic assertion would then see one
28
+ * candidate and adopt it — a silent wrong merge caused by a read hiccup. */
29
+ export async function readNameIndex(name, ns, dbPath) {
30
+ const res = await bridgeGetEntry({ key: nameIndexKey(name), namespace: ns.names, dbPath });
31
+ if (!res)
32
+ return null;
33
+ const raw = res.entry?.metadata?.entities;
34
+ if (!Array.isArray(raw))
35
+ return [];
36
+ return raw.filter((c) => c && typeof c.id === 'string');
37
+ }
38
+ /** Persist (or clear) the index row for one name.
39
+ *
40
+ * The index is a HINT, not a source of truth: it is written after the entity
41
+ * write lands, and a row that goes stale — pointing at an entity a rollback
42
+ * removed — self-heals, because resolving onto a missing id makes the next
43
+ * ingest create that entity fresh with an empty claim ledger, which is exactly
44
+ * what a new entity is. Nothing reads the index to decide what the graph
45
+ * contains; `kgStats`, `kgSearch` and `kgRollback` all read the claim
46
+ * namespaces. */
47
+ export async function writeNameIndex(name, entities, ns, dbPath, failures) {
48
+ const key = nameIndexKey(name);
49
+ if (!entities.length) {
50
+ await bridgeDeleteEntry({ key, namespace: ns.names, dbPath });
51
+ return;
52
+ }
53
+ const res = await bridgeStoreEntry({
54
+ key,
55
+ value: name,
56
+ namespace: ns.names,
57
+ dbPath,
58
+ upsert: true,
59
+ generateEmbeddingFlag: false,
60
+ tags: ['kg', 'name-index'],
61
+ metadata: { kg: 'name', name, entities },
62
+ });
63
+ failures.add(res, `name index ${key}`);
64
+ await writeMergeIndex(name, entities, ns, dbPath, failures);
65
+ }
66
+ /** Add `entities` into the merge-key bucket for `name`, unioned with whatever
67
+ * other exact spellings already sharing that bucket contributed. Additive
68
+ * only — a name written with fewer entities than before (e.g. a rollback's
69
+ * survivor list) never removes another spelling's candidates from the shared
70
+ * bucket. That is a smaller staleness cost than the exact index already
71
+ * accepts, and self-heals the same way: a stale candidate that no longer
72
+ * resolves to a live entity simply is not adopted. */
73
+ async function writeMergeIndex(name, entities, ns, dbPath, failures) {
74
+ const key = mergeIndexKey(name);
75
+ const existing = await bridgeGetEntry({ key, namespace: ns.names, dbPath });
76
+ const prior = existing?.entry?.metadata?.entities;
77
+ const merged = new Map();
78
+ if (Array.isArray(prior))
79
+ for (const c of prior)
80
+ if (c && typeof c.id === 'string')
81
+ merged.set(c.id, c);
82
+ for (const c of entities)
83
+ merged.set(c.id, c);
84
+ const res = await bridgeStoreEntry({
85
+ key,
86
+ value: mergeKey(name),
87
+ namespace: ns.names,
88
+ dbPath,
89
+ upsert: true,
90
+ generateEmbeddingFlag: false,
91
+ tags: ['kg', 'name-merge-index'],
92
+ metadata: { kg: 'name-merge', mergeKey: mergeKey(name), entities: [...merged.values()] },
93
+ });
94
+ failures.add(res, `merge index ${key}`);
95
+ }
96
+ /** @returns candidates from the merge-key bucket, or null on a read failure —
97
+ * same null-is-load-bearing contract as `readNameIndex`. */
98
+ async function readMergeIndex(name, ns, dbPath) {
99
+ const res = await bridgeGetEntry({ key: mergeIndexKey(name), namespace: ns.names, dbPath });
100
+ if (!res)
101
+ return null;
102
+ const raw = res.entry?.metadata?.entities;
103
+ if (!Array.isArray(raw))
104
+ return [];
105
+ return raw.filter((c) => c && typeof c.id === 'string');
106
+ }
107
+ /**
108
+ * Resolve (type, name) to the entity that should carry the assertion.
109
+ *
110
+ * Identity is the (type, name) tuple, so distinct types are distinct entities.
111
+ * The one thing name-only identity got right — a generic label must not fork an
112
+ * entity away from its typed self — is preserved here instead of in the key:
113
+ *
114
+ * - exact type-bucket match → that entity
115
+ * - generic assertion, exactly one same-name entity → adopt it
116
+ * - typed assertion, exactly one same-name entity and it is untyped → adopt it
117
+ * and promote its type (its ID does not change, so references stay valid)
118
+ * - anything else → a new entity, with the alternatives as candidates
119
+ *
120
+ * @returns null when the name index could not be read — the caller must refuse
121
+ * the assertion rather than resolve it against an index it could not see.
122
+ */
123
+ export async function resolveEntity(name, type, ns, dbPath) {
124
+ const bucket = typeBucket(type);
125
+ let known = await readNameIndex(name, ns, dbPath);
126
+ if (known === null)
127
+ return null;
128
+ /** True when the index row already holds exactly `known` — the only case in
129
+ * which an unchanged resolution needs no index write. */
130
+ let indexed = known.length > 0;
131
+ if (!indexed) {
132
+ // Nothing indexed. Before minting, probe the pre-KG_ID_VERSION key: an
133
+ // existing graph's rows are adopted IN PLACE (keeping their key, and so
134
+ // keeping the edges whose keys embed it) rather than re-keyed or orphaned.
135
+ const legacyKey = legacyNodeKey(name);
136
+ const legacy = await bridgeGetEntry({ key: legacyKey, namespace: ns.nodes, dbPath });
137
+ if (legacy?.found && legacy.entry) {
138
+ const md = legacy.entry.metadata;
139
+ known = [{ id: legacyKey, type: typeBucket(typeof md.type === 'string' ? md.type : '') }];
140
+ indexed = false;
141
+ }
142
+ }
143
+ if (!indexed && known.length === 0) {
144
+ // Still nothing under this exact spelling — check for a spelling variant
145
+ // (case, separators, a plain plural) already known under the same
146
+ // merge-key bucket. A hit is only a CANDIDATE: it still goes through the
147
+ // exact/promote/mint rules below, so it can never merge across types.
148
+ const merged = await readMergeIndex(name, ns, dbPath);
149
+ if (merged && merged.length > 0)
150
+ known = merged;
151
+ }
152
+ const exact = known.find((c) => c.type === bucket);
153
+ if (exact)
154
+ return { id: exact.id, candidates: others(known, exact.id), index: indexed ? null : known };
155
+ // A generic assertion adopts the one entity that bears this name; a typed
156
+ // assertion adopts a lone UNTYPED entity and PROMOTES it — same id, so every
157
+ // edge and returned reference to it stays valid. A typed assertion never
158
+ // absorbs a differently-typed entity, and neither adopts when the name is
159
+ // already ambiguous.
160
+ if (known.length === 1 && (!bucket || !known[0].type)) {
161
+ const only = known[0];
162
+ const promoted = { id: only.id, type: bucket || only.type };
163
+ return { id: only.id, candidates: [], index: [promoted] };
164
+ }
165
+ const minted = { id: mintEntityId(type, name, known), type: bucket };
166
+ return { id: minted.id, candidates: known, index: [...known, minted] };
167
+ }
168
+ /** An ID for a new entity that no entity under this name already uses.
169
+ *
170
+ * `nodeKey(type, name)` alone is not sufficient, because promotion decouples
171
+ * an entity's ID from its current type: an entity minted untyped keeps the
172
+ * `''`-bucket ID after a typed assertion promotes it, so a LATER untyped
173
+ * assertion would re-derive that same ID and write its claims into the
174
+ * promoted entity — while simultaneously reporting that entity as one it had
175
+ * "kept separate from". The discriminator is bumped only on collision, so the
176
+ * first entity of a (type, name) still gets exactly `nodeKey(type, name)`. */
177
+ function mintEntityId(type, name, known) {
178
+ const taken = new Set(known.map((c) => c.id));
179
+ let id = nodeKey(type, name);
180
+ for (let n = 1; taken.has(id); n++)
181
+ id = `n:${hashTuple([String(KG_ID_VERSION), typeBucket(type), canonicalName(name), String(n)])}`;
182
+ return id;
183
+ }
184
+ function others(known, id) {
185
+ return known.filter((c) => c.id !== id);
186
+ }
187
+ //# sourceMappingURL=memory-kg-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kg-names.js","sourceRoot":"","sources":["../../../src/memory/memory-kg-names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EACL,aAAa,EACb,SAAS,EACT,aAAa,EACb,aAAa,EACb,OAAO,EACP,UAAU,GACX,MAAM,sBAAsB,CAAC;AAY9B,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACzE,CAAC;AAED;;;;;2CAK2C;AAC3C,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACrE,CAAC;AAED;;;;;;6EAM6E;AAC7E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,EAAgB,EAChB,MAA0B;IAE1B,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3F,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,GAAG,GAAI,GAAG,CAAC,KAAK,EAAE,QAAgD,EAAE,QAAQ,CAAC;IACnF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAQ,GAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;AACjF,CAAC;AAED;;;;;;;;kBAQkB;AAClB,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,QAA2B,EAC3B,EAAgB,EAChB,MAA0B,EAC1B,QAAoB;IAEpB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;QACjC,GAAG;QACH,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,EAAE,CAAC,KAAK;QACnB,MAAM;QACN,MAAM,EAAE,IAAI;QACZ,qBAAqB,EAAE,KAAK;QAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC;QAC1B,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;KACzC,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;uDAMuD;AACvD,KAAK,UAAU,eAAe,CAC5B,IAAY,EACZ,QAA2B,EAC3B,EAAgB,EAChB,MAA0B,EAC1B,QAAoB;IAEpB,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAI,QAAQ,EAAE,KAAK,EAAE,QAAgD,EAAE,QAAQ,CAAC;IAC3F,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAClD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,KAA0B;YACxC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;QACjC,GAAG;QACH,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC;QACrB,SAAS,EAAE,EAAE,CAAC,KAAK;QACnB,MAAM;QACN,MAAM,EAAE,IAAI;QACZ,qBAAqB,EAAE,KAAK;QAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,kBAAkB,CAAC;QAChC,QAAQ,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;KACzF,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,GAAG,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;6DAC6D;AAC7D,KAAK,UAAU,cAAc,CAC3B,IAAY,EACZ,EAAgB,EAChB,MAA0B;IAE1B,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,GAAG,GAAI,GAAG,CAAC,KAAK,EAAE,QAAgD,EAAE,QAAQ,CAAC;IACnF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAQ,GAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;AACjF,CAAC;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,IAAY,EACZ,EAAgB,EAChB,MAA0B;IAE1B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC;8DAC0D;IAC1D,IAAI,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAE/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,uEAAuE;QACvE,wEAAwE;QACxE,2EAA2E;QAC3E,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,QAAmC,CAAC;YAC5D,KAAK,GAAG,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1F,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,yEAAyE;QACzE,kEAAkE;QAClE,yEAAyE;QACzE,sEAAsE;QACtE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,GAAG,MAAM,CAAC;IAClD,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACnD,IAAI,KAAK;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAE9F,0EAA0E;IAC1E,6EAA6E;IAC7E,yEAAyE;IACzE,0EAA0E;IAC1E,qBAAqB;IACrB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5D,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;AACzE,CAAC;AAED;;;;;;;;+EAQ+E;AAC/E,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY,EAAE,KAAwB;IACxE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;QAChC,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnG,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,MAAM,CAAC,KAAwB,EAAE,EAAU;IAClD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Memory Knowledge Graph — graph maintenance reads and moves: kgPromote
3
+ * (org-owned → project-shared, explicit), consolidation candidates, and
4
+ * kgStats. Split out of memory-kg.ts, which re-exports the public symbols.
5
+ */
6
+ import type { KgScope } from './memory-kg-model.js';
7
+ export interface KgPromoteResult {
8
+ success: boolean;
9
+ nodes: number;
10
+ edges: number;
11
+ rules: number;
12
+ /** Origin the shared copy carries, so the promotion can be withdrawn on its
13
+ * own and the shared graph records who shared the claim. */
14
+ promotedAs: string;
15
+ failures?: string[];
16
+ error?: string;
17
+ }
18
+ /** Copy one origin's claims out of an org's scope into project-shared
19
+ * knowledge.
20
+ *
21
+ * Sharing is deliberate, never a side effect of learning: `kgIngest` under a
22
+ * scope only ever writes that org's namespaces, and this is the one path a
23
+ * claim takes across the boundary. The org keeps its own copy untouched — the
24
+ * shared copy is an INDEPENDENT assertion under `promoted:<org-ref>`, so
25
+ * rolling back either side leaves the other standing, and a shared claim
26
+ * always names the org that vouched for it.
27
+ *
28
+ * Like ingest, NOT atomic: the counters report what actually landed. */
29
+ export declare function kgPromote(options: {
30
+ /** The org-side ref to promote, unqualified (e.g. `run:m4x2`). */
31
+ originRef: string;
32
+ /** Owner the claims are promoted FROM. Promoting from the shared scope is a
33
+ * no-op and is refused rather than silently duplicating. */
34
+ from: KgScope;
35
+ dbPath?: string;
36
+ }): Promise<KgPromoteResult>;
37
+ export interface ConsolidationCandidate {
38
+ name: string;
39
+ type: string;
40
+ description: string;
41
+ edgeCount: number;
42
+ /** Neighborhood facts to merge into one canonical description. */
43
+ neighborhood: string[];
44
+ }
45
+ /** Entities whose descriptions are stale relative to their connectivity —
46
+ * the LLM half runs in the LIVE agent: it rewrites each candidate's
47
+ * description from the neighborhood facts and resubmits via memory_kg_ingest.
48
+ * A resubmission is a NEW contribution and therefore the current one, so a
49
+ * shorter but better-supported summary now wins; under "longest description
50
+ * wins" a consolidation that tightened the prose was silently discarded.
51
+ * No LLM here (fully local constraint). */
52
+ export declare function kgConsolidateCandidates(options?: {
53
+ dbPath?: string;
54
+ /** Minimum edges for a node to qualify (default 3). */
55
+ minEdges?: number;
56
+ limit?: number;
57
+ scope?: KgScope;
58
+ }): Promise<ConsolidationCandidate[]>;
59
+ /** Real counts, not page lengths. `bridgeListEntries.total` reports how many
60
+ * rows that one call returned, so the old capped list made a 10,001-node graph
61
+ * report exactly 10,000 forever.
62
+ *
63
+ * Tries a real indexed `SELECT COUNT(*) WHERE namespace = ?` first
64
+ * (`bridgeCountEntries`, K7) — cheap and exact, since every row in a KG
65
+ * namespace is exactly one node/edge/rule (the name index lives in its own
66
+ * namespace). Falls back to the paginated scan — one query per 1,000 rows,
67
+ * still exact — when the loaded bridge predates `bridgeCountEntries`, or a
68
+ * test double doesn't stub it. */
69
+ export declare function kgStats(options?: {
70
+ dbPath?: string;
71
+ /** Whose graph to measure. Counting every org's facts under one org's name
72
+ * is what made `org memory <name> stats` a fiction. */
73
+ scope?: KgScope;
74
+ }): Promise<{
75
+ nodes: number;
76
+ edges: number;
77
+ rules: number;
78
+ }>;
79
+ //# sourceMappingURL=memory-kg-promote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-kg-promote.d.ts","sourceRoot":"","sources":["../../../src/memory/memory-kg-promote.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAA4C,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAc9F,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;iEAC6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;yEAUyE;AACzE,wBAAsB,SAAS,CAAC,OAAO,EAAE;IACvC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB;iEAC6D;IAC7D,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,eAAe,CAAC,CAmI3B;AAID,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;4CAM4C;AAC5C,wBAAsB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CA+CpC;AAID;;;;;;;;;mCASmC;AACnC,wBAAsB,OAAO,CAAC,OAAO,CAAC,EAAE;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;4DACwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB3D"}