opencode-harnmem 0.0.0-stage → 0.1.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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -2
  3. package/index.js +512 -0
  4. package/lib/engine.mjs +72 -0
  5. package/lib/format.mjs +119 -0
  6. package/lib/settings.mjs +131 -0
  7. package/package.json +23 -3
  8. package/vendor/core/assets.d.ts +52 -0
  9. package/vendor/core/assets.d.ts.map +1 -0
  10. package/vendor/core/assets.js +227 -0
  11. package/vendor/core/assets.js.map +1 -0
  12. package/vendor/core/config.d.ts +36 -0
  13. package/vendor/core/config.d.ts.map +1 -0
  14. package/vendor/core/config.js +134 -0
  15. package/vendor/core/config.js.map +1 -0
  16. package/vendor/core/consolidate.d.ts +14 -0
  17. package/vendor/core/consolidate.d.ts.map +1 -0
  18. package/vendor/core/consolidate.js +237 -0
  19. package/vendor/core/consolidate.js.map +1 -0
  20. package/vendor/core/data/synonyms.en.txt +61 -0
  21. package/vendor/core/data/synonyms.zh.txt +157 -0
  22. package/vendor/core/extract.d.ts +49 -0
  23. package/vendor/core/extract.d.ts.map +1 -0
  24. package/vendor/core/extract.js +179 -0
  25. package/vendor/core/extract.js.map +1 -0
  26. package/vendor/core/frontmatter.d.ts +31 -0
  27. package/vendor/core/frontmatter.d.ts.map +1 -0
  28. package/vendor/core/frontmatter.js +372 -0
  29. package/vendor/core/frontmatter.js.map +1 -0
  30. package/vendor/core/harnmem.d.ts +87 -0
  31. package/vendor/core/harnmem.d.ts.map +1 -0
  32. package/vendor/core/harnmem.js +918 -0
  33. package/vendor/core/harnmem.js.map +1 -0
  34. package/vendor/core/hot-context.d.ts +28 -0
  35. package/vendor/core/hot-context.d.ts.map +1 -0
  36. package/vendor/core/hot-context.js +179 -0
  37. package/vendor/core/hot-context.js.map +1 -0
  38. package/vendor/core/index.d.ts +16 -0
  39. package/vendor/core/index.d.ts.map +1 -0
  40. package/vendor/core/index.js +10 -0
  41. package/vendor/core/index.js.map +1 -0
  42. package/vendor/core/indexer.d.ts +107 -0
  43. package/vendor/core/indexer.d.ts.map +1 -0
  44. package/vendor/core/indexer.js +282 -0
  45. package/vendor/core/indexer.js.map +1 -0
  46. package/vendor/core/inspect.d.ts +278 -0
  47. package/vendor/core/inspect.d.ts.map +1 -0
  48. package/vendor/core/inspect.js +643 -0
  49. package/vendor/core/inspect.js.map +1 -0
  50. package/vendor/core/lifecycle.d.ts +50 -0
  51. package/vendor/core/lifecycle.d.ts.map +1 -0
  52. package/vendor/core/lifecycle.js +249 -0
  53. package/vendor/core/lifecycle.js.map +1 -0
  54. package/vendor/core/project.d.ts +41 -0
  55. package/vendor/core/project.d.ts.map +1 -0
  56. package/vendor/core/project.js +197 -0
  57. package/vendor/core/project.js.map +1 -0
  58. package/vendor/core/prompts/README.md +96 -0
  59. package/vendor/core/prompts/consolidate-digest.md +31 -0
  60. package/vendor/core/prompts/extract.md +80 -0
  61. package/vendor/core/prompts/migrate.md +96 -0
  62. package/vendor/core/prompts/synonyms.md +43 -0
  63. package/vendor/core/prompts/write-policy.md +12 -0
  64. package/vendor/core/retrieval.d.ts +95 -0
  65. package/vendor/core/retrieval.d.ts.map +1 -0
  66. package/vendor/core/retrieval.js +569 -0
  67. package/vendor/core/retrieval.js.map +1 -0
  68. package/vendor/core/store.d.ts +145 -0
  69. package/vendor/core/store.d.ts.map +1 -0
  70. package/vendor/core/store.js +511 -0
  71. package/vendor/core/store.js.map +1 -0
  72. package/vendor/core/suggest.d.ts +128 -0
  73. package/vendor/core/suggest.d.ts.map +1 -0
  74. package/vendor/core/suggest.js +384 -0
  75. package/vendor/core/suggest.js.map +1 -0
  76. package/vendor/core/text.d.ts +80 -0
  77. package/vendor/core/text.d.ts.map +1 -0
  78. package/vendor/core/text.js +253 -0
  79. package/vendor/core/text.js.map +1 -0
  80. package/vendor/core/types.d.ts +453 -0
  81. package/vendor/core/types.d.ts.map +1 -0
  82. package/vendor/core/types.js +14 -0
  83. package/vendor/core/types.js.map +1 -0
  84. package/vendor/core/util.d.ts +38 -0
  85. package/vendor/core/util.d.ts.map +1 -0
  86. package/vendor/core/util.js +248 -0
  87. package/vendor/core/util.js.map +1 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Configuration: defaults, file loading and merge order.
