suemo 0.1.6 → 0.1.8

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
@@ -11,6 +11,26 @@
11
11
 
12
12
  suemo gives AI agents a memory that survives across sessions, models, and runtimes. Write observations from a Telegram bot, query them from OpenCode, consolidate overnight — all agents share one source of truth in SurrealDB.
13
13
 
14
+ Specifications:
15
+
16
+ - Index: **[`specs/SPEC.md`](./specs/SPEC.md)**
17
+ - Technical/runtime contract: **[`specs/SPEC-technical.md`](./specs/SPEC-technical.md)**
18
+ - Psychological/critique framing: **[`specs/SPEC-psychological.md`](./specs/SPEC-psychological.md)**
19
+
20
+ ## For professional critique authors (longevity-focused)
21
+
22
+ If you're designing high-quality external critiques for suemo, evaluate it as **persistent coding-agent memory infrastructure**, not as a general AGI cognition claim.
23
+
24
+ Use this framing:
25
+
26
+ 1. **Psychological intent** — what memory quality should hold over time?
27
+ 2. **Technical mechanism** — what exact table/field/tool enforces that quality?
28
+ 3. **Operational evidence** — what logs/tests/metrics prove it under drift and contradiction?
29
+
30
+ Questions are most useful when they stress long-horizon behavior (30–180 day operation), contradiction handling, consolidation quality, retrieval interference, and scope/session isolation.
31
+
32
+ For rigorous critique language and category framing, start from **[`specs/SPEC-psychological.md`](./specs/SPEC-psychological.md)**.
33
+
14
34
  ---
15
35
 
16
36
  ## Features
@@ -445,6 +465,27 @@ This prints your active target (`url`, `namespace`, `database`) and step-by-step
445
465
 
446
466
  Agents never supply temporal fields (`valid_from`, `valid_until`). These are system-managed.
447
467
 
468
+ ### Memory field semantics (quick reference)
469
+
470
+ - `content`: canonical memory payload.
471
+ - `summary`: optional condensed text for compact retrieval/consolidation. It does **not** replace `content`.
472
+ - `source`: optional provenance label (free-form string), e.g. `prompt-capture`, `consolidation:nrem`.
473
+ - `prompt_source`: optional pointer to the prompt memory record that originated a derived memory.
474
+ - `fsrs_next_review`: optional review timestamp; currently set on `recall()` (not on every ingest).
475
+
476
+ ### Episode `memory_ids`
477
+
478
+ `episode.memory_ids` stores memory IDs attached to an open session, used for session reconstruction.
479
+
480
+ If you rarely see it populated, the typical reason is missing `sessionId` on write calls.
481
+ Current behavior: only write paths invoked with `sessionId` append to `memory_ids`.
482
+ `believe` now supports session linkage too:
483
+
484
+ - CLI: `suemo believe "..." --session <sessionId>`
485
+ - MCP: `believe({ content, sessionId, ... })`
486
+
487
+ See `specs/SPEC-technical.md` for full normative semantics and hardening targets.
488
+
448
489
  ### Scope and longevity notes
449
490
 
450
491
  - Default inferred project scope now uses nearest `<projectDir>/suemo.json` with `main.projectDir` defaulting to `.ua`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suemo",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Persistent semantic memory for AI agents — backed by SurrealDB.",
