@traqr/memory 0.2.32 → 0.2.33
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.
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdout-hygiene — ban stdout-writing calls in MCP-reachable code.
|
|
3
|
+
*
|
|
4
|
+
* The memory MCP serves JSON-RPC over stdio: STDOUT is the protocol channel.
|
|
5
|
+
* A single non-JSON line on stdout desyncs framing — the client logs
|
|
6
|
+
* "Ignoring non-JSON line on stdout" and can drop the connection (TD-927's
|
|
7
|
+
* recurring manual-reconnect symptom). #2510 fixed four such calls in
|
|
8
|
+
* src/lib by routing them to stderr; this test is the durable version of
|
|
9
|
+
* that fix — the class can't recur unnoticed.
|
|
10
|
+
*
|
|
11
|
+
* Scope (code reachable from the stdio MCP process):
|
|
12
|
+
* - packages/memory/src/lib/** (excluding *.test.ts)
|
|
13
|
+
* - packages/memory/src/vectordb/** (excluding *.test.ts)
|
|
14
|
+
* - packages/memory/src/index.ts
|
|
15
|
+
* - packages/memory-mcp/src/** (excluding cli/ and *.test.ts)
|
|
16
|
+
*
|
|
17
|
+
* Deliberately OUT of scope (stdout is the correct stream there):
|
|
18
|
+
* server.ts + routes/ (HTTP surface), migrate.ts (CLI), memory-mcp/src/cli/.
|
|
19
|
+
*
|
|
20
|
+
* Banned: console.log / console.info / console.debug (all alias to stdout in
|
|
21
|
+
* Node) and process.stdout.write. console.error / console.warn go to stderr
|
|
22
|
+
* and are the correct diagnostics channel. A deliberate pre-transport stdout
|
|
23
|
+
* write (e.g. a --help/--print-* CLI early-exit block) is allowed with an
|
|
24
|
+
* inline `stdout-ok` comment naming why.
|
|
25
|
+
*
|
|
26
|
+
* The scanner also asserts it scanned a sane number of files — a moved
|
|
27
|
+
* directory or path typo must FAIL this test, not green it ("scanned 0
|
|
28
|
+
* files" is the Total:0≠empty proxy trap).
|
|
29
|
+
*
|
|
30
|
+
* Run: npx tsx packages/memory/src/lib/stdout-hygiene.test.ts
|
|
31
|
+
*/
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stdout-hygiene — ban stdout-writing calls in MCP-reachable code.
|
|
3
|
+
*
|
|
4
|
+
* The memory MCP serves JSON-RPC over stdio: STDOUT is the protocol channel.
|
|
5
|
+
* A single non-JSON line on stdout desyncs framing — the client logs
|
|
6
|
+
* "Ignoring non-JSON line on stdout" and can drop the connection (TD-927's
|
|
7
|
+
* recurring manual-reconnect symptom). #2510 fixed four such calls in
|
|
8
|
+
* src/lib by routing them to stderr; this test is the durable version of
|
|
9
|
+
* that fix — the class can't recur unnoticed.
|
|
10
|
+
*
|
|
11
|
+
* Scope (code reachable from the stdio MCP process):
|
|
12
|
+
* - packages/memory/src/lib/** (excluding *.test.ts)
|
|
13
|
+
* - packages/memory/src/vectordb/** (excluding *.test.ts)
|
|
14
|
+
* - packages/memory/src/index.ts
|
|
15
|
+
* - packages/memory-mcp/src/** (excluding cli/ and *.test.ts)
|
|
16
|
+
*
|
|
17
|
+
* Deliberately OUT of scope (stdout is the correct stream there):
|
|
18
|
+
* server.ts + routes/ (HTTP surface), migrate.ts (CLI), memory-mcp/src/cli/.
|
|
19
|
+
*
|
|
20
|
+
* Banned: console.log / console.info / console.debug (all alias to stdout in
|
|
21
|
+
* Node) and process.stdout.write. console.error / console.warn go to stderr
|
|
22
|
+
* and are the correct diagnostics channel. A deliberate pre-transport stdout
|
|
23
|
+
* write (e.g. a --help/--print-* CLI early-exit block) is allowed with an
|
|
24
|
+
* inline `stdout-ok` comment naming why.
|
|
25
|
+
*
|
|
26
|
+
* The scanner also asserts it scanned a sane number of files — a moved
|
|
27
|
+
* directory or path typo must FAIL this test, not green it ("scanned 0
|
|
28
|
+
* files" is the Total:0≠empty proxy trap).
|
|
29
|
+
*
|
|
30
|
+
* Run: npx tsx packages/memory/src/lib/stdout-hygiene.test.ts
|
|
31
|
+
*/
|
|
32
|
+
import { readdirSync, readFileSync, existsSync } from 'node:fs';
|
|
33
|
+
import { join, dirname, relative } from 'node:path';
|
|
34
|
+
import { fileURLToPath } from 'node:url';
|
|
35
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
const memorySrc = join(__dirname, '..'); // packages/memory/src
|
|
37
|
+
const packagesRoot = join(memorySrc, '..', '..'); // packages/
|
|
38
|
+
const mcpSrc = join(packagesRoot, 'memory-mcp', 'src');
|
|
39
|
+
const BANNED = /\b(?:console\.(?:log|info|debug)|process\.stdout\.write)\s*\(/;
|
|
40
|
+
function walk(dir, files = []) {
|
|
41
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
42
|
+
const full = join(dir, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
walk(full, files);
|
|
45
|
+
}
|
|
46
|
+
else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.test.ts')) {
|
|
47
|
+
files.push(full);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return files;
|
|
51
|
+
}
|
|
52
|
+
function scanFile(file, violations) {
|
|
53
|
+
const lines = readFileSync(file, 'utf-8').split('\n');
|
|
54
|
+
lines.forEach((line, i) => {
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
// Skip comment lines (doc examples like encryption.ts's key-gen one-liner)
|
|
57
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
|
|
58
|
+
return;
|
|
59
|
+
if (!BANNED.test(line))
|
|
60
|
+
return;
|
|
61
|
+
if (line.includes('stdout-ok'))
|
|
62
|
+
return;
|
|
63
|
+
violations.push({ file, line: i + 1, text: trimmed.slice(0, 100) });
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Collect scope
|
|
67
|
+
const targets = [];
|
|
68
|
+
targets.push(...walk(join(memorySrc, 'lib')));
|
|
69
|
+
targets.push(...walk(join(memorySrc, 'vectordb')));
|
|
70
|
+
targets.push(join(memorySrc, 'index.ts'));
|
|
71
|
+
if (existsSync(mcpSrc)) {
|
|
72
|
+
for (const entry of readdirSync(mcpSrc, { withFileTypes: true })) {
|
|
73
|
+
const full = join(mcpSrc, entry.name);
|
|
74
|
+
if (entry.isDirectory() && entry.name !== 'cli') {
|
|
75
|
+
walk(full, targets);
|
|
76
|
+
}
|
|
77
|
+
else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.test.ts')) {
|
|
78
|
+
targets.push(full);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const violations = [];
|
|
83
|
+
for (const file of targets)
|
|
84
|
+
scanFile(file, violations);
|
|
85
|
+
let passed = 0;
|
|
86
|
+
let failed = 0;
|
|
87
|
+
function assert(label, condition) {
|
|
88
|
+
if (condition) {
|
|
89
|
+
console.log(` PASS ${label}`);
|
|
90
|
+
passed++;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(` FAIL ${label}`);
|
|
94
|
+
failed++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.log(`[stdout-hygiene] scanned ${targets.length} files`);
|
|
98
|
+
assert(`scanned a sane file count (${targets.length} >= 20 — path typo would shrink this)`, targets.length >= 20);
|
|
99
|
+
assert(`zero stdout-writing calls in MCP-reachable code (found ${violations.length})`, violations.length === 0);
|
|
100
|
+
if (violations.length > 0) {
|
|
101
|
+
console.log('\n Offending lines (route diagnostics to console.error, or mark deliberate');
|
|
102
|
+
console.log(' pre-transport CLI writes with an inline `stdout-ok` comment):');
|
|
103
|
+
for (const v of violations) {
|
|
104
|
+
console.log(` ${relative(packagesRoot, v.file)}:${v.line} ${v.text}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
108
|
+
if (failed > 0)
|
|
109
|
+
process.exit(1);
|
|
110
|
+
//# sourceMappingURL=stdout-hygiene.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdout-hygiene.test.js","sourceRoot":"","sources":["../../src/lib/stdout-hygiene.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@traqr/memory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.33",
|
|
4
4
|
"description": "Persistent memory for AI agents. Multi-strategy retrieval (semantic + BM25 + RRF), 3-zone cosine triage, type-aware lifecycle, entity canonicalization. Postgres + pgvector.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc",
|
|
17
17
|
"dev": "tsc --watch",
|
|
18
|
-
"test": "tsx src/lib/quality-gate.test.ts && tsx src/lib/retrieval.test.ts && tsx src/lib/classification-ceiling.test.ts && tsx src/lib/classification-enforcement.integration.test.ts && tsx src/vectordb/converters.test.ts && tsx src/lib/context.test.ts && tsx src/lib/pii-detection.test.ts && tsx src/lib/health.test.ts",
|
|
18
|
+
"test": "tsx src/lib/quality-gate.test.ts && tsx src/lib/retrieval.test.ts && tsx src/lib/classification-ceiling.test.ts && tsx src/lib/classification-enforcement.integration.test.ts && tsx src/vectordb/converters.test.ts && tsx src/lib/context.test.ts && tsx src/lib/pii-detection.test.ts && tsx src/lib/health.test.ts && tsx src/lib/stdout-hygiene.test.ts",
|
|
19
19
|
"migrate": "tsx src/migrate.ts"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|