suemo 0.1.3 → 0.1.6

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.
package/README.md CHANGED
@@ -52,6 +52,7 @@ For suemo, the critical capability is allowing custom functions:
52
52
  - `search::*` (for `search::score`)
53
53
  - `math::*` (for `math::mean`, `math::min`)
54
54
  - `rand::*` (used in `wander` query)
55
+ - `array::*` (used in `recall` query)
55
56
 
56
57
  If you run with strict capability mode, use an allowlist like:
57
58
 
@@ -138,7 +139,7 @@ What these commands do:
138
139
  - `suemo init fastembed`
139
140
  - checks `python-fastembed`, `python-fastapi`, `python-uvicorn` via `pacman -Q`
140
141
  - installs `data/fastembed-server.py` to `/opt/suemo/fastembed-server.py`
141
- - creates `/opt/fastembed/local.env` once (user override file; not overwritten)
142
+ - creates `/opt/suemo/fastembed/local.env` once (user override file; not overwritten)
142
143
  - writes `/etc/systemd/system/suemo-fastembed.service`
143
144
  - enables + starts `suemo-fastembed.service`
144
145
 
@@ -169,6 +170,40 @@ suemo observe "Bun is significantly faster than Node for CLI tools" \
169
170
  suemo query "which JS runtime is faster"
170
171
  ```
171
172
 
173
+ To inspect ranking/scoring internals:
174
+
175
+ ```sh
176
+ suemo query "which JS runtime is faster" --explain
177
+ suemo query "which JS runtime is faster" --explain --min-score 0.15 --relative-floor 0.75
178
+ ```
179
+
180
+ `--explain` shows per-strategy contributions (vector/BM25/graph), final score, and applied thresholds.
181
+
182
+ ### How query scoring works
183
+
184
+ `suemo query` computes a hybrid score per candidate and then applies score gates.
185
+
186
+ 1. **Per-strategy raw scores**
187
+ - vector: cosine similarity between memory embedding and query embedding
188
+ - bm25: `search::score(1)` from full-text index
189
+ - graph: anchor-weighted relation strength from top vector anchors
190
+
191
+ 2. **Normalization**
192
+ - `vector_norm = clamp((cosine - 0.2) / 0.8, 0, 1)`
193
+ - `bm25_norm = log1p(raw_bm25) / log1p(max_bm25_in_query)`
194
+ - `graph_norm = clamp(raw_graph, 0, 1)`
195
+
196
+ 3. **Final score**
197
+ - `final = 0.5*vector_norm + 0.25*bm25_norm + 0.15*graph_norm + agreement_bonus`
198
+ - `agreement_bonus = 0.05` when a node matches at least two strategies
199
+
200
+ 4. **Default gates (to reduce false positives)**
201
+ - `final >= 0.08` (`--min-score`)
202
+ - `final >= topScore * 0.65` (`--relative-floor`)
203
+ - `max(vector_norm, bm25_norm) >= 0.08` (primary evidence floor)
204
+
205
+ Use `--explain` to inspect all these values per result.
206
+
172
207
  **5. Start the MCP server**
173
208
 
174
209
  ```sh
@@ -188,25 +223,31 @@ suemo serve --dev
188
223
 
189
224
  ## OpenCode setup (only integration target)
190
225
 
191
- Print copy-paste setup snippets:
226
+ Create/update integration files automatically:
192
227
 
193
228
  ```sh
194
229
  suemo init opencode
195
230
  ```
196
231
 
197
- This prints:
232
+ This updates:
198
233
 
199
- - MCP config snippet (`command: suemo`, `args: ["serve", "--stdio", ...]`)
200
- - minimal AGENTS.md guidance snippet
234
+ - `~/.config/opencode/opencode.jsonc` (preferred) or `.json` fallback with `mcp.suemo`
235
+ - `~/.config/opencode/AGENTS.md` with managed `<!-- SUEMO:START --> ... <!-- SUEMO:END -->` block
236
+
237
+ Preview changes without writing files:
238
+
239
+ ```sh
240
+ suemo init opencode --dry-run
241
+ ```
201
242
 
