claude-flow 3.62.0 → 3.63.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.
Files changed (46) hide show
  1. package/.claude/.proven-config-version +1 -0
  2. package/.claude/helpers/.helpers-version +1 -0
  3. package/.claude/helpers/helpers.manifest.json +13 -0
  4. package/.claude/proven-config.json +42 -0
  5. package/.claude/settings.local.json +8 -0
  6. package/.claude-plugin/marketplace.json +3 -3
  7. package/README.md +2 -2
  8. package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
  9. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
  10. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
  11. package/package.json +1 -1
  12. package/v3/@claude-flow/cli/README.md +2 -2
  13. package/v3/@claude-flow/cli/catalog-manifest.json +3 -3
  14. package/v3/@claude-flow/cli/dist/src/mcp-tools/agentbbs-tools.js +7 -2
  15. package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-agent-tools.d.ts +1 -20
  16. package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-agent-tools.js +347 -108
  17. package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-learning-tool.d.ts +4 -0
  18. package/v3/@claude-flow/cli/dist/src/mcp-tools/managed-learning-tool.js +46 -0
  19. package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +6 -3
  20. package/v3/@claude-flow/cli/dist/src/missions/schemas.d.ts +12 -12
  21. package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.d.ts +78 -0
  22. package/v3/@claude-flow/cli/dist/src/ruvector/diskann-backend.js +310 -0
  23. package/v3/@claude-flow/cli/dist/src/services/flywheel-transaction.js +5 -0
  24. package/v3/@claude-flow/cli/dist/src/services/managed-learning-loop.d.ts +79 -0
  25. package/v3/@claude-flow/cli/dist/src/services/managed-learning-loop.js +76 -0
  26. package/v3/@claude-flow/cli/dist/src/services/managed-learning-store.d.ts +187 -0
  27. package/v3/@claude-flow/cli/dist/src/services/managed-learning-store.js +238 -0
  28. package/v3/@claude-flow/cli/dist/src/services/managed-learning.d.ts +108 -0
  29. package/v3/@claude-flow/cli/dist/src/services/managed-learning.js +197 -0
  30. package/v3/@claude-flow/cli/dist/src/services/managed-memory-client.d.ts +72 -0
  31. package/v3/@claude-flow/cli/dist/src/services/managed-memory-client.js +236 -0
  32. package/v3/@claude-flow/cli/dist/src/services/managed-memory-worker.d.ts +56 -0
  33. package/v3/@claude-flow/cli/dist/src/services/managed-memory-worker.js +161 -0
  34. package/v3/@claude-flow/cli/dist/src/services/managed-run-collector.d.ts +93 -0
  35. package/v3/@claude-flow/cli/dist/src/services/managed-run-collector.js +181 -0
  36. package/v3/@claude-flow/cli/dist/src/services/managed-run-store.d.ts +52 -0
  37. package/v3/@claude-flow/cli/dist/src/services/managed-run-store.js +119 -0
  38. package/v3/@claude-flow/cli/dist/src/services/managed-workflows.d.ts +101 -0
  39. package/v3/@claude-flow/cli/dist/src/services/managed-workflows.js +183 -0
  40. package/v3/@claude-flow/cli/package.json +1 -1
  41. package/v3/@claude-flow/shared/dist/events/event-store.test.d.ts +8 -0
  42. package/v3/@claude-flow/shared/dist/events/event-store.test.js +293 -0
  43. package/v3/@claude-flow/shared/dist/hooks/hooks.test.d.ts +9 -0
  44. package/v3/@claude-flow/shared/dist/hooks/hooks.test.js +322 -0
  45. package/v3/@claude-flow/shared/dist/hooks/verify-exports.test.d.ts +9 -0
  46. package/v3/@claude-flow/shared/dist/hooks/verify-exports.test.js +93 -0