5
5
  "author": {
6
6
  "name": "Umar Alfarouk",
@@ -37,10 +37,11 @@
37
37
  "scripts": {
38
38
  "dev": "bun run src/cli/index.ts",
39
39
  "start": "bun run src/cli/index.ts",
40
+ "test": "bun test",
40
41
  "ssot:check": "bun run scripts/ssot.ts check",
41
42
  "ssot:sync": "bun run scripts/ssot.ts sync",
42
43
  "fmt": "dprint fmt",
43
- "check": "bun run fmt && bun tsc --noEmit && bun run ssot:check",
44
+ "check": "bun run fmt && bun tsc --noEmit && bun test && bun run ssot:check",
44
45
  "sync": "bun run ssot:sync"
45
46
  },
46
47
  "dependencies": {
@@ -56,6 +57,7 @@
56
57
  "zod": "^4.3.6"
57
58
  },
58
59
  "devDependencies": {
60
+ "@opencode-ai/plugin": "^1.3.0",
59
61
  "@types/bun": "^1.3.11",
60
62
  "typescript": "^5.9.3"
61
63
  }
@@ -3,13 +3,38 @@ 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.6
6
+ version: 0.1.8
7
7
  ---
8
8
 
9
9
  # suemo skill
10
10
 
11
11
  Use suemo to persist technical context across sessions with minimal, project-scoped memory.
12
12
 
13
+ ## Strict defaults (v0.1.8)
14
+
15
+ - Always run pre-checks before implementation:
16
+ - `goal_list({ scope })`
17
+ - `query({ input: "recent work on <topic>", scope })`
18
+ - `context({ scope, limit: 20 })`
19
+ - `observe.kind` accepts only: `observation | belief | question | hypothesis | goal`
20
+ - For non-trivial writes, prefer structured content:
21
+ - `**What**`, `**Why**`, `**Where**`, `**Learned**`
22
+ - End meaningful tasks with:
23
+ - `episode_end({ sessionId, summary, goal, discoveries, accomplished, files_changed })`
24
+ - `goal_resolve({ goalId })` when done
25
+ - `query({ input: "most recent observations", scope })`
26
+ - `health()`
27
+
28
+ ## OpenCode plugin support
29
+
30
+ `suemo init opencode` now installs three things:
31
+
32
+ 1. MCP config entry for suemo
33
+ 2. AGENTS.md suemo block
34
+ 3. OpenCode plugin at `~/.config/opencode/plugins/suemo.ts`
35
+
36
+ The plugin injects strict suemo protocol into system prompt and adds compaction checkpoint reminders.
37
+
13
38
  ## Quick use
14
39
 
15
40
  - CLI latest skill: `suemo skill`
@@ -1,17 +1,25 @@
1
1
  ---
2
2
  name: agents-snippet
3
3
  description: AGENTS.md snippet optimized for suemo skill discovery and usage.
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # AGENTS.md snippet
8
8
 
9
9
  ```md
10
- ## suemo-first memory workflow
10
+ ## suemo-first memory workflow (strict)
11
11
 
12
12
  Before significant work:
13
13
 
14
- - query("what do I know about <topic>")
14
+ - suemo_goal_list({ scope: "<active-scope>" })
15
+ - suemo_query({ input: "recent work on <topic>", scope: "<active-scope>" })
16
+ - suemo_context({ scope: "<active-scope>", limit: 20 })
17
+ - suemo_episode_start({ sessionId: "<session-id>" }) for new tasks
18
+
19
+ Schema guardrails:
20
+
21
+ - suemo_observe.kind must be one of: observation | belief | question | hypothesis | goal
22
+ - Never use discovery/architecture/bugfix as kind
15
23
 
16
24
  If you need latest usage docs:
17
25
 
@@ -21,16 +29,19 @@ If you need latest usage docs:
21
29
 
22
30
  During work:
23
31
 
24
- - observe("...") for concrete facts
25
- - believe("...") for conclusions
26
- - goal_set("...") for long tasks
32
+ - suemo_observe({ content: "**What**: ...\n**Why**: ...\n**Where**: ...\n**Learned**: ...", kind: "observation" })
33
+ - suemo_believe("...") for uncertain interpretations
34
+ - suemo_goal_set("...") for long tasks
27
35
 
28
36
  After completion:
29
37
 
30
- - goal_resolve("...") if applicable
31
- - episode_end(sessionId, summary="...")
38
+ - suemo_episode_end({ sessionId, summary, goal, discoveries, accomplished, files_changed })
39
+ - suemo_goal_resolve({ goalId }) if applicable
40
+ - suemo_query({ input: "most recent observations", scope: "<active-scope>" })
41
+ - suemo_health()
32
42
 
33
43
  After compaction/reset:
34
44
 
35
- - context({ scope: "<project-id>", limit: 20 })
45
+ - suemo_session_context_set({ sessionId, summary: "<compacted summary>" })
46
+ - suemo_context({ scope: "<project-id>", limit: 20 })
36
47
  ```
@@ -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.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # CLI reference
@@ -14,10 +14,15 @@ Core:
14
14
  - `suemo serve [--stdio|--dev]`
15
15
  - `suemo skill [reference]`
16
16
 
17
+ Aliases (deprecated, still accepted with warning):
18
+
19
+ - `suemo skills` → use `suemo skill`
20
+ - `suemo init surrealdb` → use `suemo init surreal`
21
+
17
22
  Memory:
18
23
 
19
24
  - `suemo observe <content>`
20
- - `suemo believe <content>`
25
+ - `suemo believe <content> [--session <sessionId>]`
21
26
  - `suemo query <input>`
22
27
  - `suemo recall <nodeId>`
23
28
  - `suemo wander`
@@ -1,40 +1,68 @@
1
1
  ---
2
2
  name: core-workflow
3
3
  description: Canonical suemo operating loop for OpenCode agents.
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # Core workflow
8
8
 
9
- 1. Start with memory lookup:
9
+ 1. Start with strict pre-check:
10
10
 
11
11
  ```ts
12
- query('what do I know about <topic>')
12
+ goal_list({ scope: '<project-scope>' })
13
+ query({ input: 'recent work on <topic>', scope: '<project-scope>' })
14
+ context({ scope: '<project-scope>', limit: 20 })
15
+ episode_start({ sessionId: '<session-id>' }) // when beginning new task
13
16
  ```
14
17
 
15
18
  2. During work, persist concrete discoveries:
16
19
 
17
20
  ```ts
18
- observe('...')
19
- believe('...')
21
+ observe({
22
+ content: '**What**: ...\n**Why**: ...\n**Where**: ...\n**Learned**: ...',
23
+ kind: 'observation',
24
+ scope: '<project-scope>',
25
+ })
26
+ believe({ content: '...', scope: '<project-scope>' })
20
27
  ```
21
28
 
22
- 3. For long tasks:
29
+ 3. Kind schema is strict:
23
30
 
24
31
  ```ts
25
- goal_set('...')
32
+ // valid only:
33
+ // observation | belief | question | hypothesis | goal
26
34
  ```
27
35
 
28
- 4. If compaction/reset happened:
36
+ 4. For long tasks:
29
37
 
30
38
  ```ts
39
+ goal_set({ content: '...', scope: '<project-scope>' })
40
+ ```
41
+
42
+ 5. If compaction/reset happened:
43
+
44
+ ```ts
45
+ session_context_set({
46
+ sessionId: '<session-id>',
47
+ summary: '<compacted summary>',
48
+ })
31
49
  context({ scope: '<project-id>', limit: 20 })
32
50
  ```
33
51
 
34
- 5. Close session:
52
+ 6. Close session with structured fields:
35
53
 
36
54
  ```ts
37
- episode_end(sessionId, summary = '...')
55
+ episode_end({
56
+ sessionId: '<session-id>',
57
+ summary: '...',
58
+ goal: '...',
59
+ discoveries: ['...'],
60
+ accomplished: ['...'],
61
+ files_changed: ['path/to/file'],
62
+ })
63
+ goal_resolve({ goalId: '<goal-id>' }) // if completed
64
+ query({ input: 'most recent observations', scope: '<project-scope>' })
65
+ health()
38
66
  ```
39
67
 
40
68
  Prefer project-scoped memory. Let suemo infer scope from nearest `{projectDir}/suemo.json` (recommended `main.projectDir = '.ua'`).
@@ -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.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # Manual test plan
@@ -35,10 +35,11 @@ Expected:
35
35
 
36
36
  1. `episode_start`
37
37
  2. add observations with `sessionId`
38
- 3. `session_context_set`
39
- 4. `context`
40
- 5. `episode_end` with structured fields
41
- 6. verify episode fields persisted
38
+ 3. add belief with `sessionId` (`suemo believe "..." --session <id>` or MCP `believe({ sessionId })`)
39
+ 4. `session_context_set`
40
+ 5. `context`
41
+ 6. `episode_end` with structured fields
42
+ 7. verify episode fields persisted
42
43
 
43
44
  ## E. Goals
44
45
 
@@ -66,7 +67,17 @@ Expected:
66
67
  2. `suemo skill core-workflow`
67
68
  3. MCP `skill({})`, `skill({ reference: "cli-reference" })`
68
69
 
69
- ## I. Output modes
70
+ ## I. OpenCode init + plugin install
71
+
72
+ 1. `suemo init opencode --dry-run`
73
+ 2. `suemo init opencode`
74
+ 3. Verify files:
75
+ - `~/.config/opencode/opencode.jsonc` or `.json` contains `mcp.suemo`
76
+ - `~/.config/opencode/AGENTS.md` has `<!-- SUEMO:START --> ... <!-- SUEMO:END -->`
77
+ - `~/.config/opencode/plugins/suemo.ts` exists
78
+ 4. Validate plugin appears under OpenCode loaded plugins
79
+
80
+ ## J. Output modes
70
81
 
71
82
  Repeat representative commands under:
72
83
 
@@ -1,11 +1,17 @@
1
1
  ---
2
2
  name: mcp-reference
3
3
  description: MCP tool reference for suemo v0.0.6.
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # MCP tools
8
8
 
9
+ Strictness notes (v0.1.7):
10
+
11
+ - `observe.kind` is strict enum: `observation | belief | question | hypothesis | goal`
12
+ - `episode_end` supports optional structured fields: `summary`, `goal`, `discoveries`, `accomplished`, `files_changed`
13
+ - For reliable agent adoption, pair `episode_end` with `goal_resolve` and post-check `query("most recent observations")`
14
+
9
15
  Write/mutate:
10
16
 
11
17
  - `observe`
@@ -42,5 +48,7 @@ Maintenance:
42
48
  Notes:
43
49
 
44
50
  - Optional `scope` defaults to inferred project id.
51
+ - `believe` accepts optional `sessionId` to attach created belief memories to an open episode.
45
52
  - `update` re-embeds when `content` changes.
46
53
  - `episode_end` accepts structured fields (`goal`, `discoveries`, `accomplished`, `files_changed`).
54
+ - `skill` returns inline references; use `skill({ reference: "core-workflow" })` for canonical loop.
@@ -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.6
4
+ version: 0.1.8
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.6
4
+ version: 0.1.8
5
5
  ---
6
6
 
7
7
  # Local ↔ VPS sync scenario
package/src/AGENTS.md CHANGED
@@ -1,150 +1,130 @@
1
- # Working with suemo
1
+ **CRITICAL:** This protocol is mandatory. Start each new task with the checklist below. End each completed task with `suemo_episode_end` + `suemo_goal_resolve` (if applicable). Do not skip.
2
2
 
3
- suemo is your persistent memory. Use it to store what you learn, remember what matters, and build on past work.
3
+ ## 1) Pre-Session Checklist (required)
4
4
 
5
- ## Before anything else
5
+ Before implementation:
6
6
 
7
- **Load the skill doc first.** It is versioned and may contain updated workflows, references, and tool signatures that supersede this file.
7
+ - [ ] `suemo_goal_list({ scope: "<active-scope>" })`
8
+ - [ ] `suemo_query({ input: "recent work on <topic>", scope: "<active-scope>" })`
9
+ - [ ] `suemo_context({ scope: "<active-scope>", limit: 20 })`
10
+ - [ ] Resolve abandoned goals if any
11
+ - [ ] `suemo_episode_start({ sessionId: "<session-id>" })` for new tasks
8
12
 
9
- - CLI: `suemo skill`
10
- - MCP: `skill({})`
13
+ Proceed only after all checks pass.
11
14
 
12
- For a specific reference: `suemo skill <reference-name>` / `skill({ reference: "<reference-name>" })`
15
+ ---
13
16
 
14
- Available references: `agents-snippet`, `cli-reference`, `core-workflow`, `manual-test-plan`, `mcp-reference`, `schema-retention-longevity`, `sync-local-vps`
17
+ ## 2) Strict schema rules (required)
15
18
 
16
- Do not proceed until the skill doc is loaded.
19
+ ### `suemo_observe` kind is strict
17
20
 
18
- ## Session protocol
21
+ Valid `kind` values only:
19
22
 
20
- These steps are **mandatory**, not suggested.
23
+ - `observation`
24
+ - `belief`
25
+ - `question`
26
+ - `hypothesis`
27
+ - `goal`
21
28
 
22
- ### On session start
29
+ ### `suemo_episode_end` payload shape
23
30
 
24
- ```
25
- goal_list(scope: "<active-scope>")
26
- query("recent work on [topic]", scope: "<active-scope>")
27
- ```
31
+ Minimum schema requirement: `sessionId`.
28
32
 
29
- Read relevant results before touching any code. Do not re-derive what is already stored.
33
+ Required by protocol when finishing meaningful work:
30
34
 
31
- ### While working
35
+ - `summary`
36
+ - `goal`
37
+ - `discoveries` (array)
38
+ - `accomplished` (array)
39
+ - `files_changed` (array)
32
40
 
33
- Store anything that would save time next session:
41
+ Use exact field names above.
34
42
 
35
- ```
36
- observe("[fact you learned or confirmed]")
37
- believe("[interpretation or conclusion that might change]")
38
- ```
43
+ ---
39
44
 
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.
45
+ ## 3) During work
41
46
 
42
- ### Before ending (or if interrupted)
47
+ Persist important information immediately (not only at the end).
43
48
 
44
- Call this **before** your final tool invocation, not after — sessions can be cut off without warning:
49
+ Use this structure for non-trivial observations:
45
50
 
51
+ ```md
52
+ **What**: <what changed>
53
+ **Why**: <reason>
54
+ **Where**: <files/paths>
55
+ **Learned**: <gotchas/decisions>
46
56
  ```
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
57
 
55
- Use `observe()` for facts. Use `believe()` for interpretations that could be wrong or change.
58
+ Guidance:
56
59
 
57
- **Observe:** `"[tool] requires [flag] — without it, [failure mode]"`\
58
- **Believe:** `"[tool] behaviour is likely a bug — worth retrying after an upgrade"`
60
+ - Facts `suemo_observe`
61
+ - Interpretations/uncertainty `suemo_believe`
62
+ - Longer tasks → `suemo_goal_set`
59
63
 
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.
64
+ ---
61
65
 
62
- For uncertain things, prefer `kind: "question"` or `kind: "hypothesis"` over stating them as facts.
66
+ ## 4) After completion
63
67
 
64
- ## What to observe
68
+ Run in order:
65
69
 
66
- Observe your **experience**, not documentation:
70
+ 1. `suemo_episode_end({ sessionId, summary, goal, discoveries, accomplished, files_changed })`
71
+ 2. `suemo_goal_resolve({ goalId })` when done
72
+ 3. `suemo_query({ input: "most recent observations", scope })`
73
+ 4. `suemo_health()`
67
74
 
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
75
+ ---
73
76
 
74
- **Good:** `"[library] [method] runs before [other step] — caused [bug] in [context]"`\
75
- **Skip:** `"[library] supports [feature]"` ← already in the docs
77
+ ## 5) Querying best practices
76
78
 
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:
79
+ Prefer specific, scoped queries:
90
80
 
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>")
81
+ ```ts
82
+ suemo_query({
83
+ input: 'past decisions about auth middleware',
84
+ scope: '<project-id>',
85
+ })
86
+ suemo_query({
87
+ input: '"SURREAL_CAPS_ALLOW_FUNC" init fix',
88
+ scope: '<project-id>',
89
+ })
94
90
  ```
95
91
 
96
- For exact strings (error codes, env var names, flag spellings), quote them:
92
+ When weak ranking is suspected, run `--explain` from CLI to inspect scoring.
97
93
 
98
- ```
99
- query('"SURREAL_CAPS_ALLOW_FUNC" init fix', scope: "<active-scope>")
100
- ```
94
+ ---
101
95
 
102
- If ranking looks weak, inspect scoring directly:
96
+ ## 6) Anti-patterns
103
97
 
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
- ```
98
+ - ❌ Storing transient state (cursor position, temporary thoughts)
99
+ - Storing raw code snippets instead of distilled understanding
100
+ - Querying on every small step
101
+ - ❌ Skipping `suemo_episode_end`
102
+ - ❌ Forgetting `suemo_goal_resolve`
103
+ - ❌ Using non-schema `kind` values
108
104
 
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
105
+ ---
111
106
 
112
- `recall()` also ticks the spaced-repetition clock on that node.
107
+ ## 7) Compaction/reset handling
113
108
 
114
- ## Using recall vs query
109
+ Immediately:
115
110
 
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
111
+ 1. `suemo_session_context_set({ sessionId, summary: "<compacted summary>" })`
112
+ 2. `suemo_context({ scope: "<project-id>", limit: 20 })`
113
+ 3. Continue work
118
114
 
119
- `recall()` also ticks the spaced-repetition clock on that node, marking it as "actively used".
115
+ ---
120
116
 
121
- ## Goals
117
+ ## 8) Documentation shortcuts
122
118
 
123
- Set a goal at the start of any multi-step task:
124
-
125
- ```
126
- goal_set("<description of task>", scope: "<active-scope>")
119
+ ```bash
120
+ suemo skill
121
+ suemo skill core-workflow
122
+ suemo skill mcp-reference
123
+ suemo skill manual-test-plan
127
124
  ```
128
125
 
129
- Check open goals at session start (already covered above). Resolve when done:
130
-
131
- ```
132
- goal_resolve(<id>)
133
- ```
126
+ Load docs once per session unless requirements changed.
134
127
 
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
- ```
128
+ ---
149
129
 
150
- Signs things are working: recent consolidation run, goals resolved not abandoned, queries returning relevant results without heavy tuning.
130
+ _Version: 0.1.8 | Updated: 2026-03-24 | Summary: stricter schema + explicit completion contract_
@@ -12,6 +12,7 @@ export const believeCmd = app.sub('believe')
12
12
  .flags({
13
13
  scope: { type: 'string', short: 's', description: 'Scope label' },
14
14
  confidence: { type: 'number', description: 'Confidence 0.0–1.0', default: 1.0 },
15
+ session: { type: 'string', description: 'Session ID (attach to open episode)' },
15
16
  json: { type: 'boolean', description: 'Output JSON result' },
16
17
  pretty: { type: 'boolean', description: 'Human-readable output (default)' },
17
18
  })
@@ -32,12 +33,14 @@ export const believeCmd = app.sub('believe')
32
33
  hasScope: Boolean(resolvedScope),
33
34
  scope: resolvedScope,
34
35
  confidence: flags.confidence,
36
+ hasSession: Boolean(flags.session),
35
37
  contentLength: args.content.length,
36
38
  })
37
39
  const { node, contradicted } = await believe(db, {
38
40
  content: args.content,
39
41
  scope: resolvedScope,
40
42
  confidence: flags.confidence,
43
+ sessionId: flags.session,
41
44
  }, config)
42
45
  if (outputMode === 'json') {
43
46
  const out: Record<string, unknown> = { id: node.id, valid_from: node.valid_from }
@@ -29,7 +29,7 @@ const reportCmd = health.sub('report')
29
29
  let db: Surreal | undefined
30
30
  try {
31
31
  db = await connect(config.surreal)
32
- const report = await healthReport(db)
32
+ const report = await healthReport(db, { embeddingProvider: config.embedding.provider })
33
33
  if (outputMode === 'json') {
34
34
  printCliJson(report, flags)
35
35
  } else {
@@ -129,7 +129,7 @@ export const healthCmd = health
129
129
  let db: Surreal | undefined
130
130
  try {
131
131
  db = await connect(config.surreal)
132
- const report = await healthReport(db)
132
+ const report = await healthReport(db, { embeddingProvider: config.embedding.provider })
133
133
  if (outputMode === 'json') {
134
134
  printCliJson(report, flags)
135
135
  } else {