claude-mem-lite 3.65.0 → 3.66.1
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/format-utils.mjs +2 -1
- package/haiku-client.mjs +39 -6
- package/hook-context.mjs +5 -4
- package/hook-llm.mjs +7 -5
- package/hook-memory.mjs +4 -3
- package/hook-optimize.mjs +11 -10
- package/hook-precompact.mjs +12 -12
- package/hook-shared.mjs +122 -5
- package/hook.mjs +40 -14
- package/lib/citation-tracker.mjs +59 -5
- package/lib/db-backup.mjs +2 -1
- package/lib/deferred-work.mjs +1 -1
- package/lib/err-sampler.mjs +1 -1
- package/lib/hook-telemetry.mjs +1 -1
- package/lib/keyctx-marker.mjs +74 -0
- package/lib/maintain-core.mjs +2 -1
- package/lib/metrics.mjs +1 -1
- package/lib/save-enrich.mjs +3 -2
- package/lib/search-core.mjs +2 -1
- package/lib/stats-core.mjs +4 -3
- package/lib/stats-quality.mjs +2 -1
- package/lib/time-constants.mjs +21 -0
- package/mem-cli.mjs +6 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +3 -1
- package/registry-enricher.mjs +2 -2
- package/registry-recommend.mjs +3 -2
- package/scoring-sql.mjs +8 -7
- package/scripts/pre-tool-recall.js +2 -1
- package/scripts/user-prompt-search.js +2 -1
- package/search-scoring.mjs +2 -1
- package/server.mjs +10 -4
- package/source-files.mjs +6 -0
- package/tier.mjs +4 -3
package/scoring-sql.mjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { buildNotLowSignalSql } from './lib/low-signal-patterns.mjs';
|
|
5
5
|
|
|
6
|
+
import { DAY_MS } from './lib/time-constants.mjs';
|
|
6
7
|
// ─── Why these multipliers exist (read before "simplifying" them) ────────────
|
|
7
8
|
//
|
|
8
9
|
// The recency-decay, type-quality, project-boost, importance, cite, and noise
|
|
@@ -33,14 +34,14 @@ import { buildNotLowSignalSql } from './lib/low-signal-patterns.mjs';
|
|
|
33
34
|
|
|
34
35
|
/** Recency half-life per observation type (in milliseconds) */
|
|
35
36
|
export const DECAY_HALF_LIFE_BY_TYPE = {
|
|
36
|
-
decision: 90 *
|
|
37
|
-
discovery: 60 *
|
|
38
|
-
feature: 30 *
|
|
39
|
-
bugfix: 14 *
|
|
40
|
-
refactor: 14 *
|
|
41
|
-
change: 7 *
|
|
37
|
+
decision: 90 * DAY_MS, // 90 days — architectural decisions persist
|
|
38
|
+
discovery: 60 * DAY_MS, // 60 days — learned patterns last
|
|
39
|
+
feature: 30 * DAY_MS, // 30 days — feature work is mid-range
|
|
40
|
+
bugfix: 14 * DAY_MS, // 14 days — bugs are usually one-off
|
|
41
|
+
refactor: 14 * DAY_MS, // 14 days — code cleanup
|
|
42
|
+
change: 7 * DAY_MS, // 7 days — routine changes decay fast
|
|
42
43
|
};
|
|
43
|
-
export const DEFAULT_DECAY_HALF_LIFE_MS = 14 *
|
|
44
|
+
export const DEFAULT_DECAY_HALF_LIFE_MS = 14 * DAY_MS;
|
|
44
45
|
|
|
45
46
|
// ─── BM25 Weight Constants ──────────────────────────────────────────────────
|
|
46
47
|
// Single source of truth for FTS5 BM25 weight expressions.
|
|
@@ -20,6 +20,7 @@ import { recordMetric } from '../lib/metrics.mjs';
|
|
|
20
20
|
import { presentIdents } from '../lib/lesson-idents.mjs';
|
|
21
21
|
import { neutralizeContextDelimiters } from '../format-utils.mjs';
|
|
22
22
|
|
|
23
|
+
import { DAY_MS } from '../lib/time-constants.mjs';
|
|
23
24
|
// CLAUDE_MEM_DIR matches schema.mjs / main CLI — one env var sandboxes the
|
|
24
25
|
// whole system. CLAUDE_MEM_DB_PATH / CLAUDE_MEM_RUNTIME_DIR remain as
|
|
25
26
|
// per-component overrides for tests that mix isolated + real paths.
|
|
@@ -372,7 +373,7 @@ try {
|
|
|
372
373
|
const fileMatch = fileMatchClause('of2');
|
|
373
374
|
const fileParams = fileMatchParams(filePath);
|
|
374
375
|
// 60-day lookback to avoid surfacing ancient observations
|
|
375
|
-
const cutoff = Date.now() - 60 *
|
|
376
|
+
const cutoff = Date.now() - 60 * DAY_MS;
|
|
376
377
|
|
|
377
378
|
// Surface actionable lessons first, then high-importance bugfix/decision observations.
|
|
378
379
|
// Priority: 1) observations with lesson_learned (most actionable for preventing repeat bugs)
|
|
@@ -18,6 +18,7 @@ import { recommendSkill } from '../registry-recommend.mjs';
|
|
|
18
18
|
import { recordHookError } from '../lib/hook-telemetry.mjs';
|
|
19
19
|
import { atomicWriteFileSync } from '../lib/atomic-write.mjs';
|
|
20
20
|
|
|
21
|
+
import { DAY_MS } from '../lib/time-constants.mjs';
|
|
21
22
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
22
23
|
|
|
23
24
|
// Telemetry sink (lib/hook-telemetry.mjs contract): env override for tests, else
|
|
@@ -37,7 +38,7 @@ const injectedIdsFileFor = (sessionId) =>
|
|
|
37
38
|
// gated by explicit "before/previously/记得" prompts where breadth is the
|
|
38
39
|
// point). Env override for projects that want broader recall or to A/B.
|
|
39
40
|
const MAX_RESULTS = Number(process.env.CLAUDE_MEM_UPS_MAX_RESULTS || 3);
|
|
40
|
-
const LOOKBACK_MS = 60 *
|
|
41
|
+
const LOOKBACK_MS = 60 * DAY_MS; // 60 days
|
|
41
42
|
|
|
42
43
|
// v2.56.x: Past-similar-questions fallback row cap. Cut from 3 → 1 after
|
|
43
44
|
// 30d transcript scan (#8062 follow-up, 2026-05-09) showed UPS prompt-fallback
|
package/search-scoring.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { porterStem } from './tfidf.mjs';
|
|
|
11
11
|
import { CLI_INVOKE } from './cli-path.mjs';
|
|
12
12
|
import { liveObsFilterSql } from './lib/inject-search-core.mjs';
|
|
13
13
|
|
|
14
|
+
import { DAY_MS } from './lib/time-constants.mjs';
|
|
14
15
|
// ─── MCP Server Instructions Builder ───────────────────────────────────────
|
|
15
16
|
// Phase A (v2.31.3+): when quiet=true, drops WHEN-TO-USE proactive-trigger and
|
|
16
17
|
// Decision-rules sections; keeps the irreducible CLI/MCP tool list. Intended
|
|
@@ -302,7 +303,7 @@ export function runIdleCleanup(db) {
|
|
|
302
303
|
|
|
303
304
|
db.transaction(() => {
|
|
304
305
|
for (const { types, days } of staleThresholds) {
|
|
305
|
-
const cutoff = Date.now() - days *
|
|
306
|
+
const cutoff = Date.now() - days * DAY_MS;
|
|
306
307
|
|
|
307
308
|
const marked = db.prepare(`
|
|
308
309
|
UPDATE observations SET compressed_into = ${COMPRESSED_PENDING_PURGE}
|
package/server.mjs
CHANGED
|
@@ -52,6 +52,7 @@ import { probeOtherSources as probeIdSources, bucketIdTokens, splitDeferredToken
|
|
|
52
52
|
import { saveObservation } from './lib/save-observation.mjs';
|
|
53
53
|
import { applyObsUpdate } from './lib/observation-write.mjs';
|
|
54
54
|
import { EXPORT_COLUMNS_SQL } from './lib/export-columns.mjs';
|
|
55
|
+
import { liveObsFilterSql } from './lib/inject-search-core.mjs';
|
|
55
56
|
import { recallByFile } from './lib/recall-core.mjs';
|
|
56
57
|
import { fetchRecent } from './lib/recent-core.mjs';
|
|
57
58
|
import { AUTO_MERGE_THRESHOLD } from './lib/dedup-constants.mjs';
|
|
@@ -1032,7 +1033,7 @@ server.registerTool(
|
|
|
1032
1033
|
if (args.project) args = { ...args, project: resolveProject(args.project) };
|
|
1033
1034
|
const preview = args.preview !== false;
|
|
1034
1035
|
const ageDays = args.age_days ?? 30;
|
|
1035
|
-
const cutoff = Date.now() - ageDays *
|
|
1036
|
+
const cutoff = Date.now() - ageDays * DAY_MS;
|
|
1036
1037
|
const candidates = selectCompressionCandidates(db, { cutoff, project: args.project || null });
|
|
1037
1038
|
|
|
1038
1039
|
if (candidates.length === 0) {
|
|
@@ -1181,7 +1182,7 @@ server.registerTool(
|
|
|
1181
1182
|
// only rows a PRIOR run marked (backed up); rows decay marks below wait one cycle.
|
|
1182
1183
|
if (ops.includes('purge_stale')) {
|
|
1183
1184
|
const retainDays = args.retain_days ?? 30;
|
|
1184
|
-
const retainCutoff = Date.now() - retainDays *
|
|
1185
|
+
const retainCutoff = Date.now() - retainDays * DAY_MS;
|
|
1185
1186
|
if (!purgeConfirmed) {
|
|
1186
1187
|
// Dry-run preview (parity with CLI `maintain` without --confirm): the other
|
|
1187
1188
|
// requested non-destructive ops still run below.
|
|
@@ -1687,8 +1688,12 @@ export async function handleExportForTest(db, args) {
|
|
|
1687
1688
|
async function runExport(db, args) {
|
|
1688
1689
|
const wheres = [];
|
|
1689
1690
|
const params = [];
|
|
1690
|
-
|
|
1691
|
-
|
|
1691
|
+
// Composed, not hand-written: the CLI twin (mem-cli.mjs cmdExport) already
|
|
1692
|
+
// routes through liveObsFilterSql, and a hand-rolled copy here is how the
|
|
1693
|
+
// live-row predicate drifted apart on other surfaces (P2-11/D#123). With
|
|
1694
|
+
// include_compressed the compressed half is dropped but retractions still
|
|
1695
|
+
// are not — tombstone export is opt-in, supersession is never exported.
|
|
1696
|
+
wheres.push(args.include_compressed ? 'superseded_at IS NULL' : liveObsFilterSql(''));
|
|
1692
1697
|
if (args.project) { wheres.push('project = ?'); params.push(_resolveProjectShared(db, args.project)); }
|
|
1693
1698
|
if (args.type) { wheres.push('type = ?'); params.push(args.type); }
|
|
1694
1699
|
// T3-P1-A: surface invalid dates instead of silently dropping the filter — mirrors
|
|
@@ -1801,6 +1806,7 @@ server.registerTool(
|
|
|
1801
1806
|
// Handler extracted to server/fts-check.mjs (v2.41 split).
|
|
1802
1807
|
import { handleMemFtsCheck } from './server/fts-check.mjs';
|
|
1803
1808
|
|
|
1809
|
+
import { DAY_MS } from './lib/time-constants.mjs';
|
|
1804
1810
|
server.registerTool(
|
|
1805
1811
|
'mem_fts_check',
|
|
1806
1812
|
{
|
package/source-files.mjs
CHANGED
|
@@ -123,6 +123,12 @@ export const SOURCE_FILES = [
|
|
|
123
123
|
// scripts/user-prompt-search.js + scripts/pre-tool-recall.js. Under lib/ for
|
|
124
124
|
// the same scripts-dir-rename reason as mem-override.mjs above.
|
|
125
125
|
'lib/injected-ids.mjs',
|
|
126
|
+
// P2-13 (narrowed): millisecond time units, single-sourced from the four
|
|
127
|
+
// modules that each declared their own DAY_MS. Leaf module, zero imports.
|
|
128
|
+
'lib/time-constants.mjs',
|
|
129
|
+
// D#124: Key Context marker write + injection_count bump, shared by
|
|
130
|
+
// handleSessionStart and handlePreCompact. Statically imported by hook.mjs.
|
|
131
|
+
'lib/keyctx-marker.mjs',
|
|
126
132
|
// P2-11: injection-side shared SQL core (live-row filter / clamped decay /
|
|
127
133
|
// injection relevance chain). Statically imported by hook.mjs, hook-memory.mjs,
|
|
128
134
|
// search-engine.mjs AND the standalone hook scripts — missing it from the
|
package/tier.mjs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { DECAY_HALF_LIFE_BY_TYPE } from './utils.mjs';
|
|
6
6
|
|
|
7
|
+
import { DAY_MS } from './lib/time-constants.mjs';
|
|
7
8
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
8
9
|
|
|
9
10
|
const TWO_HOURS_MS = 2 * 3600000;
|
|
@@ -125,7 +126,7 @@ export function relativeTime(epoch, now) {
|
|
|
125
126
|
const diff = Math.max(0, now - epoch);
|
|
126
127
|
if (diff < 60000) return `${Math.floor(diff / 1000)}s ago`;
|
|
127
128
|
if (diff < 3600000) return `${Math.floor(diff / 60000)}min ago`;
|
|
128
|
-
if (diff <
|
|
129
|
-
if (diff < 30 *
|
|
130
|
-
return `${Math.floor(diff / (30 *
|
|
129
|
+
if (diff < DAY_MS) return `${Math.floor(diff / 3600000)}h ago`;
|
|
130
|
+
if (diff < 30 * DAY_MS) return `${Math.floor(diff / DAY_MS)}d ago`;
|
|
131
|
+
return `${Math.floor(diff / (30 * DAY_MS))}mo ago`;
|
|
131
132
|
}
|