omo-memory 0.1.14 → 0.1.15

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.
@@ -1,6 +1,6 @@
1
1
  # Adapter Integration
2
2
 
3
- OMO Memory is the shared local work ledger for OMO adapters. It is host-neutral: lazycodex, omo-on-opencode, lfg, and future adapters all write summaries, decisions, QA evidence, task state, and handoffs to the same project-local SQLite database at `<project-root>/.omo/memory/state.sqlite` by default.
3
+ OMO Memory is the shared local session/work/event ledger for OMO adapters. It is host-neutral: lazycodex, omo-on-opencode, lfg, and future adapters all write summaries, decisions, QA evidence, task state, and handoffs to the same project-local SQLite database at `<project-root>/.omo/memory/state.sqlite` by default.
4
4
 
5
5
  No full transcript capture by default. Do not store API keys, tokens, `.env` contents, auth files, raw tool logs, auth headers, cookies, or any other secret-bearing material.
6
6
 
@@ -118,7 +118,7 @@ During the session, hooks should write concise user-action summaries, task state
118
118
  }
119
119
  ```
120
120
 
121
- This package is the local MCP-to-SQLite router. It does not scrape host transcripts, store assistant output, or centralize cloud state. Hosts and adapters must call the MCP tools at their own lifecycle points.
121
+ This package is the local MCP-to-SQLite router. It does not scrape host transcripts, store assistant output, or centralize cloud state. Hosts and adapters must call the MCP tools at their own integration points.
122
122
 
123
123
  Retrieval is opt-in or intent-gated:
124
124
 
@@ -142,51 +142,28 @@ Use these tools:
142
142
  - `memory_global_scan`
143
143
  - `memory_global_migrate`
144
144
  - `memory_global_list`
145
- - `memory_ontology_candidates`
146
- - `memory_ontology_extract`
147
- - `memory_ontology_score`
148
- - `memory_ontology_promote`
149
- - `memory_ontology_demote`
150
- - `memory_ontology_supersede`
151
- - `memory_ontology_recall`
145
+
152
146
 
153
147
  CLI updates: normal CLI commands automatically launch a quiet background `npm install -g omo-memory@latest` at most once per day. MCP startup intentionally does not auto-update because stdout/stderr must remain reserved for the protocol. Hosts that need pinned installs should set `OMO_MEMORY_AUTO_UPDATE=0` in the CLI environment.
154
148
 
155
- Global migration is copy/import only. Adapters may scan for existing project-local `.omo/memory/state.sqlite` databases and import them into a user-selected global SQLite file, but they must preserve source DBs and retain source provenance in the global store.
149
+ Global migration is copy/import only. Adapters may scan for existing project-local `.omo/memory/state.sqlite` databases and import their event/session/handoff ledgers into a user-selected global SQLite file, but they must preserve source DBs and retain source provenance in the global store.
156
150
 
157
- Global migration also materializes an aggregate OMO schema view inside the global SQLite file. This lets existing ontology extraction, retention scoring, recall, and OpenTUI graph code operate on integrated cross-project events while `global_*` tables retain source database provenance.
151
+ Global import is an event-log surface, not an ontology, graph, concept-extraction, retention-scoring, or curated durable-memory layer.
158
152
 
159
- Example global second-brain flow:
153
+ Example global event import flow:
160
154
 
161
155
  ```sh
162
156
  omo-memory global scan --root /Users/ilseoblee/workspace
163
157
  omo-memory global migrate --root /Users/ilseoblee/workspace --global-db ~/.omo/memory/global.sqlite
