instar 1.3.1306 → 1.3.1308
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/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +23 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/JevMemoryPicker.d.ts +171 -0
- package/dist/core/JevMemoryPicker.d.ts.map +1 -0
- package/dist/core/JevMemoryPicker.js +440 -0
- package/dist/core/JevMemoryPicker.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +6 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +69 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts +5 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +18 -1
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
- package/dist/core/WriteDomainRegistry.js +16 -0
- package/dist/core/WriteDomainRegistry.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +23 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/monitoring/ResumeQueue.d.ts +8 -0
- package/dist/monitoring/ResumeQueue.d.ts.map +1 -1
- package/dist/monitoring/ResumeQueue.js +8 -1
- package/dist/monitoring/ResumeQueue.js.map +1 -1
- package/dist/scaffold/templates.d.ts +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +7 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +1 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +3 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +42 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/scaffold/templates.ts +8 -0
- package/upgrades/{1.3.1306.md → 1.3.1307.md} +47 -0
- package/upgrades/1.3.1308.md +74 -0
- package/upgrades/side-effects/age-limit-coordinator-r3.md +201 -0
- package/upgrades/side-effects/jev-memory-picker.md +101 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export declare const JEV_MEMORY_PICKER_FEATURE = "jev-memory-picker";
|
|
2
|
+
/** The documented standing-rule marker: a line carrying it always loads. */
|
|
3
|
+
export declare const PINNED_MARKER = "<!-- pinned -->";
|
|
4
|
+
/** Claude Code's positional load limits for MEMORY.md (measured: the cut falls
|
|
5
|
+
* where the running character count passes 25,000; at most 200 lines). */
|
|
6
|
+
export declare const POSITIONAL_MAX_CHARS = 25000;
|
|
7
|
+
export declare const POSITIONAL_MAX_LINES = 200;
|
|
8
|
+
/** Ranked lines added beyond the cut, and their character cap (Claude Code
|
|
9
|
+
* still loads the positional prefix itself; the picker can only add). */
|
|
10
|
+
export declare const DEFAULT_INJECT_LINES = 40;
|
|
11
|
+
export declare const DEFAULT_INJECT_MAX_CHARS = 10000;
|
|
12
|
+
export declare const DEFAULT_TIMEOUT_MS = 1500;
|
|
13
|
+
export declare const TIMEOUT_MIN_MS = 100;
|
|
14
|
+
export declare const TIMEOUT_MAX_MS = 3000;
|
|
15
|
+
/** Extra wait past the fetch abort before the caller stops waiting regardless. */
|
|
16
|
+
export declare const RACE_SLACK_MS = 250;
|
|
17
|
+
export declare const DEFAULT_DAILY_CALL_CAP = 300;
|
|
18
|
+
export declare const MAX_IN_FLIGHT = 2;
|
|
19
|
+
export declare const MAX_INDEX_BYTES: number;
|
|
20
|
+
export declare const MAX_CONTEXT_CHARS = 4000;
|
|
21
|
+
export declare const MAX_ENTRY_CHARS = 500;
|
|
22
|
+
export declare const MAX_GLOSSARY_LINES = 20;
|
|
23
|
+
export declare const MAX_GLOSSARY_CHARS = 200;
|
|
24
|
+
export declare const KEY_REREAD_MS: number;
|
|
25
|
+
export declare const INJECT_HEADER = "--- MEMORY INDEX: RANKED ENTRIES BEYOND THE LOAD CUT ---";
|
|
26
|
+
export declare const INJECT_FOOTER = "--- END MEMORY INDEX RANKED ENTRIES ---";
|
|
27
|
+
/**
|
|
28
|
+
* The frozen wordings (the note's B and C). Score = their mean: C excludes
|
|
29
|
+
* general principles, which demotes the generic lessons B alone over-ranks.
|
|
30
|
+
* Changing a wording is a reviewed code change, never config.
|
|
31
|
+
*/
|
|
32
|
+
export declare const QUESTION_B: (line: string) => string;
|
|
33
|
+
export declare const QUESTION_C: (line: string) => string;
|
|
34
|
+
export interface JevMemoryPickerConfig {
|
|
35
|
+
/** Omitted ⇒ the developmentAgent gate decides; false is the kill switch. */
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
mode?: 'shadow' | 'inject';
|
|
38
|
+
model?: string;
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
injectLines?: number;
|
|
41
|
+
injectMaxChars?: number;
|
|
42
|
+
glossary?: string[];
|
|
43
|
+
dailyCallCap?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface IndexEntry {
|
|
46
|
+
/** 1-based line number in the file. */
|
|
47
|
+
line: number;
|
|
48
|
+
/** `L<line>-<sha8>` — stable enough to join rows against a file snapshot. */
|
|
49
|
+
id: string;
|
|
50
|
+
/** The line with the pinned marker stripped. */
|
|
51
|
+
text: string;
|
|
52
|
+
pinned: boolean;
|
|
53
|
+
/** Inside the prefix Claude Code loads by position. */
|
|
54
|
+
inPrefix: boolean;
|
|
55
|
+
}
|
|
56
|
+
export type PickReason = 'fits' | 'no-index' | 'oversize-index' | 'no-context' | 'disabled-no-key' | 'daily-cap' | 'busy' | 'scrub-error' | 'timeout' | 'http-error' | 'model-mismatch' | 'no-answers';
|
|
57
|
+
export interface PickResult {
|
|
58
|
+
outcome: 'ranked' | 'fallback' | 'skipped';
|
|
59
|
+
reason?: PickReason;
|
|
60
|
+
/** Entries Claude Code would NOT load by itself, to add: pinned first, then by rank. */
|
|
61
|
+
inject: IndexEntry[];
|
|
62
|
+
scores: Map<number, number>;
|
|
63
|
+
}
|
|
64
|
+
/** Parse the index: every `- ` line is an entry; the prefix is what loads by position. */
|
|
65
|
+
export declare function parseIndex(content: string): IndexEntry[];
|
|
66
|
+
/** The entries Jev ranks: non-pinned, beyond the positional cut. */
|
|
67
|
+
export declare function candidates(entries: IndexEntry[]): IndexEntry[];
|
|
68
|
+
/**
|
|
69
|
+
* Compose what to add: pinned entries beyond the cut (file order), then the
|
|
70
|
+
* `ranked` entries, stopping at `maxLines` entries or `maxChars` characters.
|
|
71
|
+
* With no ranking (any Jev failure) only the pinned entries are added — with
|
|
72
|
+
* nothing pinned, that is exactly today's load.
|
|
73
|
+
*/
|
|
74
|
+
export declare function compose(entries: IndexEntry[], ranked: IndexEntry[], maxLines: number, maxChars: number): IndexEntry[];
|
|
75
|
+
/** Order candidates by score, highest first; ties by file position. Unscored entries are dropped. */
|
|
76
|
+
export declare function rankByScore(cands: IndexEntry[], scores: Map<number, number>): IndexEntry[];
|
|
77
|
+
/**
|
|
78
|
+
* Derive the memory index path Claude Code uses for a project. Returns null
|
|
79
|
+
* unless `configDir` is an absolute path inside `homeDir` whose last segment
|
|
80
|
+
* starts with `.claude`. The project key replaces every non-alphanumeric
|
|
81
|
+
* character with `-` (Claude Code's own scheme), so it can hold no separator.
|
|
82
|
+
* Pure: `resolveMemoryIndexPath` repeats the checks on the real paths.
|
|
83
|
+
*/
|
|
84
|
+
export declare function memoryIndexPath(configDir: unknown, projectDir: unknown, homeDir: string): string | null;
|
|
85
|
+
/**
|
|
86
|
+
* The same derivation on symlink-resolved paths: a `configDir` that is a link
|
|
87
|
+
* out of the home directory is refused, and so is an index file that is itself
|
|
88
|
+
* a symlink. Returns null when refused or absent.
|
|
89
|
+
*/
|
|
90
|
+
export declare function resolveMemoryIndexPath(configDir: unknown, projectDir: unknown, homeDir: string): Promise<string | null>;
|
|
91
|
+
/** Render the inject block, or '' when there is nothing to add. */
|
|
92
|
+
export declare function renderInjectBlock(inject: IndexEntry[]): string;
|
|
93
|
+
/** Which session-start event asked (logged on every row). */
|
|
94
|
+
export type PickSource = 'startup' | 'resume' | 'clear' | 'compact' | 'other';
|
|
95
|
+
export declare function pickSource(v: unknown): PickSource;
|
|
96
|
+
declare const PICKER_DEFAULTS: {
|
|
97
|
+
mode: "shadow" | "inject";
|
|
98
|
+
model: string;
|
|
99
|
+
timeoutMs: number;
|
|
100
|
+
injectLines: number;
|
|
101
|
+
injectMaxChars: number;
|
|
102
|
+
glossary: string[];
|
|
103
|
+
dailyCallCap: number;
|
|
104
|
+
};
|
|
105
|
+
export interface JevMemoryPickerDeps {
|
|
106
|
+
/** Live config read per request, `enabled` already gate-resolved. */
|
|
107
|
+
getConfig: () => JevMemoryPickerConfig | undefined;
|
|
108
|
+
/** Resolves the vault key; called at construction and at most every KEY_REREAD_MS after a miss. */
|
|
109
|
+
readKey: () => string | null;
|
|
110
|
+
logPath: string;
|
|
111
|
+
metrics?: {
|
|
112
|
+
record(r: Record<string, unknown>): void;
|
|
113
|
+
} | null;
|
|
114
|
+
fetchImpl?: typeof fetch;
|
|
115
|
+
now?: () => number;
|
|
116
|
+
/** The home directory the index path must sit inside (default os.homedir()). */
|
|
117
|
+
homeDir?: string;
|
|
118
|
+
}
|
|
119
|
+
export declare class JevMemoryPicker {
|
|
120
|
+
private readonly deps;
|
|
121
|
+
private readonly audit;
|
|
122
|
+
private cachedKey;
|
|
123
|
+
private keyReadAt;
|
|
124
|
+
private inFlight;
|
|
125
|
+
private capDay;
|
|
126
|
+
private capCount;
|
|
127
|
+
/** Test seam: the latest detached shadow run. */
|
|
128
|
+
lastRun: Promise<PickResult | null>;
|
|
129
|
+
readonly homeDir: string;
|
|
130
|
+
constructor(deps: JevMemoryPickerDeps);
|
|
131
|
+
/** Resolves when every queued log row is written (tests, shutdown). */
|
|
132
|
+
flush(): Promise<void>;
|
|
133
|
+
private now;
|
|
134
|
+
private refreshKey;
|
|
135
|
+
/** The live config, normalised. Null when disabled (the kill switch). */
|
|
136
|
+
config(): typeof PICKER_DEFAULTS | null;
|
|
137
|
+
/**
|
|
138
|
+
* Rank the index at `indexPath` against `context` and log one row. Never
|
|
139
|
+
* rejects: every failure resolves to "add only the pinned entries beyond the
|
|
140
|
+
* cut" (with nothing pinned, today's load exactly).
|
|
141
|
+
*/
|
|
142
|
+
pick(indexPath: string, context: string, source?: PickSource): Promise<PickResult>;
|
|
143
|
+
/** One bounded Jev call. Resolves to scores, or to a fallback reason. */
|
|
144
|
+
private rank;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The production wiring, shared by server.ts and the E2E test: the live
|
|
148
|
+
* `intelligence.jevMemoryPicker` block wins over the boot block, and an
|
|
149
|
+
* omitted `enabled` is decided by the developmentAgent gate.
|
|
150
|
+
*/
|
|
151
|
+
export declare function buildJevMemoryPicker(opts: {
|
|
152
|
+
readLiveIntelligence: () => unknown;
|
|
153
|
+
bootBlock?: JevMemoryPickerConfig;
|
|
154
|
+
developmentAgent?: boolean;
|
|
155
|
+
readSecret: (name: string) => unknown;
|
|
156
|
+
stateDir: string;
|
|
157
|
+
metrics?: JevMemoryPickerDeps['metrics'];
|
|
158
|
+
fetchImpl?: typeof fetch;
|
|
159
|
+
now?: () => number;
|
|
160
|
+
homeDir?: string;
|
|
161
|
+
}): JevMemoryPicker;
|
|
162
|
+
/** Build the opening-context text from a topic's name and last messages. */
|
|
163
|
+
export declare function topicOpeningContext(topic: {
|
|
164
|
+
topicName?: string | null;
|
|
165
|
+
recentMessages?: Array<{
|
|
166
|
+
fromUser?: boolean;
|
|
167
|
+
text?: string;
|
|
168
|
+
}>;
|
|
169
|
+
} | null | undefined, extra?: unknown): string;
|
|
170
|
+
export {};
|
|
171
|
+
//# sourceMappingURL=JevMemoryPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JevMemoryPicker.d.ts","sourceRoot":"","sources":["../../src/core/JevMemoryPicker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JevMemoryPicker — ranks the Claude Code memory index (MEMORY.md, one line per
|
|
3
|
+
* memory) against a session's opening context, so the relevant entries can
|
|
4
|
+
* load instead of whichever entries happen to sit first in the file.
|
|
5
|
+
*
|
|
6
|
+
* Spec: docs/specs/jev-memory-picker.md
|
|
7
|
+
* Evidence: docs/research/jev/field-notes/2026-09-30-idea2-memory-selection.md
|
|
8
|
+
*
|
|
9
|
+
* CONTRACT:
|
|
10
|
+
* - Signal only. It chooses which already-saved index lines are offered to a
|
|
11
|
+
* session; it cannot block, send or change anything. In `shadow` mode (the
|
|
12
|
+
* default) it changes nothing at all: it logs what it WOULD inject.
|
|
13
|
+
* - Fail-open. Every failure (no key, timeout, HTTP error, model mismatch,
|
|
14
|
+
* scrub error, cap, busy) falls back to positional order — today's loader.
|
|
15
|
+
* - Fixed top-N by rank, never a confidence cutoff: Jev's probabilities here
|
|
16
|
+
* are low and bunched (the note: 6% of pairs reach 0.5).
|
|
17
|
+
* - Rows carry line ids, scores and counts — never memory or message text.
|
|
18
|
+
* - Everything sent to Jev is secret-scrubbed first; every call is metered.
|
|
19
|
+
*/
|
|
20
|
+
import fsp from 'node:fs/promises';
|
|
21
|
+
import os from 'node:os';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import crypto from 'node:crypto';
|
|
24
|
+
import { scrubForStore } from './durableSecretScrub.js';
|
|
25
|
+
import { BoundedJsonlAudit } from './BoundedJsonlAudit.js';
|
|
26
|
+
import { resolveDevAgentGate } from './devAgentGate.js';
|
|
27
|
+
export const JEV_MEMORY_PICKER_FEATURE = 'jev-memory-picker';
|
|
28
|
+
const ENDPOINT = 'https://api.typesafe.ai/v1/systemone';
|
|
29
|
+
/** The documented standing-rule marker: a line carrying it always loads. */
|
|
30
|
+
export const PINNED_MARKER = '<!-- pinned -->';
|
|
31
|
+
/** Claude Code's positional load limits for MEMORY.md (measured: the cut falls
|
|
32
|
+
* where the running character count passes 25,000; at most 200 lines). */
|
|
33
|
+
export const POSITIONAL_MAX_CHARS = 25_000;
|
|
34
|
+
export const POSITIONAL_MAX_LINES = 200;
|
|
35
|
+
/** Ranked lines added beyond the cut, and their character cap (Claude Code
|
|
36
|
+
* still loads the positional prefix itself; the picker can only add). */
|
|
37
|
+
export const DEFAULT_INJECT_LINES = 40;
|
|
38
|
+
export const DEFAULT_INJECT_MAX_CHARS = 10_000;
|
|
39
|
+
export const DEFAULT_TIMEOUT_MS = 1500;
|
|
40
|
+
export const TIMEOUT_MIN_MS = 100;
|
|
41
|
+
export const TIMEOUT_MAX_MS = 3000;
|
|
42
|
+
/** Extra wait past the fetch abort before the caller stops waiting regardless. */
|
|
43
|
+
export const RACE_SLACK_MS = 250;
|
|
44
|
+
export const DEFAULT_DAILY_CALL_CAP = 300;
|
|
45
|
+
export const MAX_IN_FLIGHT = 2;
|
|
46
|
+
export const MAX_INDEX_BYTES = 256 * 1024;
|
|
47
|
+
export const MAX_CONTEXT_CHARS = 4000;
|
|
48
|
+
export const MAX_ENTRY_CHARS = 500;
|
|
49
|
+
export const MAX_GLOSSARY_LINES = 20;
|
|
50
|
+
export const MAX_GLOSSARY_CHARS = 200;
|
|
51
|
+
export const KEY_REREAD_MS = 10 * 60_000;
|
|
52
|
+
export const INJECT_HEADER = '--- MEMORY INDEX: RANKED ENTRIES BEYOND THE LOAD CUT ---';
|
|
53
|
+
export const INJECT_FOOTER = '--- END MEMORY INDEX RANKED ENTRIES ---';
|
|
54
|
+
/**
|
|
55
|
+
* The frozen wordings (the note's B and C). Score = their mean: C excludes
|
|
56
|
+
* general principles, which demotes the generic lessons B alone over-ranks.
|
|
57
|
+
* Changing a wording is a reviewed code change, never config.
|
|
58
|
+
*/
|
|
59
|
+
export const QUESTION_B = (line) => `Saved memory note: "${line}". The note concerns the same subject, system, account, machine or kind of work as the conversation's current request.`;
|
|
60
|
+
export const QUESTION_C = (line) => `Saved memory note: "${line}". The note is about a specific system, account, machine, tool or piece of work that the conversation's current request involves. A general working principle that would apply to any request does not count.`;
|
|
61
|
+
/** Parse the index: every `- ` line is an entry; the prefix is what loads by position. */
|
|
62
|
+
export function parseIndex(content) {
|
|
63
|
+
const lines = content.split('\n');
|
|
64
|
+
const out = [];
|
|
65
|
+
let chars = 0;
|
|
66
|
+
let prefixOpen = true;
|
|
67
|
+
for (let i = 0; i < lines.length; i++) {
|
|
68
|
+
const raw = lines[i];
|
|
69
|
+
// The running count includes the joining newline, as the loader measures the text.
|
|
70
|
+
chars += raw.length + (i > 0 ? 1 : 0);
|
|
71
|
+
if (prefixOpen && (chars > POSITIONAL_MAX_CHARS || i + 1 > POSITIONAL_MAX_LINES))
|
|
72
|
+
prefixOpen = false;
|
|
73
|
+
if (!raw.startsWith('- '))
|
|
74
|
+
continue;
|
|
75
|
+
const pinned = raw.includes(PINNED_MARKER);
|
|
76
|
+
const text = (pinned ? raw.split(PINNED_MARKER).join('') : raw).trimEnd();
|
|
77
|
+
const sha8 = crypto.createHash('sha256').update(text, 'utf8').digest('hex').slice(0, 8);
|
|
78
|
+
out.push({ line: i + 1, id: `L${i + 1}-${sha8}`, text, pinned, inPrefix: prefixOpen });
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** The entries Jev ranks: non-pinned, beyond the positional cut. */
|
|
83
|
+
export function candidates(entries) {
|
|
84
|
+
return entries.filter((e) => !e.pinned && !e.inPrefix);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Compose what to add: pinned entries beyond the cut (file order), then the
|
|
88
|
+
* `ranked` entries, stopping at `maxLines` entries or `maxChars` characters.
|
|
89
|
+
* With no ranking (any Jev failure) only the pinned entries are added — with
|
|
90
|
+
* nothing pinned, that is exactly today's load.
|
|
91
|
+
*/
|
|
92
|
+
export function compose(entries, ranked, maxLines, maxChars) {
|
|
93
|
+
const out = [];
|
|
94
|
+
let chars = 0;
|
|
95
|
+
for (const e of [...entries.filter((x) => x.pinned && !x.inPrefix), ...ranked]) {
|
|
96
|
+
if (out.length >= maxLines || chars + e.text.length + 1 > maxChars)
|
|
97
|
+
break;
|
|
98
|
+
out.push(e);
|
|
99
|
+
chars += e.text.length + 1;
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** Order candidates by score, highest first; ties by file position. Unscored entries are dropped. */
|
|
104
|
+
export function rankByScore(cands, scores) {
|
|
105
|
+
return cands
|
|
106
|
+
.filter((e) => scores.has(e.line))
|
|
107
|
+
.sort((a, b) => scores.get(b.line) - scores.get(a.line) || a.line - b.line);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Derive the memory index path Claude Code uses for a project. Returns null
|
|
111
|
+
* unless `configDir` is an absolute path inside `homeDir` whose last segment
|
|
112
|
+
* starts with `.claude`. The project key replaces every non-alphanumeric
|
|
113
|
+
* character with `-` (Claude Code's own scheme), so it can hold no separator.
|
|
114
|
+
* Pure: `resolveMemoryIndexPath` repeats the checks on the real paths.
|
|
115
|
+
*/
|
|
116
|
+
export function memoryIndexPath(configDir, projectDir, homeDir) {
|
|
117
|
+
if (typeof configDir !== 'string' || typeof projectDir !== 'string')
|
|
118
|
+
return null;
|
|
119
|
+
if (!path.isAbsolute(configDir) || !path.isAbsolute(projectDir) || !path.isAbsolute(homeDir))
|
|
120
|
+
return null;
|
|
121
|
+
const dir = path.resolve(configDir);
|
|
122
|
+
const home = path.resolve(homeDir);
|
|
123
|
+
if (!dir.startsWith(home + path.sep))
|
|
124
|
+
return null;
|
|
125
|
+
if (!path.basename(dir).startsWith('.claude'))
|
|
126
|
+
return null;
|
|
127
|
+
const key = path.resolve(projectDir).replace(/[^a-zA-Z0-9]/g, '-');
|
|
128
|
+
return path.join(dir, 'projects', key, 'memory', 'MEMORY.md');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The same derivation on symlink-resolved paths: a `configDir` that is a link
|
|
132
|
+
* out of the home directory is refused, and so is an index file that is itself
|
|
133
|
+
* a symlink. Returns null when refused or absent.
|
|
134
|
+
*/
|
|
135
|
+
export async function resolveMemoryIndexPath(configDir, projectDir, homeDir) {
|
|
136
|
+
if (memoryIndexPath(configDir, projectDir, homeDir) === null)
|
|
137
|
+
return null;
|
|
138
|
+
try {
|
|
139
|
+
const realDir = await fsp.realpath(configDir);
|
|
140
|
+
const realHome = await fsp.realpath(homeDir);
|
|
141
|
+
const file = memoryIndexPath(realDir, projectDir, realHome);
|
|
142
|
+
if (!file)
|
|
143
|
+
return null;
|
|
144
|
+
const st = await fsp.lstat(file);
|
|
145
|
+
return st.isFile() ? file : null;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// @silent-fallback-ok — a missing config dir or index file means there is nothing to rank.
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Render the inject block, or '' when there is nothing to add. */
|
|
153
|
+
export function renderInjectBlock(inject) {
|
|
154
|
+
if (inject.length === 0)
|
|
155
|
+
return '';
|
|
156
|
+
return [
|
|
157
|
+
INJECT_HEADER,
|
|
158
|
+
'These memory index entries sit past the point where MEMORY.md stops loading, and were ranked relevant to this session:',
|
|
159
|
+
...inject.map((e) => e.text),
|
|
160
|
+
INJECT_FOOTER,
|
|
161
|
+
].join('\n');
|
|
162
|
+
}
|
|
163
|
+
export function pickSource(v) {
|
|
164
|
+
return v === 'startup' || v === 'resume' || v === 'clear' || v === 'compact' ? v : 'other';
|
|
165
|
+
}
|
|
166
|
+
const PICKER_DEFAULTS = {
|
|
167
|
+
mode: 'shadow',
|
|
168
|
+
model: 'jev-1.13.0',
|
|
169
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
170
|
+
injectLines: DEFAULT_INJECT_LINES,
|
|
171
|
+
injectMaxChars: DEFAULT_INJECT_MAX_CHARS,
|
|
172
|
+
glossary: [],
|
|
173
|
+
dailyCallCap: DEFAULT_DAILY_CALL_CAP,
|
|
174
|
+
};
|
|
175
|
+
/** A row's view of an entry: id, score, pinned flag — never its text. */
|
|
176
|
+
const rowEntry = (scores) => (e) => ({
|
|
177
|
+
id: e.id,
|
|
178
|
+
...(scores.has(e.line) ? { p: Math.round(scores.get(e.line) * 1000) / 1000 } : {}),
|
|
179
|
+
...(e.pinned ? { pinned: true } : {}),
|
|
180
|
+
});
|
|
181
|
+
export class JevMemoryPicker {
|
|
182
|
+
deps;
|
|
183
|
+
audit;
|
|
184
|
+
cachedKey = null;
|
|
185
|
+
keyReadAt = 0;
|
|
186
|
+
inFlight = 0;
|
|
187
|
+
capDay = '';
|
|
188
|
+
capCount = 0;
|
|
189
|
+
/** Test seam: the latest detached shadow run. */
|
|
190
|
+
lastRun = Promise.resolve(null);
|
|
191
|
+
homeDir;
|
|
192
|
+
constructor(deps) {
|
|
193
|
+
this.deps = deps;
|
|
194
|
+
this.homeDir = deps.homeDir ?? os.homedir();
|
|
195
|
+
this.audit = new BoundedJsonlAudit({ file: deps.logPath });
|
|
196
|
+
this.refreshKey();
|
|
197
|
+
}
|
|
198
|
+
/** Resolves when every queued log row is written (tests, shutdown). */
|
|
199
|
+
flush() {
|
|
200
|
+
return this.audit.flush();
|
|
201
|
+
}
|
|
202
|
+
now() {
|
|
203
|
+
return (this.deps.now ?? Date.now)();
|
|
204
|
+
}
|
|
205
|
+
refreshKey() {
|
|
206
|
+
this.keyReadAt = this.now();
|
|
207
|
+
try {
|
|
208
|
+
this.cachedKey = this.deps.readKey() || null;
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// @silent-fallback-ok — an unreadable vault means "no key"; picks fall back to positional order with reason disabled-no-key.
|
|
212
|
+
this.cachedKey = null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/** The live config, normalised. Null when disabled (the kill switch). */
|
|
216
|
+
config() {
|
|
217
|
+
let cfg;
|
|
218
|
+
try {
|
|
219
|
+
cfg = this.deps.getConfig();
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// @silent-fallback-ok — an unreadable config means off; the session starts exactly as today.
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
if (!cfg || cfg.enabled !== true)
|
|
226
|
+
return null;
|
|
227
|
+
const num = (v, d, lo, hi) => typeof v === 'number' && Number.isFinite(v) ? Math.max(lo, Math.min(hi, Math.floor(v))) : d;
|
|
228
|
+
return {
|
|
229
|
+
mode: cfg.mode === 'inject' ? 'inject' : 'shadow',
|
|
230
|
+
model: typeof cfg.model === 'string' && cfg.model ? cfg.model : 'jev-1.13.0',
|
|
231
|
+
timeoutMs: num(cfg.timeoutMs, DEFAULT_TIMEOUT_MS, TIMEOUT_MIN_MS, TIMEOUT_MAX_MS),
|
|
232
|
+
injectLines: num(cfg.injectLines, DEFAULT_INJECT_LINES, 0, 200),
|
|
233
|
+
injectMaxChars: num(cfg.injectMaxChars, DEFAULT_INJECT_MAX_CHARS, 0, 50_000),
|
|
234
|
+
glossary: Array.isArray(cfg.glossary)
|
|
235
|
+
? cfg.glossary.filter((g) => typeof g === 'string' && g.trim() !== '').slice(0, MAX_GLOSSARY_LINES).map((g) => g.slice(0, MAX_GLOSSARY_CHARS))
|
|
236
|
+
: [],
|
|
237
|
+
dailyCallCap: num(cfg.dailyCallCap, DEFAULT_DAILY_CALL_CAP, 0, 100_000),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Rank the index at `indexPath` against `context` and log one row. Never
|
|
242
|
+
* rejects: every failure resolves to "add only the pinned entries beyond the
|
|
243
|
+
* cut" (with nothing pinned, today's load exactly).
|
|
244
|
+
*/
|
|
245
|
+
async pick(indexPath, context, source = 'other') {
|
|
246
|
+
const cfg = this.config() ?? { ...PICKER_DEFAULTS };
|
|
247
|
+
const t0 = this.now();
|
|
248
|
+
const ctx = context.slice(0, MAX_CONTEXT_CHARS);
|
|
249
|
+
const base = {
|
|
250
|
+
ts: new Date(t0).toISOString(),
|
|
251
|
+
mode: cfg.mode,
|
|
252
|
+
source,
|
|
253
|
+
contextSha256: crypto.createHash('sha256').update(ctx, 'utf8').digest('hex'),
|
|
254
|
+
contextChars: ctx.length,
|
|
255
|
+
};
|
|
256
|
+
const skip = (reason, inject = []) => {
|
|
257
|
+
this.audit.append({ ...base, outcome: 'skipped', reason, ms: this.now() - t0, ...(inject.length ? { inject: inject.map(rowEntry(new Map())) } : {}) });
|
|
258
|
+
return { outcome: 'skipped', reason, inject, scores: new Map() };
|
|
259
|
+
};
|
|
260
|
+
let content;
|
|
261
|
+
try {
|
|
262
|
+
const st = await fsp.lstat(indexPath);
|
|
263
|
+
if (!st.isFile())
|
|
264
|
+
return skip('no-index');
|
|
265
|
+
if (st.size > MAX_INDEX_BYTES)
|
|
266
|
+
return skip('oversize-index');
|
|
267
|
+
content = await fsp.readFile(indexPath, 'utf8');
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// @silent-fallback-ok — no index file means nothing to rank; the row records no-index.
|
|
271
|
+
return skip('no-index');
|
|
272
|
+
}
|
|
273
|
+
const entries = parseIndex(content);
|
|
274
|
+
const cands = candidates(entries);
|
|
275
|
+
const pinnedOnly = compose(entries, [], cfg.injectLines, cfg.injectMaxChars);
|
|
276
|
+
if (cands.length === 0)
|
|
277
|
+
return skip('fits', pinnedOnly);
|
|
278
|
+
if (ctx.trim() === '')
|
|
279
|
+
return skip('no-context', pinnedOnly);
|
|
280
|
+
const scored = await this.rank(cands, ctx, cfg);
|
|
281
|
+
const scores = 'scores' in scored ? scored.scores : new Map();
|
|
282
|
+
const inject = 'scores' in scored ? compose(entries, rankByScore(cands, scores), cfg.injectLines, cfg.injectMaxChars) : pinnedOnly;
|
|
283
|
+
const outcome = 'scores' in scored ? 'ranked' : 'fallback';
|
|
284
|
+
const reason = 'reason' in scored ? scored.reason : undefined;
|
|
285
|
+
this.audit.append({
|
|
286
|
+
...base,
|
|
287
|
+
outcome,
|
|
288
|
+
...(reason ? { reason } : {}),
|
|
289
|
+
entries: entries.length,
|
|
290
|
+
prefix: entries.filter((e) => e.inPrefix).length,
|
|
291
|
+
pinned: entries.filter((e) => e.pinned).length,
|
|
292
|
+
candidates: cands.length,
|
|
293
|
+
ms: this.now() - t0,
|
|
294
|
+
...(scored.jevMs !== undefined ? { jevMs: scored.jevMs } : {}),
|
|
295
|
+
model: cfg.model,
|
|
296
|
+
inject: inject.map(rowEntry(scores)),
|
|
297
|
+
});
|
|
298
|
+
return { outcome, ...(reason ? { reason } : {}), inject, scores };
|
|
299
|
+
}
|
|
300
|
+
/** One bounded Jev call. Resolves to scores, or to a fallback reason. */
|
|
301
|
+
async rank(cands, ctx, cfg) {
|
|
302
|
+
const nowMs = this.now();
|
|
303
|
+
if (!this.cachedKey && nowMs - this.keyReadAt >= KEY_REREAD_MS)
|
|
304
|
+
this.refreshKey();
|
|
305
|
+
if (!this.cachedKey)
|
|
306
|
+
return { reason: 'disabled-no-key' };
|
|
307
|
+
const day = new Date(nowMs).toISOString().slice(0, 10);
|
|
308
|
+
if (this.capDay !== day) {
|
|
309
|
+
this.capDay = day;
|
|
310
|
+
this.capCount = 0;
|
|
311
|
+
}
|
|
312
|
+
if (this.capCount >= cfg.dailyCallCap)
|
|
313
|
+
return { reason: 'daily-cap' };
|
|
314
|
+
if (this.inFlight >= MAX_IN_FLIGHT)
|
|
315
|
+
return { reason: 'busy' };
|
|
316
|
+
const glossary = cfg.glossary.length ? `Glossary of our internal names:\n${cfg.glossary.map((g) => `- ${g}`).join('\n')}\n\n` : '';
|
|
317
|
+
const state = scrubForStore(`${glossary}Conversation at session start:\n${ctx}`);
|
|
318
|
+
if (state.error || state.truncated)
|
|
319
|
+
return { reason: 'scrub-error' };
|
|
320
|
+
const questions = {};
|
|
321
|
+
for (const e of cands) {
|
|
322
|
+
const s = scrubForStore(e.text.slice(0, MAX_ENTRY_CHARS));
|
|
323
|
+
if (s.error || s.truncated)
|
|
324
|
+
return { reason: 'scrub-error' };
|
|
325
|
+
questions[`b${e.line}`] = { type: 'noul', instructions: QUESTION_B(s.text) };
|
|
326
|
+
questions[`c${e.line}`] = { type: 'noul', instructions: QUESTION_C(s.text) };
|
|
327
|
+
}
|
|
328
|
+
this.capCount++;
|
|
329
|
+
this.inFlight++;
|
|
330
|
+
const t0 = this.now();
|
|
331
|
+
const ctrl = new AbortController();
|
|
332
|
+
const abort = setTimeout(() => ctrl.abort(), cfg.timeoutMs);
|
|
333
|
+
let timer;
|
|
334
|
+
let tokensIn;
|
|
335
|
+
let modelServed;
|
|
336
|
+
let metricOutcome = 'error';
|
|
337
|
+
const call = (async () => {
|
|
338
|
+
try {
|
|
339
|
+
const res = await (this.deps.fetchImpl ?? fetch)(ENDPOINT, {
|
|
340
|
+
method: 'POST',
|
|
341
|
+
headers: { Authorization: `Bearer ${this.cachedKey}`, 'Content-Type': 'application/json' },
|
|
342
|
+
body: JSON.stringify({ state: state.text, model: cfg.model, questions }),
|
|
343
|
+
signal: ctrl.signal,
|
|
344
|
+
});
|
|
345
|
+
if (!res.ok) {
|
|
346
|
+
if (res.status === 401 || res.status === 403) {
|
|
347
|
+
this.cachedKey = null;
|
|
348
|
+
this.keyReadAt = this.now();
|
|
349
|
+
}
|
|
350
|
+
return { reason: 'http-error' };
|
|
351
|
+
}
|
|
352
|
+
const json = (await res.json());
|
|
353
|
+
modelServed = typeof json.model === 'string' ? json.model : undefined;
|
|
354
|
+
tokensIn = json.usage?.input_tokens;
|
|
355
|
+
if (modelServed !== cfg.model)
|
|
356
|
+
return { reason: 'model-mismatch' };
|
|
357
|
+
const scores = new Map();
|
|
358
|
+
for (const e of cands) {
|
|
359
|
+
const ps = [json.answers?.[`b${e.line}`]?.noul, json.answers?.[`c${e.line}`]?.noul]
|
|
360
|
+
.filter((p) => typeof p === 'number' && Number.isFinite(p));
|
|
361
|
+
if (ps.length)
|
|
362
|
+
scores.set(e.line, ps.reduce((a, b) => a + b, 0) / ps.length);
|
|
363
|
+
}
|
|
364
|
+
if (scores.size === 0)
|
|
365
|
+
return { reason: 'no-answers' };
|
|
366
|
+
metricOutcome = 'fired';
|
|
367
|
+
return { scores };
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
return { reason: err?.name === 'AbortError' ? 'timeout' : 'http-error' };
|
|
371
|
+
}
|
|
372
|
+
})();
|
|
373
|
+
const deadline = new Promise((resolve) => {
|
|
374
|
+
timer = setTimeout(() => resolve({ reason: 'timeout' }), cfg.timeoutMs + RACE_SLACK_MS);
|
|
375
|
+
timer.unref?.();
|
|
376
|
+
});
|
|
377
|
+
try {
|
|
378
|
+
const out = await Promise.race([call, deadline]);
|
|
379
|
+
return { ...out, jevMs: this.now() - t0 };
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
clearTimeout(abort);
|
|
383
|
+
if (timer)
|
|
384
|
+
clearTimeout(timer);
|
|
385
|
+
this.inFlight--;
|
|
386
|
+
try {
|
|
387
|
+
this.deps.metrics?.record({
|
|
388
|
+
feature: JEV_MEMORY_PICKER_FEATURE,
|
|
389
|
+
kind: 'llm',
|
|
390
|
+
outcome: metricOutcome,
|
|
391
|
+
tokensIn,
|
|
392
|
+
tokensOut: 0, // TypeSafe does not bill output tokens
|
|
393
|
+
latencyMs: this.now() - t0,
|
|
394
|
+
model: modelServed ?? cfg.model,
|
|
395
|
+
framework: 'typesafe-api',
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
catch { /* @silent-fallback-ok — metering must never break the picker */ }
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* The production wiring, shared by server.ts and the E2E test: the live
|
|
404
|
+
* `intelligence.jevMemoryPicker` block wins over the boot block, and an
|
|
405
|
+
* omitted `enabled` is decided by the developmentAgent gate.
|
|
406
|
+
*/
|
|
407
|
+
export function buildJevMemoryPicker(opts) {
|
|
408
|
+
return new JevMemoryPicker({
|
|
409
|
+
getConfig: () => {
|
|
410
|
+
const intel = opts.readLiveIntelligence();
|
|
411
|
+
const live = intel && typeof intel === 'object' ? intel.jevMemoryPicker : undefined;
|
|
412
|
+
const block = ((live && typeof live === 'object' ? live : undefined) ?? opts.bootBlock ?? {});
|
|
413
|
+
const enabled = resolveDevAgentGate(typeof block.enabled === 'boolean' ? block.enabled : undefined, { developmentAgent: opts.developmentAgent });
|
|
414
|
+
return { ...block, enabled };
|
|
415
|
+
},
|
|
416
|
+
readKey: () => {
|
|
417
|
+
const v = opts.readSecret('typesafe_api_key');
|
|
418
|
+
return typeof v === 'string' && v ? v : null;
|
|
419
|
+
},
|
|
420
|
+
logPath: path.join(opts.stateDir, '..', 'logs', 'jev-memory-picker.jsonl'),
|
|
421
|
+
metrics: opts.metrics,
|
|
422
|
+
fetchImpl: opts.fetchImpl,
|
|
423
|
+
now: opts.now,
|
|
424
|
+
homeDir: opts.homeDir,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
/** Build the opening-context text from a topic's name and last messages. */
|
|
428
|
+
export function topicOpeningContext(topic, extra) {
|
|
429
|
+
const parts = [];
|
|
430
|
+
if (topic?.topicName)
|
|
431
|
+
parts.push(`Topic: ${topic.topicName}`);
|
|
432
|
+
for (const m of (topic?.recentMessages ?? []).slice(-3)) {
|
|
433
|
+
if (typeof m.text === 'string' && m.text.trim())
|
|
434
|
+
parts.push(`${m.fromUser ? 'User' : 'Agent'}: ${m.text.slice(0, 600)}`);
|
|
435
|
+
}
|
|
436
|
+
if (typeof extra === 'string' && extra.trim())
|
|
437
|
+
parts.push(extra.slice(0, MAX_CONTEXT_CHARS));
|
|
438
|
+
return parts.join('\n').slice(0, MAX_CONTEXT_CHARS);
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=JevMemoryPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JevMemoryPicker.js","sourceRoot":"","sources":["../../src/core/JevMemoryPicker.ts"],"names":[],"mappings":"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"}
|