@@ -0,0 +1,197 @@
1
+ /** Verified, advisory workflow learning. Caller labels never establish trust. */
2
+ import { createHash, createPublicKey, verify } from 'node:crypto';
3
+ import { accept } from './harness-benchmark.js';
4
+ export const TASK_TYPES = ['code-review', 'migration', 'research', 'test-generation', 'implementation', 'other'];
5
+ const trusted = new WeakSet();
6
+ const HASH = /^[a-f0-9]{64}$/;
7
+ const ID = /^[a-z][a-z0-9-]{0,39}$/;
8
+ const MODEL = /^[a-z][a-z0-9./-]{0,79}$/;
9
+ const object = (v) => {
10
+ if (!v || typeof v !== 'object' || Array.isArray(v))
11
+ throw new Error('Expected an object');
12
+ return v;
13
+ };
14
+ function exact(v, keys) {
15
+ if (Object.keys(v).length !== keys.length || Object.keys(v).some(k => !keys.includes(k)))
16
+ throw new Error('Unknown or missing learning fields');
17
+ }
18
+ const integer = (v, min, max) => typeof v === 'number' && Number.isSafeInteger(v) && v >= min && v <= max;
19
+ const unit = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;
20
+ export function canonical(v) {
21
+ if (Array.isArray(v))
22
+ return '[' + v.map(canonical).join(',') + ']';
23
+ if (v && typeof v === 'object')
24
+ return '{' + Object.keys(v).sort().map(k => JSON.stringify(k) + ':' + canonical(v[k])).join(',') + '}';
25
+ return JSON.stringify(v);
26
+ }
27
+ export const digest = (v) => createHash('sha256').update(canonical(v)).digest('hex');
28
+ /** Closed metadata contract: no prompts, arbitrary commands, transcripts or caller trust labels. */
29
+ export function observationOf(value) {
30
+ const v = object(value);
31
+ exact(v, ['v', 'attemptId', 'taskHash', 'sourceHash', 'artifactHash', 'policyHash', 'corpusHash', 'evaluatorHash', 'taskType', 'split', 'trial', 'strategy', 'budgetCents', 'costCents', 'durationMs', 'checks']);
32
+ if (v.v !== 1 || !TASK_TYPES.includes(v.taskType) || !['train', 'holdout'].includes(v.split) || !integer(v.trial, 0, 99))
33
+ throw new Error('Invalid learning cohort');
34
+ for (const key of ['attemptId', 'taskHash', 'sourceHash', 'artifactHash', 'policyHash', 'corpusHash', 'evaluatorHash'])
35
+ if (typeof v[key] !== 'string' || !HASH.test(v[key]))
36
+ throw new Error('Invalid evidence hash');
37
+ const strategy = object(v.strategy);
38
+ exact(strategy, ['id', 'model', 'workers', 'template']);
39
+ if (!ID.test(String(strategy.id)) || !ID.test(String(strategy.template)) || !MODEL.test(String(strategy.model)) || !integer(strategy.workers, 1, 64))
40
+ throw new Error('Invalid workflow strategy');
41
+ if (!integer(v.budgetCents, 1, 999_999_999) || (v.costCents !== null && !integer(v.costCents, 0, 999_999_999)) || (v.durationMs !== null && !integer(v.durationMs, 0, 86_400_000)))
42
+ throw new Error('Invalid measured cost or duration');
43
+ const checks = object(v.checks);
44
+ exact(checks, ['acceptance', 'safety', 'replay', 'adversarial', 'drift', 'driftThreshold', 'rollbackRate']);
45
+ if (['acceptance', 'safety', 'replay', 'adversarial'].some(k => typeof checks[k] !== 'boolean') || !unit(checks.drift) || !unit(checks.driftThreshold) || !unit(checks.rollbackRate))
46
+ throw new Error('Invalid verification measurements');
47
+ // Detach caller objects, including nested strategy/checks, before hashing or persistence.
48
+ return JSON.parse(JSON.stringify(v));
49
+ }
50
+ export function evidenceOf(value) {
51
+ const v = object(value);
52
+ if (Object.keys(v).some(k => !['observation', 'signature'].includes(k)))
53
+ throw new Error('Unknown evidence fields');
54
+ const observation = observationOf(v.observation);
55
+ // Canonical form only: the last base64 character of a 64-byte signature has 4 unused bits that the decoder ignores, so
56
+ // other spellings of the same bytes would verify yet digest differently and be stored as separate records.
57
+ if (v.signature !== undefined && (typeof v.signature !== 'string' || !/^[A-Za-z0-9+/]{86}==$/.test(v.signature)
58
+ || Buffer.from(v.signature, 'base64').toString('base64') !== v.signature))
59
+ throw new Error('Invalid verifier signature');
60
+ return { observation, ...(v.signature ? { signature: v.signature } : {}) };
61
+ }
62
+ /** Public key is configured by the host, never accepted from an MCP argument or stored record. */
63
+ export function isVerified(evidence, publicKey) {
64
+ if (!publicKey || !evidence.signature)
65
+ return false;
66
+ try {
67
+ const key = createPublicKey(publicKey);
68
+ return key.asymmetricKeyType === 'ed25519' && verify(null, Buffer.from(canonical(evidence.observation)), key, Buffer.from(evidence.signature, 'base64'));
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ }
74
+ /** Revalidate every persisted record on each use; a JSON provenance label is not authority. */
75
+ export function trustedEvidence(records, publicKey) {
76
+ const out = [];
77
+ const ids = new Map();
78
+ for (const raw of records) {
79
+ const e = evidenceOf(raw);
80
+ if (!isVerified(e, publicKey) || e.observation.costCents === null || e.observation.durationMs === null)
81
+ continue;
82
+ const hash = digest(e.observation);
83
+ const previous = ids.get(e.observation.attemptId);
84
+ if (previous && previous !== hash)
85
+ throw new Error('Conflicting learning attempt');
86
+ if (previous)
87
+ continue;
88
+ ids.set(e.observation.attemptId, hash);
89
+ {
90
+ Object.freeze(e.observation.strategy);
91
+ Object.freeze(e.observation.checks);
92
+ Object.freeze(e.observation);
93
+ Object.freeze(e);
94
+ trusted.add(e);
95
+ out.push(e);
96
+ }
97
+ }
98
+ return out;
99
+ }
100
+ export function manifestOf(value) {
101
+ const m = object(value);
102
+ exact(m, ['taskHashes', 'trials']);
103
+ if (!Array.isArray(m.taskHashes) || m.taskHashes.length < 2 || m.taskHashes.length > 100 || m.taskHashes.some(h => typeof h !== 'string' || !HASH.test(h)) || new Set(m.taskHashes).size !== m.taskHashes.length)
104
+ throw new Error('Manifest needs 2 to 100 unique task hashes');
105
+ if (!Array.isArray(m.trials) || m.trials.length < 3 || m.trials.length > 10 || m.trials.some(t => !integer(t, 0, 99)) || new Set(m.trials).size !== m.trials.length)
106
+ throw new Error('Manifest needs 3 to 10 unique trials');
107
+ return { taskHashes: [...m.taskHashes].sort(), trials: [...m.trials].sort((a, b) => a - b) };
108
+ }
109
+ export function scopeOf(value) {
110
+ const s = object(value);
111
+ exact(s, ['taskType', 'policyHash', 'evaluatorHash']);
112
+ if (!TASK_TYPES.includes(s.taskType) || !HASH.test(String(s.policyHash)) || !HASH.test(String(s.evaluatorHash)))
113
+ throw new Error('Invalid recommendation scope');
114
+ return { taskType: s.taskType, policyHash: s.policyHash, evaluatorHash: s.evaluatorHash };
115
+ }
116
+ const inScope = (o, s) => o.taskType === s.taskType && o.policyHash === s.policyHash && o.evaluatorHash === s.evaluatorHash;
117
+ const success = (o) => o.checks.acceptance && o.checks.safety ? 1 : 0;
118
+ const p95 = (values) => [...values].sort((a, b) => a - b)[Math.max(0, Math.ceil(values.length * .95) - 1)] ?? 0;
119
+ /** Training evidence only; holdout records and unsigned observations cannot influence a pick. */
120
+ export function recommend(records, scope, maxP95Ms = 86_400_000) {
121
+ if (records.some(e => !trusted.has(e)))
122
+ throw new Error('Host-verified evidence required');
123
+ if (!integer(maxP95Ms, 1, 86_400_000))
124
+ throw new Error('Invalid latency constraint');
125
+ const groups = new Map();
126
+ for (const e of records) {
127
+ if (e.observation.split !== 'train' || !inScope(e.observation, scope))
128
+ continue;
129
+ const key = canonical(e.observation.strategy);
130
+ groups.set(key, [...(groups.get(key) ?? []), e]);
131
+ }
132
+ const candidates = [...groups.values()].flatMap(rows => {
133
+ if (rows.length < 3 || new Set(rows.map(r => r.observation.taskHash)).size < 3)
134
+ return [];
135
+ const totalCost = rows.reduce((n, r) => n + (r.observation.costCents ?? 0), 0);
136
+ const latency = p95(rows.map(r => r.observation.durationMs));
137
+ if (totalCost <= 0 || latency > maxP95Ms || rows.some(r => !r.observation.checks.safety))
138
+ return [];
139
+ const successes = rows.reduce((n, r) => n + success(r.observation), 0);
140
+ if (successes === 0)
141
+ return [];
142
+ return [{ strategy: rows[0].observation.strategy, samples: rows.length, successes, successRate: successes / rows.length, successesPerDollar: successes * 100 / totalCost, p95Ms: latency, evidenceIds: rows.map(r => digest(r.observation)).sort() }];
143
+ }).sort((a, b) => b.successesPerDollar - a.successesPerDollar || a.p95Ms - b.p95Ms || canonical(a.strategy).localeCompare(canonical(b.strategy)));
144
+ return { advisory: true, selected: candidates[0] ?? null, candidates, abstained: candidates.length === 0, reason: candidates.length ? 'Ranked by measured training successes per dollar within exact policy/evaluator scope' : 'Insufficient trusted training evidence within scope and latency constraint', defaultsChanged: false };
145
+ }
146
+ /** Complete paired heldout data, equal admitted budgets, source identity and existing MetaHarness conjunction. */
147
+ export function evaluate(records, scope, manifest, baselineId, candidateId) {
148
+ if (records.some(e => !trusted.has(e)))
149
+ throw new Error('Host-verified evidence required');
150
+ if (!ID.test(baselineId) || !ID.test(candidateId) || baselineId === candidateId)
151
+ throw new Error('Distinct strategy IDs required');
152
+ const corpusHash = digest(manifest);
153
+ const relevant = records.filter(e => inScope(e.observation, scope) && [baselineId, candidateId].includes(e.observation.strategy.id));
154
+ const trainingTasks = new Set(records.filter(e => inScope(e.observation, scope) && e.observation.split === 'train').map(e => e.observation.taskHash));
155
+ if (manifest.taskHashes.some(h => trainingTasks.has(h)))
156
+ throw new Error('Training and heldout tasks overlap');
157
+ const rows = relevant.filter(e => e.observation.split === 'holdout' && e.observation.corpusHash === corpusHash);
158
+ for (const id of [baselineId, candidateId])
159
+ if (new Set(rows.filter(r => r.observation.strategy.id === id).map(r => canonical(r.observation.strategy))).size !== 1)
160
+ throw new Error('Missing or inconsistent strategy configuration');
161
+ const paired = [];
162
+ for (const taskHash of manifest.taskHashes)
163
+ for (const trial of manifest.trials) {
164
+ const pick = (id) => rows.filter(e => e.observation.taskHash === taskHash && e.observation.trial === trial && e.observation.strategy.id === id);
165
+ const base = pick(baselineId), candidate = pick(candidateId);
166
+ if (base.length !== 1 || candidate.length !== 1)
167
+ throw new Error('Missing or duplicate paired heldout result');
168
+ const b = base[0].observation, c = candidate[0].observation;
169
+ if (b.sourceHash !== c.sourceHash || b.budgetCents !== c.budgetCents)
170
+ throw new Error('Source identity or admitted budgets differ');
171
+ paired.push([b, c]);
172
+ }
173
+ const base = paired.map(p => p[0]), candidate = paired.map(p => p[1]);
174
+ const efficiency = (rows) => {
175
+ const cost = rows.reduce((n, r) => n + r.costCents, 0);
176
+ if (cost <= 0)
177
+ throw new Error('Positive measured cost required');
178
+ return rows.reduce((n, r) => n + success(r), 0) * 100 / cost;
179
+ };
180
+ const baselineEfficiency = efficiency(base), candidateEfficiency = efficiency(candidate);
181
+ if (baselineEfficiency <= 0)
182
+ throw new Error('Nonzero baseline success required for relative improvement');
183
+ const delta = candidateEfficiency / baselineEfficiency - 1;
184
+ const total = baselineEfficiency + candidateEfficiency;
185
+ const all = [...base, ...candidate];
186
+ const gate = accept({
187
+ heldOutScore: candidateEfficiency / total, baselineHeldOutScore: baselineEfficiency / total,
188
+ redblue: all.every(o => o.checks.adversarial) ? 'PASS' : 'FAIL',
189
+ drift: Math.max(...candidate.map(o => o.checks.drift)), driftThreshold: Math.min(...candidate.map(o => o.checks.driftThreshold)),
190
+ replayDeterministic: all.every(o => o.checks.replay), receiptCoverage: 1,
191
+ canaryRollbackRate: Math.max(...candidate.map(o => o.checks.rollbackRate)), baselineRollbackRate: Math.max(...base.map(o => o.checks.rollbackRate)),
192
+ });
193
+ const noRegression = paired.every(([b, c]) => success(c) >= success(b)) && all.every(o => o.checks.safety);
194
+ const baselineP95Ms = p95(base.map(o => o.durationMs)), candidateP95Ms = p95(candidate.map(o => o.durationMs));
195
+ return { advisory: true, eligible: gate.accept && delta >= .10 - Number.EPSILON && noRegression && candidateP95Ms <= baselineP95Ms, baselineP95Ms, candidateP95Ms, delta, baselineEfficiency, candidateEfficiency, pairedResults: paired.length, corpusHash, noRegression, metaharness: gate, defaultsChanged: false, evidenceIds: rows.map(r => digest(r.observation)).sort() };
196
+ }
197
+ //# sourceMappingURL=managed-learning.js.map
@@ -0,0 +1,72 @@
1
+ /** Native memory runs behind a bounded child boundary, never in the MCP process. */
2
+ import { type ChildProcess } from 'node:child_process';
3
+ export declare const MANAGED_MEMORY_NAMESPACE = "managed-workflow-evidence";
4
+ export declare const MANAGED_MEMORY_LIMITS: {
5
+ readonly workers: 1;
6
+ readonly requestBytes: 80000;
7
+ readonly resultBytes: 200000;
8
+ readonly rows: 20;
9
+ readonly rowBytes: 8192;
10
+ readonly timeoutMs: 15000;
11
+ readonly idleMs: 5000;
12
+ };
13
+ export type MemoryRequest = {
14
+ operation: 'index';
15
+ id: string;
16
+ value: string;
17
+ taskType: string;
18
+ } | {
19
+ operation: 'recall';
20
+ taskType: string;
21
+ allowedIds: string[];
22
+ };
23
+ export type MemoryRow = {
24
+ key: string;
25
+ namespace: typeof MANAGED_MEMORY_NAMESPACE;
26
+ score: number;
27
+ content: string;
28
+ };
29
+ export type MemoryResult = {
30
+ operation: 'index';
31
+ durable: true;
32
+ hasEmbedding: boolean;
33
+ } | {
34
+ operation: 'recall';
35
+ available: boolean;
36
+ rows: MemoryRow[];
37
+ };
38
+ /** The optional fork callback is an in-process host test seam, not a serialized tool argument. */
39
+ export declare class ManagedMemoryClient {
40
+ private readonly slots;
41
+ private readonly timeoutMs;
42
+ private readonly idleMs;
43
+ private readonly forkWorker;
44
+ constructor(options?: {
45
+ timeoutMs?: number;
46
+ idleMs?: number;
47
+ forkWorker?: (root: string) => ChildProcess;
48
+ });
49
+ run(root: string, raw: unknown, authorize?: () => boolean): Promise<MemoryResult>;
50
+ stats(): {
51
+ workers: number;
52
+ busy: number;
53
+ };
54
+ close(): void;
55
+ private remove;
56
+ }
57
+ export declare const managedMemoryClient: ManagedMemoryClient;
58
+ export declare function nativeMemoryIndex(root: string, input: Omit<Extract<MemoryRequest, {
59
+ operation: 'index';
60
+ }>, 'operation'>, authorize?: () => boolean): Promise<{
61
+ operation: "index";
62
+ durable: true;
63
+ hasEmbedding: boolean;
64
+ }>;
65
+ export declare function nativeMemoryRecall(root: string, input: Omit<Extract<MemoryRequest, {
66
+ operation: 'recall';
67
+ }>, 'operation'>, authorize?: () => boolean): Promise<{
68
+ operation: "recall";
69
+ available: boolean;
70
+ rows: MemoryRow[];
71
+ }>;
72
+ //# sourceMappingURL=managed-memory-client.d.ts.map
@@ -0,0 +1,236 @@
1
+ /** Native memory runs behind a bounded child boundary, never in the MCP process. */
2
+ import { fork } from 'node:child_process';
3
+ import { existsSync, realpathSync, statSync } from 'node:fs';
4
+ import { createRequire } from 'node:module';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { fileURLToPath } from 'node:url';
7
+ export const MANAGED_MEMORY_NAMESPACE = 'managed-workflow-evidence';
8
+ export const MANAGED_MEMORY_LIMITS = { workers: 1, requestBytes: 80_000, resultBytes: 200_000, rows: 20, rowBytes: 8192, timeoutMs: 15_000, idleMs: 5000 };
9
+ const HASH = /^[a-f0-9]{64}$/;
10
+ const TYPES = ['code-review', 'migration', 'research', 'test-generation', 'implementation', 'other'];
11
+ function requestOf(value) {
12
+ if (!value || typeof value !== 'object' || Array.isArray(value))
13
+ throw new Error('Invalid managed memory request');
14
+ const r = value;
15
+ const keys = r.operation === 'index' ? ['operation', 'id', 'value', 'taskType'] : ['operation', 'taskType', 'allowedIds'];
16
+ if (!['index', 'recall'].includes(String(r.operation)) || Object.keys(r).length !== keys.length || Object.keys(r).some(k => !keys.includes(k)) || !TYPES.includes(String(r.taskType)))
17
+ throw new Error('Invalid managed memory request');
18
+ if (r.operation === 'index' && (typeof r.id !== 'string' || !HASH.test(r.id) || typeof r.value !== 'string' || Buffer.byteLength(r.value) > MANAGED_MEMORY_LIMITS.rowBytes))
19
+ throw new Error('Invalid managed index request');
20
+ if (r.operation === 'recall' && (!Array.isArray(r.allowedIds) || r.allowedIds.length > 500 || r.allowedIds.some(id => typeof id !== 'string' || !HASH.test(id))))
21
+ throw new Error('Invalid managed recall request');
22
+ if (Buffer.byteLength(JSON.stringify(r)) > MANAGED_MEMORY_LIMITS.requestBytes)
23
+ throw new Error('Managed memory request limit exceeded');
24
+ return JSON.parse(JSON.stringify(r));
25
+ }
26
+ function resultOf(value, operation, requestId) {
27
+ if (!value || typeof value !== 'object' || Array.isArray(value) || Buffer.byteLength(JSON.stringify(value)) > MANAGED_MEMORY_LIMITS.resultBytes)
28
+ throw new Error('Invalid managed memory worker response');
29
+ const r = value;
30
+ if (r.v !== 1 || r.ok !== true || r.operation !== operation || r.requestId !== requestId)
31
+ throw new Error('Managed native memory worker did not complete');
32
+ if (operation === 'index') {
33
+ if (Object.keys(r).some(k => !['v', 'ok', 'requestId', 'operation', 'durable', 'hasEmbedding'].includes(k)) || r.durable !== true || typeof r.hasEmbedding !== 'boolean')
34
+ throw new Error('Unconfirmed managed memory persistence');
35
+ return { operation, durable: true, hasEmbedding: r.hasEmbedding };
36
+ }
37
+ if (Object.keys(r).some(k => !['v', 'ok', 'requestId', 'operation', 'available', 'rows'].includes(k)) || typeof r.available !== 'boolean' || !Array.isArray(r.rows) || r.rows.length > MANAGED_MEMORY_LIMITS.rows)
38
+ throw new Error('Invalid managed recall response');
39
+ for (const raw of r.rows) {
40
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
41
+ throw new Error('Invalid managed recall row');
42
+ const row = raw;
43
+ if (Object.keys(row).length !== 4 || Object.keys(row).some(k => !['key', 'namespace', 'score', 'content'].includes(k)) || typeof row.key !== 'string' || !HASH.test(row.key) || row.namespace !== MANAGED_MEMORY_NAMESPACE || typeof row.score !== 'number' || !Number.isFinite(row.score) || row.score < -1 || row.score > 1 || typeof row.content !== 'string' || Buffer.byteLength(row.content) > MANAGED_MEMORY_LIMITS.rowBytes)
44
+ throw new Error('Invalid managed recall row');
45
+ }
46
+ return { operation, available: r.available, rows: r.rows };
47
+ }
48
+ function sourceLoader() {
49
+ try {
50
+ return createRequire(import.meta.url).resolve('tsx');
51
+ }
52
+ catch { /* npx tsx can live outside project node_modules */ }
53
+ for (let i = 0; i < process.execArgv.length; i++) {
54
+ const arg = process.execArgv[i];
55
+ const path = arg === '--import' ? process.execArgv[i + 1] : arg.startsWith('--import=') ? arg.slice(9) : undefined;
56
+ if (!path)
57
+ continue;
58
+ const file = path.startsWith('file:') ? fileURLToPath(path) : path;
59
+ if (/[/\\]node_modules[/\\]tsx[/\\]dist[/\\](?:loader\.mjs|esm[/\\]index\.mjs)$/.test(file) && existsSync(file))
60
+ return file;
61
+ }
62
+ throw new Error('Source managed memory worker requires tsx');
63
+ }
64
+ function launch(root) {
65
+ const js = new URL('./managed-memory-worker.js', import.meta.url), ts = new URL('./managed-memory-worker.ts', import.meta.url);
66
+ const compiled = existsSync(fileURLToPath(js));
67
+ const entry = compiled ? js : ts;
68
+ if (!existsSync(fileURLToPath(entry)))
69
+ throw new Error('Managed memory worker is not installed');
70
+ // Production uses emitted JS. Source development uses the project's declared
71
+ // tsx dependency so internal .js imports resolve to TypeScript sources.
72
+ const args = compiled ? [] : ['--import', sourceLoader()];
73
+ const env = {};
74
+ for (const key of ['PATH', 'HOME', 'USERPROFILE', 'SystemRoot', 'SYSTEMROOT', 'WINDIR', 'TMPDIR', 'TMP', 'TEMP', 'LANG', 'LC_ALL', 'CLAUDE_FLOW_DISABLE_BRIDGE', 'CLAUDE_FLOW_ENABLE_NATIVE_BRIDGE_ON_WINDOWS'])
75
+ if (process.env[key] !== undefined)
76
+ env[key] = process.env[key];
77
+ // No provider credentials or startup hooks are inherited. Existing local
78
+ // models may be used; indexing never initiates a model download.
79
+ env.CLAUDE_FLOW_CWD = root;
80
+ env.HF_HUB_OFFLINE = '1';
81
+ env.TRANSFORMERS_OFFLINE = '1';
82
+ return fork(entry, [], { cwd: root, env, execArgv: args, stdio: ['ignore', 'ignore', 'ignore', 'ipc'], serialization: 'json' });
83
+ }
84
+ /** The optional fork callback is an in-process host test seam, not a serialized tool argument. */
85
+ export class ManagedMemoryClient {
86
+ slots = new Map();
87
+ timeoutMs;
88
+ idleMs;
89
+ forkWorker;
90
+ constructor(options = {}) {
91
+ this.timeoutMs = options.timeoutMs ?? MANAGED_MEMORY_LIMITS.timeoutMs;
92
+ this.idleMs = options.idleMs ?? MANAGED_MEMORY_LIMITS.idleMs;
93
+ this.forkWorker = options.forkWorker ?? launch;
94
+ if (!Number.isFinite(this.timeoutMs) || this.timeoutMs < 20 || this.timeoutMs > 60_000 || !Number.isFinite(this.idleMs) || this.idleMs < 20 || this.idleMs > 30_000)
95
+ throw new Error('Invalid managed memory worker limits');
96
+ }
97
+ run(root, raw, authorize = () => true) {
98
+ let input, cwd;
99
+ try {
100
+ input = requestOf(raw);
101
+ cwd = realpathSync(root);
102
+ if (!statSync(cwd).isDirectory())
103
+ throw new Error('Invalid learning project root');
104
+ }
105
+ catch {
106
+ return Promise.reject(new Error('Invalid managed memory operation or project root'));
107
+ }
108
+ try {
109
+ if (!authorize())
110
+ return Promise.reject(new Error('Managed memory policy denied'));
111
+ }
112
+ catch {
113
+ return Promise.reject(new Error('Managed memory policy denied'));
114
+ }
115
+ let slot = this.slots.get(cwd);
116
+ if (slot?.busy)
117
+ return Promise.reject(new Error('Managed memory worker is busy; retry later'));
118
+ if (!slot) {
119
+ if (this.slots.size >= MANAGED_MEMORY_LIMITS.workers) {
120
+ const idle = [...this.slots.values()].filter(s => !s.busy).sort((a, b) => a.lastUsed - b.lastUsed)[0];
121
+ if (!idle)
122
+ return Promise.reject(new Error('Managed memory worker limit reached; retry later'));
123
+ this.remove(idle);
124
+ }
125
+ try {
126
+ slot = { child: this.forkWorker(cwd), root: cwd, busy: false, lastUsed: Date.now() };
127
+ this.slots.set(cwd, slot);
128
+ const owned = slot;
129
+ slot.child.once('error', () => { owned.fail?.(); this.remove(owned); });
130
+ slot.child.once('exit', () => { owned.fail?.(); this.remove(owned); });
131
+ }
132
+ catch {
133
+ return Promise.reject(new Error('Managed native memory worker unavailable'));
134
+ }
135
+ }
136
+ const owned = slot;
137
+ const requestId = randomUUID();
138
+ if (owned.timer)
139
+ clearTimeout(owned.timer);
140
+ owned.busy = true;
141
+ return new Promise((resolve, reject) => {
142
+ let settled = false, policyDenied = false, ready = false, writeGranted = false;
143
+ const complete = (result) => {
144
+ if (settled)
145
+ return;
146
+ settled = true;
147
+ clearTimeout(timeout);
148
+ owned.child.off('message', onMessage);
149
+ owned.fail = undefined;
150
+ owned.busy = false;
151
+ owned.lastUsed = Date.now();
152
+ if (result) {
153
+ owned.timer = setTimeout(() => this.remove(owned), this.idleMs);
154
+ owned.timer.unref();
155
+ owned.child.unref();
156
+ owned.child.channel?.unref();
157
+ resolve(result);
158
+ }
159
+ else {
160
+ this.remove(owned);
161
+ reject(new Error(policyDenied ? (writeGranted ? 'Managed memory policy changed; admitted write may have completed' : 'Managed memory policy denied before dispatch') : 'Managed native memory operation failed or timed out; parent remains available'));
162
+ }
163
+ };
164
+ const onMessage = (value) => {
165
+ try {
166
+ if (!authorize()) {
167
+ policyDenied = true;
168
+ complete();
169
+ return;
170
+ }
171
+ const message = value;
172
+ if (message?.phase !== undefined) {
173
+ if (Object.keys(message).length !== 3 || message.v !== 1 || message.requestId !== requestId || !['ready', 'before-write'].includes(String(message.phase)))
174
+ throw new Error('Invalid worker grant request');
175
+ if (message.phase === 'ready') {
176
+ if (ready)
177
+ throw new Error('Repeated worker ready');
178
+ ready = true;
179
+ }
180
+ else {
181
+ if (!ready || writeGranted || input.operation !== 'index')
182
+ throw new Error('Invalid worker write grant');
183
+ writeGranted = true;
184
+ }
185
+ owned.child.send({ v: 1, requestId, grant: message.phase === 'ready' ? 'execute' : 'write' }, error => { if (error)
186
+ complete(); });
187
+ return;
188
+ }
189
+ if (!ready)
190
+ throw new Error('Worker was not ready');
191
+ complete(resultOf(value, input.operation, requestId));
192
+ }
193
+ catch {
194
+ complete();
195
+ }
196
+ };
197
+ const timeout = setTimeout(() => complete(), this.timeoutMs);
198
+ owned.fail = () => complete();
199
+ owned.child.on('message', onMessage);
200
+ try {
201
+ if (!authorize()) {
202
+ policyDenied = true;
203
+ complete();
204
+ return;
205
+ }
206
+ owned.child.send({ v: 1, requestId, ...input }, error => { if (error)
207
+ complete(); });
208
+ }
209
+ catch {
210
+ policyDenied = true;
211
+ complete();
212
+ }
213
+ });
214
+ }
215
+ stats() { return { workers: this.slots.size, busy: [...this.slots.values()].filter(s => s.busy).length }; }
216
+ close() { for (const slot of [...this.slots.values()]) {
217
+ slot.fail?.();
218
+ this.remove(slot);
219
+ } }
220
+ remove(slot) {
221
+ if (slot.timer)
222
+ clearTimeout(slot.timer);
223
+ if (this.slots.get(slot.root) === slot)
224
+ this.slots.delete(slot.root);
225
+ if (!slot.child.killed)
226
+ slot.child.kill('SIGKILL');
227
+ }
228
+ }
229
+ export const managedMemoryClient = new ManagedMemoryClient();
230
+ export async function nativeMemoryIndex(root, input, authorize) {
231
+ return await managedMemoryClient.run(root, { operation: 'index', ...input }, authorize);
232
+ }
233
+ export async function nativeMemoryRecall(root, input, authorize) {
234
+ return await managedMemoryClient.run(root, { operation: 'recall', ...input }, authorize);
235
+ }
236
+ //# sourceMappingURL=managed-memory-client.js.map
@@ -0,0 +1,56 @@
1
+ type Row = {
2
+ key: string;
3
+ namespace: string;
4
+ content: string;
5
+ hasEmbedding?: boolean;
6
+ };
7
+ export type NativeMemoryAdapter = {
8
+ getEntry: (options: Record<string, unknown>) => Promise<{
9
+ success: boolean;
10
+ found: boolean;
11
+ entry?: Row;
12
+ } | null>;
13
+ storeEntry: (options: Record<string, unknown>) => Promise<{
14
+ success: boolean;
15
+ persistWarning?: unknown;
16
+ embedding?: {
17
+ dimensions?: number;
18
+ };
19
+ error?: unknown;
20
+ } | null>;
21
+ searchEntries: (options: Record<string, unknown>) => Promise<{
22
+ success: boolean;
23
+ results: Array<{
24
+ key: string;
25
+ namespace: string;
26
+ score: number;
27
+ }>;
28
+ } | null>;
29
+ };
30
+ /** Pure operation seam for host tests. Serialized callers cannot supply an adapter. */
31
+ export declare function executeManagedMemory(raw: unknown, adapter: NativeMemoryAdapter, dbPath: string, beforeWrite?: () => Promise<void>): Promise<{
32
+ v: number;
33
+ requestId: string;
34
+ ok: boolean;
35
+ operation: string;
36
+ durable: boolean;
37
+ hasEmbedding: boolean;
38
+ available?: undefined;
39
+ rows?: undefined;
40
+ } | {
41
+ v: number;
42
+ requestId: string;
43
+ ok: boolean;
44
+ operation: string;
45
+ available: boolean;
46
+ rows: {
47
+ key: string;
48
+ namespace: string;
49
+ score: number;
50
+ content: string;
51
+ }[];
52
+ durable?: undefined;
53
+ hasEmbedding?: undefined;
54
+ }>;
55
+ export {};
56
+ //# sourceMappingURL=managed-memory-worker.d.ts.map