164
- OMO_MEMORY_DB=~/.omo/memory/global.sqlite omo-memory ontology candidates
165
- OMO_MEMORY_DB=~/.omo/memory/global.sqlite omo-memory ontology score
166
- bun --version
167
- omo-memory graph tui --db ~/.omo/memory/global.sqlite --query linaforge
158
+ omo-memory global list --global-db ~/.omo/memory/global.sqlite
159
+ OMO_MEMORY_DB=~/.omo/memory/global.sqlite omo-memory recall --query linaforge
168
160
  ```
169
161
 
170
- `graph tui` requires `bun` on `PATH` for the OpenTUI terminal renderer. Other CLI and MCP commands run on Node.
171
-
172
- Lifecycle commands:
173
-
174
- - `memory_ontology_candidates`: derive candidate terms from concise summaries.
175
- - `memory_ontology_extract`: explicitly extract candidates from one summary/event.
176
- - `memory_ontology_score`: recompute deterministic scores and retention classes.
177
- - `memory_ontology_promote`: curate a concept into durable memory.
178
- - `memory_ontology_demote`: lower a durable memory's retention class.
179
- - `memory_ontology_supersede`: preserve the old memory and create a replacement.
180
- - `memory_ontology_recall`: retrieve ontology-backed memories only for an explicit query.
162
+ Unavailable surfaces:
181
163
 
182
- OpenTUI graph controls:
183
-
184
- - `q`: quit.
185
- - `Up` / `Down`: move selected concept.
186
- - `Tab`: move to the next concept.
187
- - `/` or `f`: focus filter input when supported by the terminal runtime.
188
-
189
- The graph UI is local terminal UI. It does not require a browser, web server, cloud account, or vector service.
164
+ - `memory_ontology_*` MCP tools are absent.
165
+ - `omo-memory ontology ...` CLI commands are unknown.
166
+ - `omo-memory graph tui` is unknown.
190
167
 
191
168
  Example session start:
192
169
 
@@ -218,59 +195,10 @@ Example QA evidence:
218
195
  - Do not read or record `.env`, auth files, tokens, cookies, API keys, bearer headers, or raw secret-bearing logs.
219
196
  - Store sanitized summaries and evidence references instead of full logs.
220
197
  - Host-specific values may appear only in small redacted metadata payloads and must not require schema branches.
221
- - Export and purge are explicit lifecycle commands; purge requires explicit confirmation.
222
-
223
- ## Ontology Schema Boundary
224
-
225
- OMO Memory's chronological ledger remains authoritative: sessions, events, and handoffs record what happened in a project. The ontology schema is an additive layer for durable memory derived from that ledger:
226
-
227
- - `concepts` stores vocabulary entries such as project terms, practices, tools, and recurring ideas.
228
- - `relations` stores typed links between concepts, decisions, events, sessions, and handoffs.
229
- - `durable_memories` stores approved long-term facts, preferences, and working rules.
230
- - `decision_records` stores important choices with rationale, evidence, status, reversibility, and provenance.
231
-
232
- Adapters must treat ontology rows as curated local memory, not as raw capture. Do not write full transcripts, raw logs, `.env` contents, auth files, cookies, bearer headers, or secret-bearing payloads into ontology tables. User-authored text must pass through the same redaction boundary used by event and handoff writes before it is promoted into durable memory.
233
-
234
- The ontology layer is intentionally not a new adapter surface by itself. CLI and MCP commands should continue to call shared core functions, and future concept/decision commands must not create host-specific schemas or side databases.
235
-
236
- ## Retention Scoring Policy (Deterministic Contract)
237
-
238
- Retention classification is strictly deterministic. There is no ML, embeddings, or hidden model. A pure function maps explicit signals to a numeric score and then to one of five classes.
239
-
240
- Classes (in ascending durability):
241
-
242
- - `forget`: score < 30 (or after decay/contradiction). Safe to drop.
243
- - `temporary`: 30 <= score < 50. Short-term context only.
244
- - `working`: 50 <= score < 75. Active task/iteration memory.
245
- - `durable`: 75 <= score < 90. Cross-session value; survives typical decay.
246
- - `permanent`: score >= 90, or any manually pinned item. Manual pin is a hard override.
247
-
248
- Manual pin rule (critical): an item with `manualPin: true` is always classified `permanent` regardless of raw score, age, or frequency. Decay jobs and age-based expiration MUST NOT remove or downgrade pinned permanent memory; only explicit supersede/demote/purge may change it.
249
-
250
- ### Score Formula (pure, exposed)
251
-
252
- Exported constants (see `src/retentionPolicy.ts`):
253
-
254
- - `RETENTION_CLASSES = ["forget", "temporary", "working", "durable", "permanent"] as const`
255
- - `RETENTION_THRESHOLDS = { forget: 0, temporary: 30, working: 50, durable: 75, permanent: 90 } as const`
256
- - `RETENTION_WEIGHTS = { frequency: 4.5, spread: 7, decision: 12, qa: 10, relation: 4, confidence: 10, recencyBase: 18, recencyPerDay: 0.55, agePerDay: 0.12, ageCap: 22, contradiction: 9 } as const`
257
-
258
- ```
259
- score = clamp(
260
- frequency * 4.5
261
- + spread * 7
262
- + decisionWeight * 12
263
- + qaWeight * 10
264
- + relationDegree * 4
265
- + confidence * 10
266
- + max(0, 18 - recencyDays * 0.55)
267
- - min(22, ageDays * 0.12)
268
- - contradictionCount * 9
269
- , 0, 110)
270
- ```
198
+ - Export and purge are explicit local data commands; purge requires explicit confirmation.
271
199
 
272
- `computeRetentionScore(input)` returns the rounded integer. `classifyRetention(score, manualPin)` returns the class, applying the pin override first.
200
+ ## Ledger Boundary
273
201
 
274
- Boundary cases (score, pin=false): 29→forget, 30→temporary, 49→temporary, 50→working, 74→working, 75→durable, 89→durable, 90→permanent. These are verified by the focused contract test.
202
+ OMO Memory's chronological ledger is authoritative: sessions, events, and handoffs record what happened in a project. Adapters should write concise summaries and evidence references to that ledger, then use explicit `recent`, `recall`, `handoff`, `export`, `purge`, and global event import/list operations.
275
203
 
276
- All scoring inputs are derived from ledger signals (event counts, last-seen deltas, project spread from index, decision/qa event types, explicit relation degree, stored confidence, manual pin flag, contradiction markers). No raw transcripts or secrets are inputs.
204
+ OMO Memory does not provide automatic ontology extraction, graph visualization, retention scoring, durable-memory promotion, or OpenTUI workflows. Do not build adapter behavior that depends on those unavailable surfaces.
@@ -1,12 +1,12 @@
1
- # Epic: OMO Memory — shared local second-brain DB for OMO adapters
1
+ # Epic: OMO Memory — shared local session/work ledger for OMO adapters
2
2
 
3
3
  ## Goal
4
4
 
5
- Build a host-neutral local memory layer for OMO so lazycodex, omo-on-opencode, lfg, and future adapters can share task context, durable decisions, and ontology-backed project knowledge across coding-tool sessions.
5
+ Build a host-neutral local memory layer for OMO so lazycodex, omo-on-opencode, lfg, and future adapters can share task context, recorded decisions, QA evidence, event history, and handoffs across coding-tool sessions.
6
6
 
7
7
  The product ships as both:
8
8
 
9
- - CLI: install, inspect, global migration, ontology lifecycle, graph, search, export, purge, and handoff operations.
9
+ - CLI: install, inspect, global event import, search, export, purge, and handoff operations.
10
10
  - MCP server: standard stdio tools for agents and coding tools to explicitly read/write OMO memory.
11
11
 
12
12
  ## Problem
@@ -23,7 +23,7 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
23
23
  - Local-first privacy: no cloud sync and no secret storage by default
24
24
  - Adapter-neutral schema: `host` and `adapter` are metadata, not separate products
25
25
  - Shared API: CLI and MCP use the same core DB layer
26
- - Second-brain lifecycle: candidate extraction, deterministic retention scoring, promotion, demotion, supersession, explicit recall, and OpenTUI graph inspection
26
+ - Explicit recall only: no automatic prompt injection, ontology extraction, graph TUI, concept extraction, retention scoring, or durable-memory lifecycle.
27
27
 
28
28
  ## In scope
29
29
 
@@ -32,6 +32,7 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
32
32
  - `init`
33
33
  - `global scan`
34
34
  - `global migrate`
35
+ - `global list`
35
36
  - `session start`
36
37
  - `session bootstrap`
37
38
  - `event record`
@@ -39,13 +40,9 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
39
40
  - `recall`
40
41
  - `handoff write`
41
42
  - `doctor`
42
- - `ontology candidates`
43
- - `ontology score`
44
- - `ontology promote`
45
- - `ontology demote`
46
- - `ontology supersede`
47
- - `ontology recall`
48
- - `graph tui`
43
+ - `export`
44
+ - `purge`
45
+
49
46
  - MCP stdio server with tools:
50
47
  - `memory_init`
51
48
  - `memory_project_context`
@@ -58,24 +55,15 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
58
55
  - `memory_global_scan`
59
56
  - `memory_global_migrate`
60
57
  - `memory_global_list`
61
- - `memory_ontology_candidates`
62
- - `memory_ontology_extract`
63
- - `memory_ontology_score`
64
- - `memory_ontology_promote`
65
- - `memory_ontology_demote`
66
- - `memory_ontology_supersede`
67
- - `memory_ontology_recall`
58
+ - `memory_export`
59
+ - `memory_purge`
60
+
68
61
  - Privacy guardrails:
69
62
  - local-only default
70
63
  - no API key/token/env capture
71
64
  - explicit purge/export commands
72
65
  - Adapter integration notes for lazycodex, omo-on-opencode, and lfg
73
- - Retention classes:
74
- - `forget`: safe to drop after low score or decay
75
- - `temporary`: short-term task context
76
- - `working`: active project memory
77
- - `durable`: cross-session knowledge
78
- - `permanent`: manual-pin or high-score knowledge; only explicit demote/supersede/purge changes it
66
+ - Cross-project event import with source provenance through user-selected global SQLite files.
79
67
 
80
68
  ## Out of scope
81
69
 
@@ -83,7 +71,9 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
83
71
  - Team sharing by default
84
72
  - Full transcript capture by default
85
73
  - Vector/embedding search in MVP
86
- - Browser-only graph UI
74
+ - Ontology/concept extraction
75
+ - Graph UI, graph TUI, and OpenTUI
76
+ - Retention scoring or durable-memory curation lifecycle
87
77
  - Automatic prompt injection from the last session
88
78
  - Replacing codegraph
89
79
  - Host-specific private APIs as required dependencies
@@ -95,21 +85,22 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
95
85
  - `omo-memory init` creates or migrates `<project-root>/.omo/memory/state.sqlite`.
96
86
  - `omo-memory global scan --root <path>` discovers project-local OMO DBs and reports schema versions.
97
87
  - `omo-memory global migrate --root <path> --global-db <path>` copies source DB data into one global SQLite file without mutating source DBs.
88
+ - `omo-memory global list --global-db <path>` lists imported global event history with source provenance.
98
89
  - `omo-memory session start --host grok --adapter lfg` records a session for the current project.
99
90
  - `omo-memory session bootstrap --host codex --adapter lazycodex` returns a session id and project metadata without injecting recent events.
100
91
  - `omo-memory event record --type decision --summary "..."` appends a project/session event.
101
92
  - `omo-memory recent` lists recent project events.
102
93
  - `omo-memory recall --query "..."` performs explicit query-gated event recall.
103
94
  - `omo-memory handoff write --summary-file path.md` stores a handoff summary.
104
- - `omo-memory ontology candidates` extracts vocabulary candidates from concise summaries.
105
- - `omo-memory ontology score` recomputes deterministic retention classes.
106
- - `omo-memory ontology promote/demote/supersede/recall` supports curated durable memory lifecycle.
107
- - `omo-memory graph tui --db <path> --query <term>` opens an OpenTUI graph with `q` quit, arrow/tab selection, retention class, score, provenance, and detail pane. It requires `bun` on `PATH`; other CLI and MCP commands run on Node.
95
+ - `omo-memory doctor` reports DB path, schema version, and project identity.
96
+ - `omo-memory export` writes explicit local ledger export data.
97
+ - `omo-memory purge --yes` removes local ledger data only after explicit confirmation.
98
+
108
99
 
109
100
  ### MCP
110
101
 
111
102
  - `omo-memory mcp` starts a stdio MCP server.
112
- - MCP tools can initialize the DB, read project context, record events, list/retrieve explicit memory, write handoffs, migrate global memory, and manage ontology lifecycle.
103
+ - MCP tools can initialize the DB, read project context, record events, list/retrieve explicit memory, write handoffs, export/purge local data, and scan/import/list global event memory.
113
104
  - MCP tool responses are structured JSON text.
114
105
  - `memory_bootstrap_session` remains write-only/session-only and does not return `recentEvents`.
115
106
 
@@ -119,25 +110,14 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
119
110
  - DB path can be overridden only by explicit `OMO_MEMORY_DB`.
120
111
  - `doctor` reports DB path, schema version, and project identity without leaking sensitive values.
121
112
  - Global migration is copy/import only; source project DB mtimes and row counts must remain unchanged.
122
- - Graph and recall are local-first and explicit; no cloud sync, browser server, raw transcript capture, or embeddings are required.
113
+ - Recall is local-first and explicit; no cloud sync, browser server, raw transcript capture, ontology extraction, graph UI, OpenTUI, retention scoring, durable-memory curation, or embeddings are required.
123
114
 
124
115
  ### QA evidence
125
116
 
126
- - `npm run typecheck`
127
- - `npm run build`
128
- - `npm run check`
129
- - CLI smoke:
130
- - `node dist/cli.js init`
131
- - `node dist/cli.js global scan --root <tmp-workspace>`
132
- - `node dist/cli.js global migrate --root <tmp-workspace> --global-db <tmp-global.sqlite>`
133
- - `node dist/cli.js session start --host grok --adapter lfg`
134
- - `node dist/cli.js event record --type decision --summary "smoke"`
135
- - `node dist/cli.js ontology candidates`
136
- - `node dist/cli.js ontology score`
137
- - `bun dist/cli.js graph tui --db <tmp-db> --query smoke`
138
- - `node dist/cli.js recent`
139
- - MCP smoke: start `node dist/cli.js mcp` and verify `tools/list` includes memory tools.
140
- - Backfill verifier: synthetic Linaforge/omo-memory/lfg/omo-phone DB replicas plus read-only scan of real local DB paths.
117
+ - Focused CLI smoke covers init, global scan/migrate/list, session start/bootstrap, event record, recent, recall, handoff write, export, and purge.
118
+ - MCP smoke verifies `tools/list` includes the core `memory_*` ledger tools plus `memory_global_scan`, `memory_global_migrate`, and `memory_global_list`, and excludes `memory_ontology_*`.
119
+ - Global import smoke verifies source project DBs are copied/imported with provenance and not mutated.
120
+ - Documentation review verifies removed ontology, graph TUI/OpenTUI, concept extraction, retention scoring, and durable-memory curation surfaces are not documented as shipped features.
141
121
 
142
122
  ## Follow-up issue breakdown
143
123
 
@@ -147,8 +127,6 @@ Codegraph solves code intelligence, not work/session memory. OMO needs a separat
147
127
  4. Project identity and git metadata
148
128
  5. Privacy/redaction/purge/export
149
129
  6. Global SQLite migration and source provenance
150
- 7. Deterministic ontology extraction and retention scoring
151
- 8. Durable memory promote/demote/supersede lifecycle
152
- 9. OpenTUI graph visualization
153
- 10. Adapter integration docs for lazycodex, omo-on-opencode, and lfg
154
- 11. QA harness for CLI, MCP, global backfill, and TUI smoke tests
130
+ 7. Adapter integration docs for lazycodex, omo-on-opencode, and lfg
131
+ 8. QA harness for CLI, MCP, and global import smoke tests
132
+ 9. Removal verification for ontology, graph TUI/OpenTUI, concept extraction, retention scoring, and durable-memory curation docs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omo-memory",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Host-neutral local SQLite memory and session ledger for OMO adapters, exposed through CLI and MCP.",
5
5
  "type": "module",
6
6
  "files": [
@@ -33,16 +33,16 @@
33
33
  "start": "node dist/cli.js",
34
34
  "prepack": "npm run build",
35
35
  "presmoke": "npm run build",
36
- "smoke": "npm run smoke:cli && npm run smoke:mcp && npm run smoke:hook",
36
+ "smoke": "npm run smoke:cli && npm run smoke:mcp && npm run smoke:hook && npm run smoke:legacy",
37
37
  "smoke:cli": "node scripts/smoke-cli.mjs",
38
38
  "smoke:mcp": "node scripts/smoke-mcp.mjs",
39
39
  "smoke:hook": "node scripts/verify-user-prompt-hook.mjs",
40
+ "smoke:legacy": "node scripts/verify-legacy-schema-compat.mjs",
40
41
  "mcp": "node dist/cli.js mcp",
41
42
  "issue:epic": "node scripts/create-epic-issue.mjs"
42
43
  },
43
44
  "dependencies": {
44
45
  "@modelcontextprotocol/sdk": "^1.29.0",
45
- "@opentui/core": "0.4.2",
46
46
  "better-sqlite3": "^12.11.1",
47
47
  "zod": "^4.4.3"
48
48
  },
@@ -1,188 +0,0 @@
1
- import { recordMemoryReference, upsertConcept } from "./ontologyCore.js";
2
- import { redactSecrets } from "./privacy.js";
3
- // Comprehensive generic/hook stopwords. Keep domain terms out.
4
- const STOPWORDS = new Set([
5
- // from recall + hook words
6
- "action",
7
- "asked",
8
- "current",
9
- "help",
10
- "memory",
11
- "need",
12
- "needs",
13
- "omo",
14
- "please",
15
- "prompt",
16
- "request",
17
- "requested",
18
- "session",
19
- "user",
20
- "want",
21
- "wants",
22
- "work",
23
- "working",
24
- // common English + dev noise
25
- "the",
26
- "and",
27
- "for",
28
- "with",
29
- "from",
30
- "into",
31
- "about",
32
- "this",
33
- "that",
34
- "these",
35
- "those",
36
- "start",
37
- "now",
38
- "test",
39
- "run",
40
- "check",
41
- "fix",
42
- "add",
43
- "change",
44
- "update",
45
- "get",
46
- "set",
47
- "make",
48
- "create",
49
- "delete",
50
- "remove",
51
- "show",
52
- "list",
53
- "use",
54
- "using",
55
- "via",
56
- "task",
57
- "todo",
58
- "step",
59
- "item",
60
- "thing",
61
- "stuff",
62
- "new",
63
- "old",
64
- "one",
65
- "two",
66
- "three",
67
- "four",
68
- "five",
69
- "six",
70
- "seven",
71
- "eight",
72
- "nine",
73
- "ten",
74
- "please",
75
- "thanks",
76
- "thank",
77
- "also",
78
- "just",
79
- "only",
80
- "like",
81
- "such",
82
- "very",
83
- "really",
84
- "should",
85
- "could",
86
- "would",
87
- "will",
88
- "can",
89
- "may",
90
- "must",
91
- "have",
92
- "has",
93
- "had",
94
- "been",
95
- "being",
96
- "are",
97
- "was",
98
- "were",
99
- "is",
100
- "be",
101
- "to",
102
- "of",
103
- "in",
104
- "on",
105
- "at",
106
- "by",
107
- "as",
108
- "it",
109
- "its",
110
- "if",
111
- "or",
112
- "and",
113
- "but",
114
- "not",
115
- "no",
116
- "yes",
117
- "all",
118
- "any",
119
- "each",
120
- "few",
121
- "more",
122
- "most",
123
- "other",
124
- "some",
125
- "such",
126
- "than",
127
- "too",
128
- "very",
129
- ]);
130
- function normalizeLabel(raw) {
131
- return raw.trim().toLowerCase();
132
- }
133
- function tokenize(input) {
134
- // Preserve hyphenated compounds (local-first), keep alnum _ -
135
- const cleaned = input
136
- .toLowerCase()
137
- .replace(/[^a-z0-9_\-\s]/g, " ")
138
- .replace(/\s+/g, " ")
139
- .trim();
140
- if (!cleaned)
141
- return [];
142
- return cleaned.split(" ").filter((t) => t.length >= 3);
143
- }
144
- export function extractConceptCandidates(summary, _eventType) {
145
- if (!summary || typeof summary !== "string")
146
- return [];
147
- // Never operate on large blobs: caller must pass short summary only.
148
- const redacted = redactSecrets(summary);
149
- const tokens = tokenize(redacted);
150
- const seen = new Set();
151
- const out = [];
152
- for (const t of tokens) {
153
- if (STOPWORDS.has(t))
154
- continue;
155
- const norm = normalizeLabel(t);
156
- if (norm.length < 3)
157
- continue;
158
- if (seen.has(norm))
159
- continue;
160
- seen.add(norm);
161
- out.push(norm);
162
- }
163
- return out;
164
- }
165
- export function applyConceptExtraction(dbPath, project, sourceEventId, summary, eventType) {
166
- const candidates = extractConceptCandidates(summary, eventType);
167
- const concepts = [];
168
- const references = [];
169
- for (const label of candidates) {
170
- // upsertConcept will be made idempotent + bump ref_count by label
171
- const concept = upsertConcept(dbPath, project, {
172
- kind: "term",
173
- label,
174
- // score/retention left to scorer (Todo 6); default working
175
- });
176
- concepts.push(concept);
177
- const ref = recordMemoryReference(dbPath, project, {
178
- sourceType: "event",
179
- sourceId: sourceEventId,
180
- targetType: "concept",
181
- targetId: concept.id,
182
- refKind: "mentions",
183
- weight: 1,
184
- });
185
- references.push(ref);
186
- }
187
- return { concepts, references };
188
- }