open-memex 0.8.0-alpha.3 → 0.8.0
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/AGENTS.md +3 -2
- package/CHANGELOG.md +3 -1
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/dist/.build-stamp +1 -1
- package/dist/cli.js +1 -2
- package/dist/init.js +8 -10
- package/dist/tools/ops.js +3 -3
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/cli.ts +1 -2
- package/src/init.ts +8 -16
- package/src/tools/ops.ts +3 -3
package/AGENTS.md
CHANGED
|
@@ -144,8 +144,9 @@ Every write path (tool, keyword hook, CLI `add`) must:
|
|
|
144
144
|
|
|
145
145
|
Capture-time aliases (D61): `memory_add`/`supersede` may carry up to 4
|
|
146
146
|
`aliases` (alternate phrasings) into frontmatter; they index in their own FTS
|
|
147
|
-
column.
|
|
148
|
-
|
|
147
|
+
column. Always on since 2026-10-07 (Stone: init no longer asks) —
|
|
148
|
+
`cfg.captureAliases` still gates them for backward compatibility with
|
|
149
|
+
installs that set it manually, but new installs never see the question. Always pass them through
|
|
149
150
|
`normalizeAliases`; the keyword-capture path (no agent in the loop) never
|
|
150
151
|
invents aliases. Checkpoint-proposal guidance (propose, never auto-draft) is
|
|
151
152
|
copy, not mechanism: keep the rubric wording in sync across the skill, the
|
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,9 @@ the `@alpha` tag are development snapshots and are not listed individually.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## [0.8.0] - 2026-10-07
|
|
13
|
+
|
|
14
|
+
- User-defined alias vocabulary as query-time expansion (D81): any memory type may now carry `alias:` (nickname, e.g. 香蕉计划) and `target:` (referent, e.g. 支付系统重构项目) frontmatter — an alias memory defines vocabulary once per scope. At query time, query terms hit the alias registry (exact match, one cheap SELECT per search) and the query is rewritten with the other side of the relation — bidirectional, depth < 3, cycle-safe — then re-run as round 2/3. Rounds merge by normalized-max (`mergeRounds` in `src/retrieve/alias-memory.ts`): each round's BM25 scores are divided by that round's best, so an alias-side champion competes evenly with a literal-side champion; the merged pool is re-ranked and cut to [1.5K, 2K], never back to K. No reindex when an alias changes. Creation: `memory_add` alias/target params, CLI `add --alias/--target`, or frontmatter edit (v1: user-explicit only). Fixture grows to 54 memories / 44 queries (3 bidirectional alias queries): recall@1 0.750, recall@5 **0.977**, MRR 0.857. Also removes the init `captureAliases` and keyword-capture questions — both are now always on (Stone 2026-10-07).
|
|
13
15
|
|
|
14
16
|
- Index-time synonym/translation expansion (D80, supersedes D79): the curated map (`src/retrieve/synonyms.ts` — EN dev-domain groups, ZH groups and EN↔ZH translation pairs in one bidirectional list) is now applied at sync/index time — `writeRow` expands each memory's keywords (`expansionVariantsForDoc()`, capped at 32) into the indexed `aliases` column, so any related word matches in a plain round-1 query. The query-time second-chance round is removed (`search()` is a single FTS round; `SearchStats.secondRound` gone); `expandQueryWithSynonyms` stays as a bench-only export. Fixture (51 memories / 41 queries): recall@1 0.732 → 0.756, recall@5 0.854 → **0.976**, MRR 0.791 → **0.859** — all 5 EN↔ZH vocabulary misses rescued at rank 1–3. Map updates need a reindex to backfill.
|
|
15
17
|
|
package/README.md
CHANGED
|
@@ -406,8 +406,8 @@ Three ways memories get in:
|
|
|
406
406
|
**Aliases.** Each saved memory can carry up to 4 alternate phrasings
|
|
407
407
|
(synonyms, another language's equivalent) that are indexed with it, so a
|
|
408
408
|
question worded differently still finds the memory — "vacation days" finds the
|
|
409
|
-
holiday policy.
|
|
410
|
-
|
|
409
|
+
holiday policy. Always on — the agent may attach up to 4 per memory, and you
|
|
410
|
+
can pass your own via `open-memex add --aliases`.
|
|
411
411
|
|
|
412
412
|
Three ways to add them: `open-memex add "text" --aliases "phrase one; phrase
|
|
413
413
|
two"` (semicolon-separated, up to 4); ask the agent ("remember: 小宝贝 is my
|
package/README.zh-CN.md
CHANGED
|
@@ -263,7 +263,7 @@ open-memex uninstall --yes
|
|
|
263
263
|
- **检查点提议**:一个任务收尾时,助手会提议 1–3 条从这轮工作里提炼的候选记忆——决定及其理由、约定、踩过的坑、走过又放弃的路——只有你点头的那几条才存。不会有任何东西在你不知情时被写下来。
|
|
264
264
|
- **CLI**:`open-memex add "…"`,可选 `--scope` / `--tag` / `--type` / `--aliases`。
|
|
265
265
|
|
|
266
|
-
**别名。** 每条记忆可以带最多 4 个换一种说法(同义词、另一种语言的对应词),和记忆一起进索引,这样问法不同也能找到——比如搜 "vacation days"
|
|
266
|
+
**别名。** 每条记忆可以带最多 4 个换一种说法(同义词、另一种语言的对应词),和记忆一起进索引,这样问法不同也能找到——比如搜 "vacation days" 能找到假期政策那条。永远开启:agent 每条记忆最多可附 4 个,你也可以用 `open-memex add --aliases` 自己加。
|
|
267
267
|
|
|
268
268
|
三种加法:`open-memex add "正文" --aliases "说法一; 说法二"`(分号分隔,最多 4 个);直接跟 agent 说("记住:小宝贝是我的 AI agent,别名加上小沐");或直接改那条记忆的 `aliases:` frontmatter——Markdown 是事实来源,sync 会吃进去。
|
|
269
269
|
|
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
55d6d5c601b1769ad9c4813aebefcb25ee3b29cab0c6c30f8450d9388fe83a6a
|
package/dist/cli.js
CHANGED
|
@@ -116,8 +116,7 @@ Flags:
|
|
|
116
116
|
--aliases alternate phrasings of this fact (up to 4), indexed with the
|
|
117
117
|
memory so differently-worded searches still match; separate
|
|
118
118
|
with ; (commas also accepted — use ; when an alias itself
|
|
119
|
-
contains one).
|
|
120
|
-
(init default)
|
|
119
|
+
contains one). Always on.
|
|
121
120
|
--alias --target D81: define user vocabulary once — e.g. --alias 香蕉计划
|
|
122
121
|
--target 支付系统重构项目. Later queries mentioning either side
|
|
123
122
|
trigger a second search round on the other side (both
|
package/dist/init.js
CHANGED
|
@@ -811,19 +811,17 @@ export async function initProject(opts) {
|
|
|
811
811
|
// Install-time settings (D19). Non-default answers persist to the JSONC
|
|
812
812
|
// config file; `open-memex config set` changes them later.
|
|
813
813
|
const patch = {};
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
814
|
+
// Keyword auto-capture is always on (Stone 2026-10-07): no init
|
|
815
|
+
// question — there is no reason to turn it off. The
|
|
816
|
+
// `keywordCaptureEnabled` config key is still honored if set manually.
|
|
817
817
|
const injectOnFirstTurn = await askBool("Inject relevant memories when a session starts?", DEFAULT_CONFIG.injectOnFirstTurn);
|
|
818
818
|
if (injectOnFirstTurn !== DEFAULT_CONFIG.injectOnFirstTurn)
|
|
819
819
|
patch.injectOnFirstTurn = injectOnFirstTurn;
|
|
820
|
-
// D61
|
|
821
|
-
//
|
|
822
|
-
// Distinct from D80's automatic index-time synonym expansion, which
|
|
823
|
-
// applies
|
|
824
|
-
|
|
825
|
-
if (captureAliases !== DEFAULT_CONFIG.captureAliases)
|
|
826
|
-
patch.captureAliases = captureAliases;
|
|
820
|
+
// D61 capture-time aliases are always on (Stone 2026-10-07): the agent
|
|
821
|
+
// may always attach its own alternate phrasings — no init question.
|
|
822
|
+
// (Distinct from D80's automatic index-time synonym expansion, which
|
|
823
|
+
// also always applies.) The `captureAliases` config key is still
|
|
824
|
+
// honored if someone sets it manually; init just never asks anymore.
|
|
827
825
|
if (Object.keys(patch).length > 0) {
|
|
828
826
|
const file = saveConfig(patch);
|
|
829
827
|
console.log(` + settings saved to ${file} (change later with \`open-memex config set <key> <value>\`)`);
|
package/dist/tools/ops.js
CHANGED
|
@@ -58,7 +58,7 @@ export const scopeArg = z
|
|
|
58
58
|
export const aliasesArg = z
|
|
59
59
|
.array(z.string())
|
|
60
60
|
.optional()
|
|
61
|
-
.describe("Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match.
|
|
61
|
+
.describe("Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match. Always on. Send at most 4; extras and blanks are dropped silently, never an error.");
|
|
62
62
|
export const memoryAddArgs = {
|
|
63
63
|
content: z.string().min(1).describe("The fact to remember. One idea per memory."),
|
|
64
64
|
type: z
|
|
@@ -242,8 +242,8 @@ export async function addMemory(getScope, cfg, args) {
|
|
|
242
242
|
const fm = buildFrontmatter(s, {
|
|
243
243
|
type: args.type ?? "fact",
|
|
244
244
|
tags: args.tags ?? [],
|
|
245
|
-
// D61: aliases are stored
|
|
246
|
-
//
|
|
245
|
+
// D61: aliases are always stored (Stone 2026-10-07: init no longer asks;
|
|
246
|
+
// default on). Normalize caps at 4 and drops junk silently.
|
|
247
247
|
// Aliases pass through the same redaction as content (write-path
|
|
248
248
|
// invariant) — an alias carrying a token gets masked, not stored raw.
|
|
249
249
|
aliases: cfg.captureAliases
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-memex",
|
|
3
|
-
"version": "0.8.0
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"mcpName": "io.github.stoneskin/open-memex",
|
|
5
5
|
"description": "Local-first memory layer and protocol for AI coding agents. Markdown source of truth, SQLite FTS5 index, zero cloud.",
|
|
6
6
|
"keywords": [
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.stoneskin/open-memex",
|
|
4
4
|
"title": "open-memex",
|
|
5
5
|
"description": "Local-first memory for AI coding agents — Markdown + SQLite FTS5, shared across editors via MCP.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.8.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"url": "https://github.com/stoneskin/open-memex",
|
|
9
9
|
"source": "github"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "open-memex",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.8.0",
|
|
17
17
|
"runtimeHint": "npx",
|
|
18
18
|
"packageArguments": [
|
|
19
19
|
{
|
package/src/cli.ts
CHANGED
|
@@ -133,8 +133,7 @@ Flags:
|
|
|
133
133
|
--aliases alternate phrasings of this fact (up to 4), indexed with the
|
|
134
134
|
memory so differently-worded searches still match; separate
|
|
135
135
|
with ; (commas also accepted — use ; when an alias itself
|
|
136
|
-
contains one).
|
|
137
|
-
(init default)
|
|
136
|
+
contains one). Always on.
|
|
138
137
|
--alias --target D81: define user vocabulary once — e.g. --alias 香蕉计划
|
|
139
138
|
--target 支付系统重构项目. Later queries mentioning either side
|
|
140
139
|
trigger a second search round on the other side (both
|
package/src/init.ts
CHANGED
|
@@ -893,28 +893,20 @@ export async function initProject(opts: {
|
|
|
893
893
|
// Install-time settings (D19). Non-default answers persist to the JSONC
|
|
894
894
|
// config file; `open-memex config set` changes them later.
|
|
895
895
|
const patch: Record<string, unknown> = {};
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
);
|
|
900
|
-
if (keywordCaptureEnabled !== DEFAULT_CONFIG.keywordCaptureEnabled)
|
|
901
|
-
patch.keywordCaptureEnabled = keywordCaptureEnabled;
|
|
896
|
+
// Keyword auto-capture is always on (Stone 2026-10-07): no init
|
|
897
|
+
// question — there is no reason to turn it off. The
|
|
898
|
+
// `keywordCaptureEnabled` config key is still honored if set manually.
|
|
902
899
|
const injectOnFirstTurn = await askBool(
|
|
903
900
|
"Inject relevant memories when a session starts?",
|
|
904
901
|
DEFAULT_CONFIG.injectOnFirstTurn,
|
|
905
902
|
);
|
|
906
903
|
if (injectOnFirstTurn !== DEFAULT_CONFIG.injectOnFirstTurn)
|
|
907
904
|
patch.injectOnFirstTurn = injectOnFirstTurn;
|
|
908
|
-
// D61
|
|
909
|
-
//
|
|
910
|
-
// Distinct from D80's automatic index-time synonym expansion, which
|
|
911
|
-
// applies
|
|
912
|
-
|
|
913
|
-
"Let the agent attach its own alternate phrasings (aliases) to memories? (The built-in synonym map applies regardless.)",
|
|
914
|
-
DEFAULT_CONFIG.captureAliases,
|
|
915
|
-
);
|
|
916
|
-
if (captureAliases !== DEFAULT_CONFIG.captureAliases)
|
|
917
|
-
patch.captureAliases = captureAliases;
|
|
905
|
+
// D61 capture-time aliases are always on (Stone 2026-10-07): the agent
|
|
906
|
+
// may always attach its own alternate phrasings — no init question.
|
|
907
|
+
// (Distinct from D80's automatic index-time synonym expansion, which
|
|
908
|
+
// also always applies.) The `captureAliases` config key is still
|
|
909
|
+
// honored if someone sets it manually; init just never asks anymore.
|
|
918
910
|
if (Object.keys(patch).length > 0) {
|
|
919
911
|
const file = saveConfig(patch);
|
|
920
912
|
console.log(
|
package/src/tools/ops.ts
CHANGED
|
@@ -101,7 +101,7 @@ export const aliasesArg = z
|
|
|
101
101
|
.array(z.string())
|
|
102
102
|
.optional()
|
|
103
103
|
.describe(
|
|
104
|
-
"Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match.
|
|
104
|
+
"Optional: alternate phrasings of this fact — synonyms, another way a question might be worded, equivalents in the user's other language (e.g. 节假日 for 'public holidays'). They are indexed with the memory so differently-worded questions still match. Always on. Send at most 4; extras and blanks are dropped silently, never an error.",
|
|
105
105
|
);
|
|
106
106
|
|
|
107
107
|
export const memoryAddArgs = {
|
|
@@ -350,8 +350,8 @@ export async function addMemory(
|
|
|
350
350
|
const fm = buildFrontmatter(s, {
|
|
351
351
|
type: args.type ?? "fact",
|
|
352
352
|
tags: args.tags ?? [],
|
|
353
|
-
// D61: aliases are stored
|
|
354
|
-
//
|
|
353
|
+
// D61: aliases are always stored (Stone 2026-10-07: init no longer asks;
|
|
354
|
+
// default on). Normalize caps at 4 and drops junk silently.
|
|
355
355
|
// Aliases pass through the same redaction as content (write-path
|
|
356
356
|
// invariant) — an alias carrying a token gets masked, not stored raw.
|
|
357
357
|
aliases: cfg.captureAliases
|