3
+ *
4
+ * Precedence (low -> high):
5
+ * built-in defaults
6
+ * <home>/config.json
7
+ * <projectRoot>/.harnmem.json
8
+ * explicit options passed to HarnMem.open()
9
+ */
10
+ import { promises as fs } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { DEFAULT_FIELDS } from "./text.js";
13
+ import { readJson } from "./util.js";
14
+ export const DEFAULT_BUDGET = {
15
+ injectTokens: 1200,
16
+ searchTokens: 1200,
17
+ hotEntries: 24,
18
+ maxPinned: 10,
19
+ };
20
+ export const DEFAULT_RETRIEVAL = {
21
+ k1: 1.2,
22
+ b: 0.75,
23
+ weights: { lex: 1.0, imp: 0.15, conf: 0.1, rec: 0.12, use: 0.08, pin: 0.25, link: 0.3, stale: 0.3 },
24
+ decayPerHour: 0.995,
25
+ mmrLambda: 0.7,
26
+ // 0.10 keeps solid synonym-only matches answerable (a "go live" query still
27
+ // matches a record that says "deploy", lex ≈ 0.14) while a query with no
28
+ // lexical overlap at all abstains. S6-style false injections were caused by
29
+ // polluted expansion terms, not by this knob.
30
+ abstainLex: 0.1,
31
+ ttlDays: { user: 365, feedback: 365, project: 180, reference: 365 },
32
+ synonyms: true,
33
+ linkDiffusion: true,
34
+ mmr: true,
35
+ };
36
+ export const DEFAULT_WRITE = {
37
+ autoExtract: true,
38
+ skipExtractIfModelWrote: 1,
39
+ minUserMessages: 3,
40
+ minDigestChars: 500,
41
+ maxPerRun: 6,
42
+ minConfidence: 0.5,
43
+ llmTimeoutMs: 12000,
44
+ };
45
+ export const DEFAULT_GOVERNANCE = {
46
+ maxUserRecords: 500,
47
+ maxProjectRecords: 3000,
48
+ maxBodyBytes: 65536,
49
+ consolidateEveryWrites: 200,
50
+ trashGraceDays: 30,
51
+ archiveRetention: 180,
52
+ archiveR0: 0.3,
53
+ };
54
+ export const DEFAULT_CONFIG = {
55
+ home: "",
56
+ harness: "cli",
57
+ cwd: process.cwd(),
58
+ now: () => Date.now(),
59
+ budget: DEFAULT_BUDGET,
60
+ retrieval: DEFAULT_RETRIEVAL,
61
+ write: DEFAULT_WRITE,
62
+ governance: DEFAULT_GOVERNANCE,
63
+ };
64
+ export function mergeConfig(base, override) {
65
+ if (!override)
66
+ return base;
67
+ const merged = { ...base, ...override };
68
+ if (override.budget)
69
+ merged.budget = { ...(base.budget ?? DEFAULT_BUDGET), ...override.budget };
70
+ if (override.retrieval) {
71
+ const baseRetrieval = { ...DEFAULT_RETRIEVAL, ...(base.retrieval ?? {}) };
72
+ const next = { ...baseRetrieval, ...override.retrieval };
73
+ next.weights = { ...baseRetrieval.weights, ...(override.retrieval.weights ?? {}) };
74
+ next.ttlDays = { ...baseRetrieval.ttlDays, ...(override.retrieval.ttlDays ?? {}) };
75
+ merged.retrieval = next;
76
+ }
77
+ if (override.write)
78
+ merged.write = { ...(base.write ?? DEFAULT_WRITE), ...override.write };
79
+ if (override.governance)
80
+ merged.governance = { ...(base.governance ?? DEFAULT_GOVERNANCE), ...override.governance };
81
+ return merged;
82
+ }
83
+ async function readConfigFile(file) {
84
+ try {
85
+ await fs.access(file);
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ const parsed = await readJson(file, null);
91
+ return parsed && typeof parsed === "object" ? parsed : null;
92
+ }
93
+ /**
94
+ * Load config from the home config file and the project-local `.harnmem.json`
95
+ * (if any), then apply explicit overrides.
96
+ */
97
+ export async function loadConfig(home, projectRoot, explicit) {
98
+ let config = { ...DEFAULT_CONFIG, home };
99
+ const globalFile = await readConfigFile(join(home, "config.json"));
100
+ if (globalFile)
101
+ config = mergeConfig(config, globalFile);
102
+ if (projectRoot) {
103
+ const localFile = await readConfigFile(join(projectRoot, ".harnmem.json"));
104
+ if (localFile)
105
+ config = mergeConfig(config, localFile);
106
+ }
107
+ config = mergeConfig(config, explicit);
108
+ config.home = home;
109
+ return config;
110
+ }
111
+ export function fieldsOf(config) {
112
+ return { ...DEFAULT_FIELDS, ...(config.retrieval?.fields ?? {}) };
113
+ }
114
+ /** Resolved ttl days for a type. */
115
+ export function ttlDays(config, type) {
116
+ const ttl = config.retrieval?.ttlDays;
117
+ if (!ttl)
118
+ return 180;
119
+ return ttl[type] ?? 180;
120
+ }
121
+ /** Resolved retrieval config with all defaults applied. */
122
+ export function retrievalOf(config) {
123
+ return { ...DEFAULT_RETRIEVAL, ...(config.retrieval ?? {}), weights: { ...DEFAULT_RETRIEVAL.weights, ...(config.retrieval?.weights ?? {}) }, ttlDays: { ...DEFAULT_RETRIEVAL.ttlDays, ...(config.retrieval?.ttlDays ?? {}) } };
124
+ }
125
+ export function writeOf(config) {
126
+ return { ...DEFAULT_WRITE, ...(config.write ?? {}) };
127
+ }
128
+ export function governanceOf(config) {
129
+ return { ...DEFAULT_GOVERNANCE, ...(config.governance ?? {}) };
130
+ }
131
+ export function budgetOf(config) {
132
+ return { ...DEFAULT_BUDGET, ...(config.budget ?? {}) };
133
+ }
134
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ConsolidateOptions, ConsolidationReport, HarnMemConfig } from "./types.js";
2
+ import type { Store } from "./store.js";
3
+ import type { IndexManager } from "./indexer.js";
4
+ export declare class Consolidator {
5
+ private readonly store;
6
+ private readonly index;
7
+ private readonly config;
8
+ constructor(store: Store, index: IndexManager, config: HarnMemConfig);
9
+ private now;
10
+ run(opts?: ConsolidateOptions): Promise<ConsolidationReport>;
11
+ private findDuplicates;
12
+ private writeDigests;
13
+ }
14
+ //# sourceMappingURL=consolidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../src/consolidate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EAGd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAY,KAAK,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAmBjD,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,aAAa;IAGxC,OAAO,CAAC,GAAG;IAIL,GAAG,CAAC,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA0FtE,OAAO,CAAC,cAAc;YAwBR,YAAY;CA2F3B"}
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Consolidation: mechanical dedupe, lifecycle transitions and capacity
3
+ * enforcement; optional LLM digest writing. Never destructive: removals go to
4
+ * `trash/` and every action is audited.
5
+ */
6
+ import { promises as fs } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { contentSimilarity, mergeIntoRecord, recordSimhash, retentionDecision, trashDecision, valueScore, } from "./lifecycle.js";
9
+ import { resolvePrompt, DEFAULT_CONSOLIDATE_PROMPT, ensurePromptFiles } from "./extract.js";
10
+ import { fillPrompt } from "./assets.js";
11
+ import { hamming64, newMemoryId } from "./util.js";
12
+ import { governanceOf } from "./config.js";
13
+ export class Consolidator {
14
+ store;
15
+ index;
16
+ config;
17
+ constructor(store, index, config) {
18
+ this.store = store;
19
+ this.index = index;
20
+ this.config = config;
21
+ }
22
+ now() {
23
+ return (this.config.now ?? Date.now)();
24
+ }
25
+ async run(opts = {}) {
26
+ const startedAt = this.now();
27
+ const dryRun = Boolean(opts.dryRun);
28
+ const report = {
29
+ runId: newMemoryId(startedAt),
30
+ startedAt,
31
+ finishedAt: startedAt,
32
+ merged: [],
33
+ supersededChainsCompressed: 0,
34
+ archived: [],
35
+ digestsWritten: [],
36
+ skipped: 0,
37
+ llmCalls: 0,
38
+ dryRun,
39
+ };
40
+ await ensurePromptFiles(this.store.home);
41
+ const shards = await this.store.listShards();
42
+ for (const shard of shards) {
43
+ const { records } = await this.store.readShard(shard);
44
+ for (const pair of this.findDuplicates(records)) {
45
+ report.merged.push({ into: pair.keep.id, from: [pair.drop.id] });
46
+ if (dryRun)
47
+ continue;
48
+ const merged = mergeIntoRecord(pair.keep, pair.drop, this.now());
49
+ merged.links = merged.links.filter((id) => id !== pair.drop.id);
50
+ await this.store.writeRecord(shard, merged);
51
+ await this.store.moveToTrash(shard, pair.drop, this.now());
52
+ await this.store.audit({
53
+ ts: this.now(),
54
+ kind: "consolidate",
55
+ action: "merge",
56
+ merged: [pair.drop.id],
57
+ into: pair.keep.id,
58
+ reason: "near-dup",
59
+ });
60
+ }
61
+ const refreshed = await this.store.readShard(shard);
62
+ for (const record of refreshed.records.filter((r) => r.status === "active")) {
63
+ if (retentionDecision(record, this.now()) !== "archive")
64
+ continue;
65
+ report.archived.push(record.id);
66
+ if (dryRun)
67
+ continue;
68
+ await this.store.writeRecord(shard, { ...record, status: "archived", updated: this.now() });
69
+ await this.store.audit({ ts: this.now(), kind: "archive", ids: [record.id], reason: "decayed" });
70
+ }
71
+ for (const record of refreshed.records.filter((r) => r.status === "archived")) {
72
+ if (!trashDecision(record, this.now()))
73
+ continue;
74
+ if (dryRun) {
75
+ report.skipped++;
76
+ continue;
77
+ }
78
+ await this.store.moveToTrash(shard, record, this.now());
79
+ await this.store.audit({ ts: this.now(), kind: "trash", ids: [record.id], reason: "cold-archive" });
80
+ }
81
+ // Supersede chains: compress metadata only (history stays on disk).
82
+ const all = (await this.store.readShard(shard)).records;
83
+ for (const record of all) {
84
+ if (record.supersededBy && record.status === "superseded" && record.validTo === null) {
85
+ report.supersededChainsCompressed++;
86
+ if (!dryRun)
87
+ await this.store.writeRecord(shard, { ...record, validTo: record.updated });
88
+ }
89
+ }
90
+ // Capacity: archive lowest-value active records beyond the per-shard cap.
91
+ const governance = governanceOf(this.config);
92
+ const cap = shard.scope === "user" ? governance.maxUserRecords : governance.maxProjectRecords;
93
+ const active = (await this.store.readShard(shard)).records.filter((r) => r.status === "active");
94
+ if (active.length > cap) {
95
+ const excess = active
96
+ .filter((r) => !r.pinned)
97
+ .sort((a, b) => valueScore(a, this.now()) - valueScore(b, this.now()) || a.updated - b.updated)
98
+ .slice(0, active.length - cap);
99
+ for (const record of excess) {
100
+ report.archived.push(record.id);
101
+ if (dryRun)
102
+ continue;
103
+ await this.store.writeRecord(shard, { ...record, status: "archived", updated: this.now() });
104
+ await this.store.audit({ ts: this.now(), kind: "archive", ids: [record.id], reason: "capacity" });
105
+ }
106
+ }
107
+ if (this.config.llm && !dryRun && !opts.mechanicalOnly) {
108
+ const written = await this.writeDigests(shard, this.config.llm, opts.maxLlmCalls ?? 3, report);
109
+ report.digestsWritten.push(...written);
110
+ }
111
+ }
112
+ await this.index.rebuildAll();
113
+ report.finishedAt = this.now();
114
+ return report;
115
+ }
116
+ findDuplicates(records) {
117
+ const active = records.filter((record) => record.status === "active" && !record.sensitive);
118
+ const used = new Set();
119
+ const pairs = [];
120
+ for (let i = 0; i < active.length; i++) {
121
+ const a = active[i];
122
+ if (used.has(a.id))
123
+ continue;
124
+ for (let j = i + 1; j < active.length; j++) {
125
+ const b = active[j];
126
+ if (used.has(b.id))
127
+ continue;
128
+ if (a.type !== b.type || a.scope !== b.scope)
129
+ continue;
130
+ if (a.scope === "project" && a.project !== b.project)
131
+ continue;
132
+ if (hamming64(recordSimhash(a), recordSimhash(b)) > 3)
133
+ continue;
134
+ if (contentSimilarity(a, b) < 0.82)
135
+ continue;
136
+ const keep = a.created <= b.created ? a : b;
137
+ const drop = keep === a ? b : a;
138
+ used.add(drop.id);
139
+ pairs.push({ keep, drop });
140
+ break;
141
+ }
142
+ }
143
+ return pairs;
144
+ }
145
+ async writeDigests(shard, llm, maxCalls, report) {
146
+ const { records } = await this.store.readShard(shard);
147
+ const active = records.filter((record) => record.status === "active");
148
+ if (active.length === 0)
149
+ return [];
150
+ const groups = new Map();
151
+ for (const record of active) {
152
+ const key = record.category ?? record.tags[0] ?? record.type;
153
+ const list = groups.get(key) ?? [];
154
+ list.push(record);
155
+ groups.set(key, list);
156
+ }
157
+ const asset = resolvePrompt(this.store.home, "consolidate-digest", DEFAULT_CONSOLIDATE_PROMPT);
158
+ const written = [];
159
+ for (const [topic, group] of [...groups.entries()].slice(0, maxCalls)) {
160
+ const memoriesBlock = group
161
+ .slice(0, 12)
162
+ .map((r) => [
163
+ `### [${r.id}] (${r.type}) valid_from=${new Date(r.validFrom).toISOString().slice(0, 10)}`,
164
+ `title: ${r.title}`,
165
+ `description: ${r.description}`,
166
+ `content:`,
167
+ r.content.slice(0, 800),
168
+ ].join("\n"))
169
+ .join("\n\n");
170
+ const legacyPrompt = [
171
+ `Shard: ${shard.name}`,
172
+ `Topic: ${topic}`,
173
+ "",
174
+ "Existing memory excerpts:",
175
+ group
176
+ .slice(0, 12)
177
+ .map((r) => `### ${r.title}\n${r.content.slice(0, 1200)}`)
178
+ .join("\n\n"),
179
+ ].join("\n");
180
+ const prompt = asset.user
181
+ ? fillPrompt(asset.user, { topic, memories: memoriesBlock })
182
+ : legacyPrompt;
183
+ const request = {
184
+ system: asset.system,
185
+ prompt,
186
+ temperature: 0,
187
+ maxTokens: 2000,
188
+ };
189
+ let parsed;
190
+ try {
191
+ const response = await llm(request);
192
+ report.llmCalls++;
193
+ const start = response.text.indexOf("{");
194
+ const end = response.text.lastIndexOf("}");
195
+ if (start < 0 || end <= start)
196
+ continue;
197
+ parsed = JSON.parse(response.text.slice(start, end + 1));
198
+ }
199
+ catch {
200
+ continue;
201
+ }
202
+ const digest = parsed.digest;
203
+ if (!digest || !digest.content)
204
+ continue;
205
+ const slug = topic.replace(/[^A-Za-z0-9\u4e00-\u9fff_-]+/g, "-").slice(0, 60) || "digest";
206
+ const file = join(this.store.digestDir(shard), `${slugifyFile(slug)}.md`);
207
+ await fs.mkdir(this.store.digestDir(shard), { recursive: true });
208
+ const body = [
209
+ "---",
210
+ "schema: 1",
211
+ `title: ${JSON.stringify(digest.title ?? topic)}`,
212
+ `updated: ${this.now()}`,
213
+ `sources: ${JSON.stringify(digest.sources ?? [])}`,
214
+ "---",
215
+ "",
216
+ `# ${digest.title ?? topic}`,
217
+ "",
218
+ digest.content,
219
+ "",
220
+ ].join("\n");
221
+ await fs.writeFile(file, body, "utf8");
222
+ written.push(file);
223
+ await this.store.audit({
224
+ ts: this.now(),
225
+ kind: "digest",
226
+ shard: shard.name,
227
+ topic,
228
+ sources: digest.sources ?? [],
229
+ });
230
+ }
231
+ return written;
232
+ }
233
+ }
234
+ function slugifyFile(input) {
235
+ return input.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "") || "digest";
236
+ }
237
+ //# sourceMappingURL=consolidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../src/consolidate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ # HarnMem synonym table v1 (English)
2
+ # Purpose: BM25 query expansion for English queries. English tokenization is word-based, so the same-meaning-rewording gap is much smaller than in Chinese; this table therefore stays small.
3
+ # Format: canonical<TAB>syn1,syn2,... — exactly one ASCII TAB; the second column is comma-separated with no spaces around commas.
4
+ # Rules:
5
+ # - canonical is unique across the file; synonyms within a row must not repeat, and must not equal the canonical.
6
+ # - English terms are lowercase; no explanatory content.
7
+ # - Terms may contain spaces (e.g. rate limit, pull request); no spaces around commas.
8
+ # - Lines may cross-reference each other; expansion is one-hop and deduplicated, never transitive closure.
9
+ # - Used only for query expansion, never changes stored text; terms hit through expansion are down-weighted in scoring (see docs/design/03-retrieval.md).
10
+ # - Keep the shipped table generic (common development/AI vocabulary). Personal or project-specific terms belong in the user's <home>/data/synonyms.en.txt copy, never in the repository.
11
+ # Language files: the engine loads every data/synonyms.<lang>.txt it finds (this file = English, data/synonyms.zh.txt = Chinese); the <home> copy of a filename overrides the shipped default of the same name. Add a language by adding data/synonyms.<lang>.txt — no code change.
12
+ # Maintenance: add rows grouped by topic; verify changes with a reworded `harnmem search` query. The repository eval suite uses its own fixture (evals/data/synonyms.zh.tsv), so it does not cover edits to this file.
13
+
14
+ ## Development workflow
15
+ deploy deployment,release,ship
16
+ install setup,provision
17
+ upgrade update,bump
18
+ rollback revert,undo
19
+ build compile,bundle
20
+
21
+ ## Errors and debugging
22
+ bug defect,regression
23
+ error failure,exception,issue
24
+ fix patch,resolve
25
+ debug diagnose,troubleshoot
26
+ memory leak leak
27
+
28
+ ## Configuration and dependencies
29
+ config configuration,setting
30
+ dependency dep,package,library
31
+
32
+ ## Code refactoring
33
+ refactor rewrite,restructure
34
+
35
+ ## Version control and collaboration
36
+ branch feature branch
37
+ commit checkin
38
+ pull request pr,merge request,mr
39
+ review code review,cr
40
+
41
+ ## Testing and quality
42
+ test spec,suite
43
+ coverage code coverage
44
+ lint linter,static check
45
+ eval evaluation,benchmark
46
+ baseline bench,reference score
47
+
48
+ ## AI / LLM / memory
49
+ agent assistant,bot
50
+ memory memories
51
+ embedding embed,vectorize
52
+ context context window,ctx
53
+ prompt system prompt,instruction
54
+ token tokens
55
+ session conversation,thread
56
+ retrieval recall,search
57
+ decay aging,downweight
58
+ dedupe deduplicate,dedup
59
+ archive cold storage
60
+ hook callback,lifecycle hook
61
+ plugin extension,addon
@@ -0,0 +1,157 @@
1
+ # HarnMem synonym table v1 (Chinese)
2
+ # Purpose: BM25 query expansion / index-side normalization / Chinese near-synonym recall. Zero-dependency plain text, loaded by the engine at startup.
3
+ # Format: canonical<TAB>syn1,syn2,... — exactly one ASCII TAB; the second column is comma-separated with no spaces around commas.
4
+ # Rules:
5
+ # - canonical is unique across the file; synonyms within a row must not repeat, and must not equal the canonical.
6
+ # - English terms are lowercase; Chinese keeps common colloquial forms/abbreviations; no explanatory content.
7
+ # - Terms may contain spaces (e.g. rate limit, pull request); no spaces around commas.
8
+ # - Lines may cross-reference each other (e.g. deploy→release, release→deploy); expansion is one-hop and deduplicated, never transitive closure.
9
+ # - Used only for query expansion, never changes stored text; terms hit through expansion are down-weighted in scoring (see docs/design/03-retrieval.md).
10
+ # - Keep the shipped table generic (common development/AI vocabulary). Personal or project-specific domain terms belong in the user's <home>/data/synonyms.zh.txt copy, never in the repository.
11
+ # Language files: the engine loads every data/synonyms.<lang>.txt it finds (this file = Chinese, data/synonyms.en.txt = English); the <home> copy of a filename overrides the shipped default of the same name. Add a language by adding data/synonyms.<lang>.txt — no code change.
12
+ # Maintenance: add rows grouped by topic; verify changes with a reworded `harnmem search` query. The repository eval suite uses its own fixture (evals/data/synonyms.zh.tsv), so it does not cover edits to this file.
13
+
14
+ ## Development workflow
15
+ 部署 上线,发布,rollout,deploy
16
+ 上线 部署,发布,release,ship
17
+ 发布 上线,发版,出包,release
18
+ 回滚 rollback,退回,恢复版本
19
+ 灰度 金丝雀,canary,灰度发布
20
+ 打包 构建,build,编译产物
21
+ 构建 打包,build,compile
22
+ 流水线 pipeline,CI,持续集成
23
+ 持续集成 CI,流水线
24
+ 持续交付 CD,持续部署
25
+ 环境 env,环境配置,environment
26
+ 生产环境 prod,线上,production
27
+ 预发环境 staging,预发布
28
+ 本地环境 local,本机
29
+ 压测 压力测试,benchmark
30
+ 验证 校验,validate,检查
31
+ 监控 monitor,告警观测
32
+ 告警 报警,alert,通知
33
+ 日志 log,运行日志,logs
34
+ 排查 定位,诊断,troubleshoot
35
+ 修复 fix,修补,改正
36
+ 故障 事故,incident,宕机
37
+ 限流 rate limit,流控
38
+ 熔断 circuit breaker
39
+ 降级 fallback,退化
40
+ 缓存 cache,缓存层
41
+ 队列 queue,消息队列
42
+ 定时任务 cron,定时器
43
+ 后台任务 worker,异步任务
44
+
45
+ ## Errors and debugging
46
+ 报错 错误,异常,error
47
+ 异常 报错,错误,exception
48
+ 错误 报错,异常,error
49
+ 崩溃 crash,闪退,挂了
50
+ 卡死 hang,无响应,死锁
51
+ 超时 timeout,逾时
52
+ 内存泄漏 memory leak,泄漏
53
+ 堆栈 stack,调用栈,traceback
54
+ 断点 breakpoint,调试点
55
+ 调试 debug,排查
56
+ 复现 重现,repro
57
+ 根因 root cause,根本原因
58
+ 绕开 workaround,规避,临时方案
59
+ 兜底 fallback,保底
60
+ 空指针 null,undefined,空引用
61
+ 越界 out of range,数组越界
62
+
63
+ ## Configuration and dependencies
64
+ 配置 设置,config,配置项
65
+ 环境变量 env,环境配置
66
+ 依赖 包,dependency,库
67
+ 安装 install,装,部署依赖
68
+ 升级 update,更新版本,bump
69
+ 降级版本 downgrade,回退版本
70
+ 版本号 version,ver
71
+ 锁文件 lockfile,lock
72
+ 镜像源 registry,源
73
+ 代理 proxy,代理服务器
74
+ 密钥 key,secret,凭证
75
+ 令牌 token,access token
76
+ 授权 auth,鉴权,认证
77
+ 登录 signin,login,登陆
78
+
79
+ ## Code refactoring
80
+ 重构 refactor,重写,整理结构
81
+ 重写 重构,rewrite
82
+ 抽取公共逻辑 抽公共,extract,提取
83
+ 解耦 decouple,拆分
84
+ 耦合 coupling,强依赖
85
+ 死代码 dead code,无用代码
86
+ 命名 naming,取名
87
+ 注释 comment,文档注释
88
+ 类型定义 type,interface,接口定义
89
+ 接口 API,impl
90
+ 补丁 patch,hotfix,热修
91
+ 回退提交 revert,撤销,撤销提交
92
+
93
+ ## Version control and collaboration
94
+ 提交 commit,提交代码,checkin
95
+ 推送 push,推到远端
96
+ 拉取 pull,拉代码
97
+ 合并 merge,合入
98
+ 分支 branch,feature分支
99
+ 冲突 conflict,代码冲突
100
+ 评审 review,code review,CR
101
+ 变更请求 PR,pull request,MR
102
+ 标签 tag,版本标签
103
+ 发布说明 changelog,变更日志
104
+ 问题单 issue,工单,ticket
105
+
106
+ ## Testing and quality
107
+ 测试 test,单测,用例
108
+ 单元测试 单测,unit test
109
+ 集成测试 联调,integration test
110
+ 端到端测试 e2e,端到端
111
+ 回归测试 回归,regression
112
+ 冒烟测试 smoke test,smoke
113
+ 覆盖率 coverage,覆盖
114
+ 断言 assert,校验
115
+ 基准测试 benchmark,基准
116
+ 用例 case,测试用例,spec
117
+ 静态检查 lint,格式检查
118
+ 类型检查 typecheck,类型校验
119
+ 门槛 门禁,gate,阈值
120
+
121
+ ## AI / LLM / memory
122
+ 提示词 prompt,系统提示,instruction
123
+ 上下文 context,上下文窗口,ctx
124
+ 令牌数 token数,tokens
125
+ 嵌入 embedding,向量化,embed
126
+ 向量 vector,向量库
127
+ 检索 recall,召回,search
128
+ 召回 检索,recall
129
+ 重排 rerank,重排序
130
+ 微调 finetune,微调训练
131
+ 推理 inference,推理调用
132
+ 幻觉 hallucination,编造
133
+ 记忆 memory,长期记忆,memories
134
+ 会话 session,对话会话,conversation
135
+ 抽取 extraction,提取,extract
136
+ 固化 consolidate,consolidation,整理
137
+ 去重 dedupe,dedup,去重复
138
+ 衰减 decay,降权
139
+ 归档 archive,封存
140
+ 摘要 summary,总结摘要
141
+ 评测 eval,评估,测评
142
+ 基准 benchmark,基线
143
+ 插件 plugin,扩展,addon
144
+ 钩子 hook,callback,生命周期钩子
145
+
146
+ ## Documentation and communication
147
+ 文档 doc,说明文档
148
+ 规范 约定,convention,约定俗成
149
+ 决策 决定,decision
150
+ 原因 理由,why
151
+ 教训 经验,lesson
152
+ 坑 陷阱,pitfall,踩坑
153
+ 待办 TODO,待办事项
154
+ 注意事项 注意点,caveat
155
+ 示例 例子,sample,example
156
+ 路径 path,目录
157
+ 文件名 filename,文件名称