@mmnto/mcp 1.113.1 → 1.115.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.
- package/dist/ledger-writer.d.ts +17 -0
- package/dist/ledger-writer.d.ts.map +1 -1
- package/dist/ledger-writer.js +57 -1
- package/dist/ledger-writer.js.map +1 -1
- package/dist/ledger-writer.test.js +63 -0
- package/dist/ledger-writer.test.js.map +1 -1
- package/dist/tools/search-knowledge.d.ts +37 -0
- package/dist/tools/search-knowledge.d.ts.map +1 -1
- package/dist/tools/search-knowledge.js +196 -12
- package/dist/tools/search-knowledge.js.map +1 -1
- package/dist/tools/search-knowledge.test.js +305 -1
- package/dist/tools/search-knowledge.test.js.map +1 -1
- package/dist/xml-format.d.ts +6 -2
- package/dist/xml-format.d.ts.map +1 -1
- package/dist/xml-format.js +6 -2
- package/dist/xml-format.js.map +1 -1
- package/package.json +2 -2
package/dist/ledger-writer.d.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* All writes are fire-and-forget: a ledger failure must NEVER break the tool
|
|
16
16
|
* call. Telemetry is a sensor, not an actuator (lesson-b1bae311).
|
|
17
17
|
*/
|
|
18
|
+
import type { SelectionCandidate, SelectionContextKey } from '@mmnto/totem';
|
|
18
19
|
/**
|
|
19
20
|
* Emit a single `mcp_call` ledger event for the given activity.
|
|
20
21
|
*
|
|
@@ -41,5 +42,21 @@ export declare function logMcpCall(activityName: string): Promise<void>;
|
|
|
41
42
|
* Zero hits still counts — the query RAN, and the agent saw its result. The
|
|
42
43
|
* distinction is "did a corpus query execute", not "did it find something".
|
|
43
44
|
*/
|
|
45
|
+
/**
|
|
46
|
+
* Emit the `search_knowledge` selection manifest (mmnto-ai/totem#2468 M1).
|
|
47
|
+
*
|
|
48
|
+
* Pure sensor: called only after a search actually produced a selection
|
|
49
|
+
* outcome (the same "did it run" boundary `logCorpusQuery` draws — isError
|
|
50
|
+
* outages emit nothing; the `mcp_call` denominator row makes that absence a
|
|
51
|
+
* recorded one, never a silent skip). Failures surface through the search log
|
|
52
|
+
* under the `internal:` idiom — this package speaks MCP over stdio, so
|
|
53
|
+
* stderr/stdout are off-limits by styleguide.
|
|
54
|
+
*/
|
|
55
|
+
export declare function logSelectionManifest(input: {
|
|
56
|
+
context: Partial<Record<SelectionContextKey, string | number | boolean | null>>;
|
|
57
|
+
universe: string;
|
|
58
|
+
candidates: SelectionCandidate[];
|
|
59
|
+
warnings: string[];
|
|
60
|
+
}): Promise<void>;
|
|
44
61
|
export declare function logCorpusQuery(): Promise<void>;
|
|
45
62
|
//# sourceMappingURL=ledger-writer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-writer.d.ts","sourceRoot":"","sources":["../src/ledger-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"ledger-writer.d.ts","sourceRoot":"","sources":["../src/ledger-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAe,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAWzF;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BpE;AAED;;;;;;;;;;;;;;;GAeG;AACH;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE;IAChD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BpD"}
|
package/dist/ledger-writer.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* call. Telemetry is a sensor, not an actuator (lesson-b1bae311).
|
|
17
17
|
*/
|
|
18
18
|
import * as path from 'node:path';
|
|
19
|
-
import { appendLedgerEvent, readSessionId, senseCorpusQuery } from '@mmnto/totem';
|
|
19
|
+
import { appendLedgerEvent, readSessionId, senseCorpusQuery, senseSelectionManifest, } from '@mmnto/totem';
|
|
20
20
|
import { getContext } from './context.js';
|
|
21
21
|
import { logSearch } from './search-log.js';
|
|
22
22
|
/**
|
|
@@ -72,6 +72,62 @@ export async function logMcpCall(activityName) {
|
|
|
72
72
|
* Zero hits still counts — the query RAN, and the agent saw its result. The
|
|
73
73
|
* distinction is "did a corpus query execute", not "did it find something".
|
|
74
74
|
*/
|
|
75
|
+
/**
|
|
76
|
+
* Emit the `search_knowledge` selection manifest (mmnto-ai/totem#2468 M1).
|
|
77
|
+
*
|
|
78
|
+
* Pure sensor: called only after a search actually produced a selection
|
|
79
|
+
* outcome (the same "did it run" boundary `logCorpusQuery` draws — isError
|
|
80
|
+
* outages emit nothing; the `mcp_call` denominator row makes that absence a
|
|
81
|
+
* recorded one, never a silent skip). Failures surface through the search log
|
|
82
|
+
* under the `internal:` idiom — this package speaks MCP over stdio, so
|
|
83
|
+
* stderr/stdout are off-limits by styleguide.
|
|
84
|
+
*/
|
|
85
|
+
export async function logSelectionManifest(input) {
|
|
86
|
+
// totem-context: fire-and-forget telemetry; failure must not propagate
|
|
87
|
+
try {
|
|
88
|
+
const { projectRoot, config } = await getContext();
|
|
89
|
+
const totemDir = path.join(projectRoot, config.totemDir);
|
|
90
|
+
// Best-effort emitting-package version (leg round 1, N-13 — row parity
|
|
91
|
+
// with the orient/hook emitters). `../package.json` resolves to
|
|
92
|
+
// packages/mcp/package.json from BOTH src/ and dist/ layouts.
|
|
93
|
+
const rowWarnings = [...input.warnings];
|
|
94
|
+
let emitterVersion;
|
|
95
|
+
try {
|
|
96
|
+
const { createRequire } = await import('node:module');
|
|
97
|
+
emitterVersion = createRequire(import.meta.url)('../package.json')
|
|
98
|
+
.version;
|
|
99
|
+
// totem-context: version is a best-effort enrichment of the manifest row; resolution failure must never cost the row (Tenet 13) — but it lands on the row's accounting channel rather than vanishing (PR #2625 re-review, greptile residual: this emitter had the void-err half only).
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
rowWarnings.push(`cli_version unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
103
|
+
}
|
|
104
|
+
senseSelectionManifest({
|
|
105
|
+
totemDir,
|
|
106
|
+
emitter: 'search_knowledge',
|
|
107
|
+
context: input.context,
|
|
108
|
+
universe: input.universe,
|
|
109
|
+
candidates: input.candidates,
|
|
110
|
+
warnings: rowWarnings,
|
|
111
|
+
...(emitterVersion !== undefined && { cliVersion: emitterVersion }),
|
|
112
|
+
}, (msg) => {
|
|
113
|
+
logSearch({
|
|
114
|
+
timestamp: new Date().toISOString(),
|
|
115
|
+
query: 'internal:selection-manifest',
|
|
116
|
+
resultCount: 0,
|
|
117
|
+
durationMs: 0,
|
|
118
|
+
topScore: null,
|
|
119
|
+
error: msg,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
// totem-context: fire-and-forget telemetry; failure must not propagate
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
// intentional swallow — telemetry is a sensor (lesson-b1bae311); failing to
|
|
126
|
+
// record a selection manifest must not crash the MCP server. The absence
|
|
127
|
+
// stays recorded via the mcp_call denominator row (#2468 design).
|
|
128
|
+
void err;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
75
131
|
export async function logCorpusQuery() {
|
|
76
132
|
// totem-context: fire-and-forget telemetry; failure must not propagate
|
|
77
133
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-writer.js","sourceRoot":"","sources":["../src/ledger-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,
|
|
1
|
+
{"version":3,"file":"ledger-writer.js","sourceRoot":"","sources":["../src/ledger-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,YAAoB;IACnD,0EAA0E;IAC1E,kEAAkE;IAClE,yEAAyE;IACzE,kEAAkE;IAClE,oCAAoC;IACpC,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,KAAK,GAAgB;YACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,aAAa,EAAE,YAAY;YAC3B,MAAM,EAAE,KAAK;YACb,aAAa,EAAE,EAAE;YACjB,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;SAC1D,CAAC;QAEF,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnC,uEAAuE;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iEAAiE;QACjE,qEAAqE;QACrE,KAAK,GAAG,CAAC;IACX,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAK1C;IACC,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzD,uEAAuE;QACvE,gEAAgE;QAChE,8DAA8D;QAC9D,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,cAAkC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YACtD,cAAc,GAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAA0B;iBACzF,OAAO,CAAC;YACX,uRAAuR;QACzR,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,WAAW,CAAC,IAAI,CACd,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/E,CAAC;QACJ,CAAC;QACD,sBAAsB,CACpB;YACE,QAAQ;YACR,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,QAAQ,EAAE,WAAW;YACrB,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;SACpE,EACD,CAAC,GAAG,EAAE,EAAE;YACN,SAAS,CAAC;gBACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,6BAA6B;gBACpC,WAAW,EAAE,CAAC;gBACd,UAAU,EAAE,CAAC;gBACb,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,GAAG;aACX,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QACF,uEAAuE;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,yEAAyE;QACzE,kEAAkE;QAClE,KAAK,GAAG,CAAC;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzD,gBAAgB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YACjF,0EAA0E;YAC1E,2EAA2E;YAC3E,2EAA2E;YAC3E,uEAAuE;YACvE,uEAAuE;YACvE,SAAS,CAAC;gBACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,2BAA2B;gBAClC,WAAW,EAAE,CAAC;gBACd,UAAU,EAAE,CAAC;gBACb,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,GAAG;aACX,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,uEAAuE;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,2DAA2D;QAC3D,KAAK,GAAG,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -128,4 +128,67 @@ describe('logCorpusQuery (mmnto-ai/totem#2510)', () => {
|
|
|
128
128
|
await expect(logCorpusQuery()).resolves.toBeUndefined();
|
|
129
129
|
});
|
|
130
130
|
});
|
|
131
|
+
describe('logSelectionManifest (mmnto-ai/totem#2468)', () => {
|
|
132
|
+
const input = {
|
|
133
|
+
context: { query: 'q', status: 'ok' },
|
|
134
|
+
universe: 'store-returned-pool maxResults=5',
|
|
135
|
+
candidates: [
|
|
136
|
+
{
|
|
137
|
+
id: 'a.ts',
|
|
138
|
+
disposition: 'selected',
|
|
139
|
+
reason: 'returned rank=1',
|
|
140
|
+
bytes: 4,
|
|
141
|
+
approxTokens: 1,
|
|
142
|
+
// Measured fields travel together (schema invariant, PR #2625 CR
|
|
143
|
+
// round) — a bytes-without-fingerprint fixture is now a contract
|
|
144
|
+
// violation, as it should be.
|
|
145
|
+
fingerprint: '0123456789abcdef',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
warnings: [],
|
|
149
|
+
};
|
|
150
|
+
it('writes a schema-valid row to selection-manifests.ndjson end-to-end', async () => {
|
|
151
|
+
fs.mkdirSync(path.join(tmpDir, '.totem'), { recursive: true });
|
|
152
|
+
mockContext();
|
|
153
|
+
const { logSelectionManifest } = await import('./ledger-writer.js');
|
|
154
|
+
await logSelectionManifest(input);
|
|
155
|
+
const rows = readRows(path.join(tmpDir, '.totem', 'ledger', 'selection-manifests.ndjson'));
|
|
156
|
+
expect(rows).toHaveLength(1);
|
|
157
|
+
expect(rows[0]).toMatchObject({
|
|
158
|
+
schemaVersion: 1,
|
|
159
|
+
emitter: 'search_knowledge',
|
|
160
|
+
universe: 'store-returned-pool maxResults=5',
|
|
161
|
+
});
|
|
162
|
+
expect(rows[0].costBasis).toEqual({
|
|
163
|
+
bytes: 'utf8-length',
|
|
164
|
+
approxTokens: 'ceil(bytes/4) approximation',
|
|
165
|
+
});
|
|
166
|
+
// Emitting-package version rides the row (leg round 2, finding 4 — the
|
|
167
|
+
// compile.ts precedent names "regressions that strip cli_version" as a
|
|
168
|
+
// known class; this guards the seam).
|
|
169
|
+
expect(String(rows[0].cli_version)).toMatch(/^\d+\.\d+\.\d+/);
|
|
170
|
+
// The events.ndjson stream is untouched — the sidecar ruling (#2468 OQ1).
|
|
171
|
+
expect(fs.existsSync(path.join(tmpDir, '.totem', 'ledger', 'events.ndjson'))).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
it('does not throw when getContext fails', async () => {
|
|
174
|
+
vi.doMock('./context.js', () => ({
|
|
175
|
+
getContext: async () => {
|
|
176
|
+
throw new Error('context load failed');
|
|
177
|
+
},
|
|
178
|
+
}));
|
|
179
|
+
const { logSelectionManifest } = await import('./ledger-writer.js');
|
|
180
|
+
await expect(logSelectionManifest(input)).resolves.toBeUndefined();
|
|
181
|
+
});
|
|
182
|
+
it('never throws on a contract-invalid row — the sense wrapper absorbs it, nothing persists', async () => {
|
|
183
|
+
fs.mkdirSync(path.join(tmpDir, '.totem'), { recursive: true });
|
|
184
|
+
mockContext();
|
|
185
|
+
const { logSelectionManifest } = await import('./ledger-writer.js');
|
|
186
|
+
const poisoned = {
|
|
187
|
+
...input,
|
|
188
|
+
candidates: [{ ...input.candidates[0], reason: '' }],
|
|
189
|
+
};
|
|
190
|
+
await expect(logSelectionManifest(poisoned)).resolves.toBeUndefined();
|
|
191
|
+
expect(fs.existsSync(path.join(tmpDir, '.totem', 'ledger', 'selection-manifests.ndjson'))).toBe(false);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
131
194
|
//# sourceMappingURL=ledger-writer.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-writer.test.js","sourceRoot":"","sources":["../src/ledger-writer.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ledger-writer.test.js","sourceRoot":"","sources":["../src/ledger-writer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,5 +21,42 @@ export declare function formatRetrievalEnvelope(params: {
|
|
|
21
21
|
floor: number;
|
|
22
22
|
hits: number;
|
|
23
23
|
}): string;
|
|
24
|
+
/**
|
|
25
|
+
* Per-process accumulation behind the `<size-disclosure>` envelope (#2600).
|
|
26
|
+
* The basis is the MCP server process's lifetime, declared in-band via the
|
|
27
|
+
* envelope's `scope="server-process"`: totals survive conversation clears
|
|
28
|
+
* and compactions, and a client running multiple totem MCP servers sees
|
|
29
|
+
* independent per-server totals. That is the only scope measurable
|
|
30
|
+
* UNCONDITIONALLY at this seam — `TOTEM_SESSION_ID`, when a harness sets it
|
|
31
|
+
* (see search-log.ts), could key a finer scope; deciding that is #2604.
|
|
32
|
+
* Counts non-error responses only (error bodies are bounded provider/store
|
|
33
|
+
* text, never corpus content). Exported with {@link withSizeDisclosure} so
|
|
34
|
+
* unit tests can drive and reset the accumulator directly.
|
|
35
|
+
*/
|
|
36
|
+
export declare const sessionPayload: {
|
|
37
|
+
chars: number;
|
|
38
|
+
calls: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Count the response toward the session totals and, when THIS response
|
|
42
|
+
* crosses `contextWarningThreshold`, append a self-closing measurement
|
|
43
|
+
* envelope (house style of `<index-meta>` / `<retrieval-envelope>`):
|
|
44
|
+
*
|
|
45
|
+
* `<size-disclosure chars="…" approxTokens="…" sessionChars="…" sessionCalls="…" scope="server-process" />`
|
|
46
|
+
*
|
|
47
|
+
* A measurement with NO risk claim: this seam never sees the consumer's
|
|
48
|
+
* model, window size, or occupancy, so the context-pressure warning it
|
|
49
|
+
* replaces was denominator-blind by construction (live-falsified at 15%
|
|
50
|
+
* occupancy on a 1M-window seat, #2600). The weighing judgment lives with
|
|
51
|
+
* the only party holding the denominator — the consumer, per the generated
|
|
52
|
+
* CLAUDE.md Context Management Guardrail (reflex v10, #2599). `chars` counts
|
|
53
|
+
* the delivered payload BEFORE this envelope (the envelope never counts
|
|
54
|
+
* itself, in the attribute or the accumulator). Applied once, at the
|
|
55
|
+
* handler's finalize seam AFTER the first-call warning prepend — measuring
|
|
56
|
+
* earlier understated `chars` on exactly the call a first-time consumer
|
|
57
|
+
* reads. Attribute values are numerals and a fixed token, so no XML
|
|
58
|
+
* escaping is required.
|
|
59
|
+
*/
|
|
60
|
+
export declare function withSizeDisclosure(text: string, thresholdChars: number): string;
|
|
24
61
|
export declare function registerSearchKnowledge(server: McpServer): void;
|
|
25
62
|
//# sourceMappingURL=search-knowledge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/search-knowledge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"search-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/search-knowledge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmDzE;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAyWD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,MAAM,EAAE,IAAI,GAAG,gBAAgB,GAAG,OAAO,CAAC;IAC1C,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAMT;AA2gBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc;;;CAAyB,CAAC;AAYrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAU/E;AAmCD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0P/D"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { ContentTypeSchema, DEFAULT_SEARCH_RELEVANCE_FLOOR } from '@mmnto/totem';
|
|
3
|
+
import { buildMeasuredCandidate, ContentTypeSchema, DEFAULT_SEARCH_RELEVANCE_FLOOR, } from '@mmnto/totem';
|
|
4
4
|
import { getContext, reconnectStore } from '../context.js';
|
|
5
|
-
import { logCorpusQuery, logMcpCall } from '../ledger-writer.js';
|
|
5
|
+
import { logCorpusQuery, logMcpCall, logSelectionManifest } from '../ledger-writer.js';
|
|
6
6
|
import { logSearch, setLogDir } from '../search-log.js';
|
|
7
7
|
import { extractIndexState } from '../state-extractors.js';
|
|
8
8
|
import { formatIndexEnvelope, formatSystemWarning, formatXmlResponse } from '../xml-format.js';
|
|
@@ -201,7 +201,7 @@ function formatResult(r, index) {
|
|
|
201
201
|
*
|
|
202
202
|
* mmnto/totem#1294 Phase 2 + mmnto/totem#1295 fix.
|
|
203
203
|
*/
|
|
204
|
-
async function federatedSearch(query, typeFilter, perStoreLimit, finalLimit, failures, onFtsFallback) {
|
|
204
|
+
async function federatedSearch(query, typeFilter, perStoreLimit, finalLimit, failures, onFtsFallback, overflow) {
|
|
205
205
|
const { store: primaryStore, linkedStores } = await getContext();
|
|
206
206
|
// mmnto/totem#1295 GCA HIGH: catch primary failures inside federatedSearch
|
|
207
207
|
// ONLY when linked stores exist, so a transient primary failure doesn't
|
|
@@ -309,6 +309,7 @@ async function federatedSearch(query, typeFilter, perStoreLimit, finalLimit, fai
|
|
|
309
309
|
// already comparable since they all come from one store. Skip RRF
|
|
310
310
|
// normalization to keep the original scores visible to the agent.
|
|
311
311
|
if (buckets.length === 1) {
|
|
312
|
+
overflow?.push(...primaryResults.slice(finalLimit));
|
|
312
313
|
return primaryResults.slice(0, finalLimit);
|
|
313
314
|
}
|
|
314
315
|
// mmnto/totem#1295 GCA CRITICAL: re-rank via Reciprocal Rank Fusion
|
|
@@ -342,6 +343,11 @@ async function federatedSearch(query, typeFilter, perStoreLimit, finalLimit, fai
|
|
|
342
343
|
});
|
|
343
344
|
}
|
|
344
345
|
reranked.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
346
|
+
// Selection-manifest visibility (mmnto-ai/totem#2468): the final-limit cut
|
|
347
|
+
// was this pipeline's one SILENT exclusion — fetched, ranked, then dropped
|
|
348
|
+
// with no trace. Report the cut candidates so the emitter can record them;
|
|
349
|
+
// the returned selection is byte-identical with or without the out-param.
|
|
350
|
+
overflow?.push(...reranked.slice(finalLimit));
|
|
345
351
|
return reranked.slice(0, finalLimit);
|
|
346
352
|
}
|
|
347
353
|
/**
|
|
@@ -399,6 +405,10 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
399
405
|
// `deriveLinkName` strips leading dots so a `.primary/` linked repo would
|
|
400
406
|
// collide with a reserved key. CR MAJOR catch on round 7.
|
|
401
407
|
const failures = makeFailureLog();
|
|
408
|
+
// Selection-manifest capture (mmnto-ai/totem#2468): candidates the federation
|
|
409
|
+
// fetched but cut at the final limit — populated only by Case 5, mirroring
|
|
410
|
+
// the `failures` out-param pattern. Purely observational.
|
|
411
|
+
const federationOverflow = [];
|
|
402
412
|
// ─── Boundary resolution (mmnto/totem#1294 Phase 2) ──
|
|
403
413
|
//
|
|
404
414
|
// Order of precedence:
|
|
@@ -524,7 +534,7 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
524
534
|
// Pass the `failures` log so the federation path can populate it on
|
|
525
535
|
// store errors without mutating global state. Primary lives in a
|
|
526
536
|
// dedicated slot to avoid colliding with linked-store names.
|
|
527
|
-
results = await federatedSearch(query, typeFilter, finalLimit, finalLimit, failures, onFtsFallback);
|
|
537
|
+
results = await federatedSearch(query, typeFilter, finalLimit, finalLimit, failures, onFtsFallback, federationOverflow);
|
|
528
538
|
}
|
|
529
539
|
// Build the runtime-failures warning (if any) once so we can decide
|
|
530
540
|
// whether to skip the "no results" early return for warn-only cases.
|
|
@@ -619,6 +629,94 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
619
629
|
.filter((x) => typeof x === 'number');
|
|
620
630
|
const hasRelevanceSignal = relevances.length > 0;
|
|
621
631
|
const bestRelevance = hasRelevanceSignal ? Math.max(...relevances) : null;
|
|
632
|
+
// ─── Selection-manifest emitter (mmnto-ai/totem#2468 M1) ──
|
|
633
|
+
//
|
|
634
|
+
// One manifest per selection OUTCOME (empty / no_useful_hits / mixed / ok) —
|
|
635
|
+
// the same "did a selection happen" boundary logCorpusQuery draws for the
|
|
636
|
+
// QBD row. isError outages emit nothing: the mcp_call denominator row makes
|
|
637
|
+
// that absence recorded, never silent. Each branch calls this AFTER
|
|
638
|
+
// composing its response text, so emission can never alter the selection
|
|
639
|
+
// (Tenet 13); logSelectionManifest swallows its own failures into the
|
|
640
|
+
// search log.
|
|
641
|
+
//
|
|
642
|
+
// Every candidate here was FETCHED by the policy (returned, withheld at the
|
|
643
|
+
// floor, or cut at the federation final limit), so every row is fully
|
|
644
|
+
// measured — the id-only form exists for policies that never read their
|
|
645
|
+
// exclusions, which this one has none of. `universe` names that boundary:
|
|
646
|
+
// exclusions are recorded over the fetched pool, not the whole index.
|
|
647
|
+
const emitSelectionManifest = async (status, parts) => {
|
|
648
|
+
const candidates = [];
|
|
649
|
+
const manifestWarnings = [];
|
|
650
|
+
const add = (hit, disposition, reason) => {
|
|
651
|
+
const { candidate, warning } = buildMeasuredCandidate({
|
|
652
|
+
id: hit.filePath,
|
|
653
|
+
content: hit.content,
|
|
654
|
+
disposition,
|
|
655
|
+
reason,
|
|
656
|
+
...(hit.sourceRepo !== undefined && { sourceRepo: hit.sourceRepo }),
|
|
657
|
+
});
|
|
658
|
+
candidates.push(candidate);
|
|
659
|
+
if (warning !== undefined)
|
|
660
|
+
manifestWarnings.push(warning);
|
|
661
|
+
};
|
|
662
|
+
for (const { hit, reason } of parts.selected ?? [])
|
|
663
|
+
add(hit, 'selected', reason);
|
|
664
|
+
for (const { hit, reason } of parts.excluded ?? [])
|
|
665
|
+
add(hit, 'excluded', reason);
|
|
666
|
+
for (const hit of federationOverflow)
|
|
667
|
+
add(hit, 'excluded', 'federation-final-limit overflow');
|
|
668
|
+
const federated = boundary === undefined && linkedStores.size > 0;
|
|
669
|
+
// Store outages are part of the observable-pool accounting (leg round 1,
|
|
670
|
+
// D-3): without them a query where stores errored reads as a FULL pool.
|
|
671
|
+
// Each failed store is named on the row's accounting channel, and the
|
|
672
|
+
// federated universe string carries how many stores actually answered.
|
|
673
|
+
if (failures.primary !== null) {
|
|
674
|
+
manifestWarnings.push(`store failure: primary: ${failures.primary}`);
|
|
675
|
+
}
|
|
676
|
+
for (const [name, msg] of failures.linked.entries()) {
|
|
677
|
+
manifestWarnings.push(`store failure: ${name}: ${msg}`);
|
|
678
|
+
}
|
|
679
|
+
const storesFailed = (failures.primary !== null ? 1 : 0) + failures.linked.size;
|
|
680
|
+
try {
|
|
681
|
+
await logSelectionManifest({
|
|
682
|
+
context: {
|
|
683
|
+
query,
|
|
684
|
+
boundary: boundary ?? null,
|
|
685
|
+
typeFilter: typeFilter ?? null,
|
|
686
|
+
floor: effectiveFloor,
|
|
687
|
+
finalLimit,
|
|
688
|
+
method,
|
|
689
|
+
status,
|
|
690
|
+
storesFailed,
|
|
691
|
+
// Links that never initialized are absent from `linkedStores`, so
|
|
692
|
+
// `answered` alone would read a permanently-broken link as a full
|
|
693
|
+
// pool — the exact misreading D-3 exists to prevent (leg round 2,
|
|
694
|
+
// finding 3). Counted as init-error entries NOT also present in
|
|
695
|
+
// `linkedStores`: that map carries non-fatal startup warnings for
|
|
696
|
+
// stores that still serve (empty stores, name collisions), and
|
|
697
|
+
// counting those would record an answering store as unavailable
|
|
698
|
+
// (PR #2625, greptile P1 + CR — the double-count both bots named).
|
|
699
|
+
storesUnavailable: [...linkedStoreInitErrors.keys()].filter((name) => !linkedStores.has(name)).length,
|
|
700
|
+
},
|
|
701
|
+
universe: federated
|
|
702
|
+
? `federated-returned-pool perStoreLimit=${finalLimit} stores=${linkedStores.size + 1} answered=${linkedStores.size + 1 - storesFailed}`
|
|
703
|
+
: `store-returned-pool maxResults=${finalLimit}`,
|
|
704
|
+
candidates,
|
|
705
|
+
warnings: manifestWarnings,
|
|
706
|
+
});
|
|
707
|
+
// totem-context: defense-in-depth (leg round 1, D-5) — logSelectionManifest swallows its own failures by contract; this catch guarantees the sensor can never surface as a search failure even if that contract regresses, and the failure stays visible via the search log (never swallowed silently).
|
|
708
|
+
}
|
|
709
|
+
catch (err) {
|
|
710
|
+
logSearch({
|
|
711
|
+
timestamp: new Date().toISOString(),
|
|
712
|
+
query: 'internal:selection-manifest',
|
|
713
|
+
resultCount: 0,
|
|
714
|
+
durationMs: 0,
|
|
715
|
+
topScore: null,
|
|
716
|
+
error: `selection-manifest emit failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
};
|
|
622
720
|
if (results.length === 0) {
|
|
623
721
|
if (allFederatedStoresFailed) {
|
|
624
722
|
return {
|
|
@@ -648,6 +746,7 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
648
746
|
retrievalEnvelope: emptyEnvelope,
|
|
649
747
|
body,
|
|
650
748
|
}); // totem-ignore mmnto-ai/totem#1294 — composed from system-generated + XML-wrapped pieces
|
|
749
|
+
await emitSelectionManifest('empty', {});
|
|
651
750
|
return { content: [{ type: 'text', text }] };
|
|
652
751
|
}
|
|
653
752
|
// Floor fires ONLY when a real relevance signal exists — a pure-FTS corpus
|
|
@@ -693,6 +792,12 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
693
792
|
retrievalEnvelope: belowFloorEnvelope,
|
|
694
793
|
body,
|
|
695
794
|
}); // totem-ignore mmnto-ai/totem#1294 — composed from system-generated + XML-wrapped pieces
|
|
795
|
+
await emitSelectionManifest('no_useful_hits', {
|
|
796
|
+
excluded: withheld.map((hit) => ({
|
|
797
|
+
hit,
|
|
798
|
+
reason: `below-relevance-floor floor=${effectiveFloor.toFixed(3)} relevance=${typeof hit.relevance === 'number' ? hit.relevance.toFixed(3) : 'n/a'}`,
|
|
799
|
+
})),
|
|
800
|
+
});
|
|
696
801
|
return { content: [{ type: 'text', text }] };
|
|
697
802
|
}
|
|
698
803
|
// Mixed batch: return the floor-exempt keyword hits, disclose the
|
|
@@ -714,6 +819,16 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
714
819
|
retrievalEnvelope: mixedEnvelope,
|
|
715
820
|
body,
|
|
716
821
|
}); // totem-ignore mmnto-ai/totem#1294 — composed from system-generated + XML-wrapped pieces
|
|
822
|
+
await emitSelectionManifest('ok', {
|
|
823
|
+
selected: floorExempt.map((hit) => ({
|
|
824
|
+
hit,
|
|
825
|
+
reason: 'floor-exempt keyword hit (no relevance signal)',
|
|
826
|
+
})),
|
|
827
|
+
excluded: withheld.map((hit) => ({
|
|
828
|
+
hit,
|
|
829
|
+
reason: `below-relevance-floor floor=${effectiveFloor.toFixed(3)} relevance=${typeof hit.relevance === 'number' ? hit.relevance.toFixed(3) : 'n/a'}`,
|
|
830
|
+
})),
|
|
831
|
+
});
|
|
717
832
|
return { content: [{ type: 'text', text }] };
|
|
718
833
|
}
|
|
719
834
|
const okEnvelope = formatRetrievalEnvelope({
|
|
@@ -725,7 +840,7 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
725
840
|
});
|
|
726
841
|
const formatted = results.map((r, i) => formatResult(r, i)).join('\n\n---\n\n');
|
|
727
842
|
const knowledgeBody = formatXmlResponse('knowledge', formatted);
|
|
728
|
-
|
|
843
|
+
const text = composeResponseText({
|
|
729
844
|
fallbackWarning,
|
|
730
845
|
runtimeWarning,
|
|
731
846
|
staleWarning,
|
|
@@ -733,15 +848,62 @@ async function performSearch(query, typeFilter, maxResults, boundary, minRelevan
|
|
|
733
848
|
retrievalEnvelope: okEnvelope,
|
|
734
849
|
body: knowledgeBody,
|
|
735
850
|
}); // totem-ignore mmnto-ai/totem#1294 — composed from system-generated + XML-wrapped pieces
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
'\n\n' +
|
|
740
|
-
formatSystemWarning('You just ingested a large amount of context. You may be at risk of forgetting earlier instructions. ' +
|
|
741
|
-
'Consider warning the user about context pressure and suggest running `totem handoff` to capture mid-session state.');
|
|
742
|
-
}
|
|
851
|
+
await emitSelectionManifest('ok', {
|
|
852
|
+
selected: results.map((hit, i) => ({ hit, reason: `returned rank=${i + 1}` })),
|
|
853
|
+
});
|
|
743
854
|
return { content: [{ type: 'text', text }] };
|
|
744
855
|
}
|
|
856
|
+
/**
|
|
857
|
+
* Per-process accumulation behind the `<size-disclosure>` envelope (#2600).
|
|
858
|
+
* The basis is the MCP server process's lifetime, declared in-band via the
|
|
859
|
+
* envelope's `scope="server-process"`: totals survive conversation clears
|
|
860
|
+
* and compactions, and a client running multiple totem MCP servers sees
|
|
861
|
+
* independent per-server totals. That is the only scope measurable
|
|
862
|
+
* UNCONDITIONALLY at this seam — `TOTEM_SESSION_ID`, when a harness sets it
|
|
863
|
+
* (see search-log.ts), could key a finer scope; deciding that is #2604.
|
|
864
|
+
* Counts non-error responses only (error bodies are bounded provider/store
|
|
865
|
+
* text, never corpus content). Exported with {@link withSizeDisclosure} so
|
|
866
|
+
* unit tests can drive and reset the accumulator directly.
|
|
867
|
+
*/
|
|
868
|
+
export const sessionPayload = { chars: 0, calls: 0 };
|
|
869
|
+
/** The config JSDoc's stated approximation: ~4 chars ≈ 1 token. */
|
|
870
|
+
const APPROX_CHARS_PER_TOKEN = 4;
|
|
871
|
+
/**
|
|
872
|
+
* Fallback threshold when the config cannot be re-read at the finalize seam
|
|
873
|
+
* (practically unreachable after a successful search) — mirrors the
|
|
874
|
+
* `contextWarningThreshold` default in core's config-schema.
|
|
875
|
+
*/
|
|
876
|
+
const CONTEXT_WARNING_THRESHOLD_FALLBACK = 40_000;
|
|
877
|
+
/**
|
|
878
|
+
* Count the response toward the session totals and, when THIS response
|
|
879
|
+
* crosses `contextWarningThreshold`, append a self-closing measurement
|
|
880
|
+
* envelope (house style of `<index-meta>` / `<retrieval-envelope>`):
|
|
881
|
+
*
|
|
882
|
+
* `<size-disclosure chars="…" approxTokens="…" sessionChars="…" sessionCalls="…" scope="server-process" />`
|
|
883
|
+
*
|
|
884
|
+
* A measurement with NO risk claim: this seam never sees the consumer's
|
|
885
|
+
* model, window size, or occupancy, so the context-pressure warning it
|
|
886
|
+
* replaces was denominator-blind by construction (live-falsified at 15%
|
|
887
|
+
* occupancy on a 1M-window seat, #2600). The weighing judgment lives with
|
|
888
|
+
* the only party holding the denominator — the consumer, per the generated
|
|
889
|
+
* CLAUDE.md Context Management Guardrail (reflex v10, #2599). `chars` counts
|
|
890
|
+
* the delivered payload BEFORE this envelope (the envelope never counts
|
|
891
|
+
* itself, in the attribute or the accumulator). Applied once, at the
|
|
892
|
+
* handler's finalize seam AFTER the first-call warning prepend — measuring
|
|
893
|
+
* earlier understated `chars` on exactly the call a first-time consumer
|
|
894
|
+
* reads. Attribute values are numerals and a fixed token, so no XML
|
|
895
|
+
* escaping is required.
|
|
896
|
+
*/
|
|
897
|
+
export function withSizeDisclosure(text, thresholdChars) {
|
|
898
|
+
sessionPayload.calls += 1;
|
|
899
|
+
sessionPayload.chars += text.length;
|
|
900
|
+
if (text.length <= thresholdChars)
|
|
901
|
+
return text;
|
|
902
|
+
const approxTokens = Math.ceil(text.length / APPROX_CHARS_PER_TOKEN);
|
|
903
|
+
return (text +
|
|
904
|
+
`\n\n<size-disclosure chars="${text.length}" approxTokens="${approxTokens}" ` +
|
|
905
|
+
`sessionChars="${sessionPayload.chars}" sessionCalls="${sessionPayload.calls}" scope="server-process" />`);
|
|
906
|
+
}
|
|
745
907
|
/**
|
|
746
908
|
* Compose the final response text by stacking diagnostics on top of the
|
|
747
909
|
* knowledge body. Order (outermost → innermost):
|
|
@@ -963,6 +1125,28 @@ export function registerSearchKnowledge(server) {
|
|
|
963
1125
|
text: warnings.join('\n\n') + '\n\n' + result.content[0].text, // totem-ignore #1294 — all system-generated + XML-wrapped
|
|
964
1126
|
};
|
|
965
1127
|
}
|
|
1128
|
+
// Size disclosure LAST, on the final delivered text (#2600): the
|
|
1129
|
+
// first-call warning prepend above is part of what the consumer
|
|
1130
|
+
// ingests, so measuring any earlier understates `chars` on exactly
|
|
1131
|
+
// the call a first-time consumer reads. Error responses excluded —
|
|
1132
|
+
// bounded error text, never corpus content. getContext is memoized
|
|
1133
|
+
// and already resolved for the search itself; the fallback default
|
|
1134
|
+
// is unreachable in practice.
|
|
1135
|
+
if (result.isError !== true && result.content.length > 0) {
|
|
1136
|
+
let threshold = CONTEXT_WARNING_THRESHOLD_FALLBACK;
|
|
1137
|
+
// totem-context: intentional fallback (#2600) — a context failure after a successful search cannot happen (memoized); the named default keeps the disclosure seam total rather than letting it throw away the response.
|
|
1138
|
+
try {
|
|
1139
|
+
threshold = (await getContext()).config.contextWarningThreshold;
|
|
1140
|
+
// totem-context: intentional fallback (#2600) — see directive above the try; dual placement so the rule fires on either the catch-keyword line or the catch-body line.
|
|
1141
|
+
}
|
|
1142
|
+
catch (err) {
|
|
1143
|
+
void err; // fall through to the named default
|
|
1144
|
+
}
|
|
1145
|
+
result.content[0] = {
|
|
1146
|
+
type: 'text',
|
|
1147
|
+
text: withSizeDisclosure(result.content[0].text, threshold),
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
966
1150
|
return result;
|
|
967
1151
|
}
|
|
968
1152
|
catch (err) {
|