202
- To fetch the latest skill docs directly from your local checkout:
243
+ To fetch latest skill docs directly from your local checkout:
203
244
 
204
245
  ```sh
205
246
  suemo skill
206
247
  suemo skill core-workflow
207
248
  ```
208
249
 
209
- No files are auto-written by this command.
250
+ This command is idempotent and avoids duplicate `mcp.suemo` entries.
210
251
 
211
252
  ---
212
253
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suemo",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "Persistent semantic memory for AI agents — backed by SurrealDB.",
5
5
  "author": {
6
6
  "name": "Umar Alfarouk",
@@ -3,7 +3,7 @@ name: suemo
3
3
  description: OpenCode-focused persistent memory workflow for suemo with CLI/MCP parity and versioned references.
4
4
  license: GPL-3.0-only
5
5
  compatibility: opencode
6
- version: 0.1.2
6
+ version: 0.1.6
7
7
  ---
8
8
 
9
9
  # suemo skill
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agents-snippet
3
3
  description: AGENTS.md snippet optimized for suemo skill discovery and usage.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # AGENTS.md snippet
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: cli-reference
3
3
  description: CLI command reference for suemo v0.0.6 including skill access.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # CLI reference
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: core-workflow
3
3
  description: Canonical suemo operating loop for OpenCode agents.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # Core workflow
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: manual-test-plan
3
3
  description: Comprehensive manual test matrix for suemo features and commands.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # Manual test plan
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: mcp-reference
3
3
  description: MCP tool reference for suemo v0.0.6.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # MCP tools
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: schema-retention-longevity
3
3
  description: Long-term schema and retention design expectations for suemo.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # Schema + retention longevity
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sync-local-vps
3
3
  description: Two-way sync manual scenario for local and VPS SurrealDB.
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  ---
6
6
 
7
7
  # Local ↔ VPS sync scenario
package/src/AGENTS.md ADDED
@@ -0,0 +1,150 @@
1
+ # Working with suemo
2
+
3
+ suemo is your persistent memory. Use it to store what you learn, remember what matters, and build on past work.
4
+
5
+ ## Before anything else
6
+
7
+ **Load the skill doc first.** It is versioned and may contain updated workflows, references, and tool signatures that supersede this file.
8
+
9
+ - CLI: `suemo skill`
10
+ - MCP: `skill({})`
11
+
12
+ For a specific reference: `suemo skill <reference-name>` / `skill({ reference: "<reference-name>" })`
13
+
14
+ Available references: `agents-snippet`, `cli-reference`, `core-workflow`, `manual-test-plan`, `mcp-reference`, `schema-retention-longevity`, `sync-local-vps`
15
+
16
+ Do not proceed until the skill doc is loaded.
17
+
18
+ ## Session protocol
19
+
20
+ These steps are **mandatory**, not suggested.
21
+
22
+ ### On session start
23
+
24
+ ```
25
+ goal_list(scope: "<active-scope>")
26
+ query("recent work on [topic]", scope: "<active-scope>")
27
+ ```
28
+
29
+ Read relevant results before touching any code. Do not re-derive what is already stored.
30
+
31
+ ### While working
32
+
33
+ Store anything that would save time next session:
34
+
35
+ ```
36
+ observe("[fact you learned or confirmed]")
37
+ believe("[interpretation or conclusion that might change]")
38
+ ```
39
+
40
+ Query only when you are **genuinely blocked** or starting a distinct new subtask. Do not query on every step — it burns context and adds noise.
41
+
42
+ ### Before ending (or if interrupted)
43
+
44
+ Call this **before** your final tool invocation, not after — sessions can be cut off without warning:
45
+
46
+ ```
47
+ episode_end(<session_id>, summary="<one sentence of what was accomplished>")
48
+ goal_resolve(<goal_id>) # only if the goal is fully done
49
+ ```
50
+
51
+ If the session is interrupted and you never reach this step, that is acceptable. Incomplete episodes are better than missing observations mid-session.
52
+
53
+ ## observe vs believe
54
+
55
+ Use `observe()` for facts. Use `believe()` for interpretations that could be wrong or change.
56
+
57
+ **Observe:** `"[tool] requires [flag] — without it, [failure mode]"`\
58
+ **Believe:** `"[tool] behaviour is likely a bug — worth retrying after an upgrade"`
59
+
60
+ Beliefs trigger contradiction detection. If you later believe the opposite, the old belief is invalidated and both are linked — useful for tracing why you changed your mind.
61
+
62
+ For uncertain things, prefer `kind: "question"` or `kind: "hypothesis"` over stating them as facts.
63
+
64
+ ## What to observe
65
+
66
+ Observe your **experience**, not documentation:
67
+
68
+ - Approaches tried and whether they worked
69
+ - Config or flags that took effort to figure out
70
+ - Errors encountered and how they were resolved
71
+ - Decisions made and the reasoning behind them
72
+ - Constraints or preferences the user stated
73
+
74
+ **Good:** `"[library] [method] runs before [other step] — caused [bug] in [context]"`\
75
+ **Skip:** `"[library] supports [feature]"` ← already in the docs
76
+
77
+ ## What not to store
78
+
79
+ - Transient state: current cursor position, open file, in-progress thought
80
+ - Exact code snippets from files — observe your _understanding_ of them instead
81
+ - Timestamps — suemo sets `valid_from` automatically
82
+ - Uncertain things stated as facts — use `kind: "hypothesis"` instead
83
+
84
+ ## Querying
85
+
86
+ suemo uses hybrid retrieval (vector + BM25 + graph) with score gates.
87
+ Natural language often works, but broad prompts can still be noisy.
88
+
89
+ Use scoped, specific queries first:
90
+
91
+ ```
92
+ query("what approaches did we try for N+1 query issue", scope: "<active-scope>")
93
+ query("past decisions about auth middleware", scope: "<active-scope>")
94
+ ```
95
+
96
+ For exact strings (error codes, env var names, flag spellings), quote them:
97
+
98
+ ```
99
+ query('"SURREAL_CAPS_ALLOW_FUNC" init fix', scope: "<active-scope>")
100
+ ```
101
+
102
+ If ranking looks weak, inspect scoring directly:
103
+
104
+ ```
105
+ suemo query "<your query>" --scope <active-scope> --explain
106
+ suemo query "<your query>" --scope <active-scope> --explain --min-score 0.25 --relative-floor 0.8
107
+ ```
108
+
109
+ - Use `query()` when searching — you don't know which node you want
110
+ - Use `recall(<nodeId>)` when you have a node ID and want it plus neighbours
111
+
112
+ `recall()` also ticks the spaced-repetition clock on that node.
113
+
114
+ ## Using recall vs query
115
+
116
+ - Use `query()` when you don't know _which_ memory you want — you're searching
117
+ - Use `recall(nodeId)` when you have a specific node ID and want it plus its neighbours — you're inspecting
118
+
119
+ `recall()` also ticks the spaced-repetition clock on that node, marking it as "actively used".
120
+
121
+ ## Goals
122
+
123
+ Set a goal at the start of any multi-step task:
124
+
125
+ ```
126
+ goal_set("<description of task>", scope: "<active-scope>")
127
+ ```
128
+
129
+ Check open goals at session start (already covered above). Resolve when done:
130
+
131
+ ```
132
+ goal_resolve(<id>)
133
+ ```
134
+
135
+ Goals are a record of intent. Abandoned goals show up in health reports as a signal something was left incomplete.
136
+
137
+ ## What suemo handles automatically
138
+
139
+ - **Timestamps** — `valid_from` on write, `valid_until` on contradiction or invalidation
140
+ - **Deduplication** — identical writes merge; near-duplicates create a new linked node
141
+ - **Consolidation** — runs on a schedule; no manual trigger needed
142
+ - **Embeddings** — computed server-side via `fn::embed()`; never pass vectors yourself
143
+
144
+ ## Health check
145
+
146
+ ```
147
+ suemo health
148
+ ```
149
+
150
+ Signs things are working: recent consolidation run, goals resolved not abandoned, queries returning relevant results without heavy tuning.