@mmnto/totem 1.105.0 → 1.107.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/ast-classifier.d.ts +3 -3
- package/dist/ast-classifier.js +12 -3
- package/dist/ast-classifier.js.map +1 -1
- package/dist/ast-classifier.test.js +33 -2
- package/dist/ast-classifier.test.js.map +1 -1
- package/dist/capability/schema.d.ts +2 -2
- package/dist/errors.d.ts +3 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +92 -4
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +91 -13
- package/dist/ledger.js.map +1 -1
- package/dist/qbd/compliance.d.ts +216 -0
- package/dist/qbd/compliance.d.ts.map +1 -0
- package/dist/qbd/compliance.js +490 -0
- package/dist/qbd/compliance.js.map +1 -0
- package/dist/qbd/compliance.test.d.ts +2 -0
- package/dist/qbd/compliance.test.d.ts.map +1 -0
- package/dist/qbd/compliance.test.js +539 -0
- package/dist/qbd/compliance.test.js.map +1 -0
- package/dist/qbd/correlation-id.d.ts +130 -0
- package/dist/qbd/correlation-id.d.ts.map +1 -0
- package/dist/qbd/correlation-id.js +224 -0
- package/dist/qbd/correlation-id.js.map +1 -0
- package/dist/qbd/correlation-id.test.d.ts +2 -0
- package/dist/qbd/correlation-id.test.d.ts.map +1 -0
- package/dist/qbd/correlation-id.test.js +136 -0
- package/dist/qbd/correlation-id.test.js.map +1 -0
- package/dist/qbd/record.d.ts +140 -0
- package/dist/qbd/record.d.ts.map +1 -0
- package/dist/qbd/record.js +419 -0
- package/dist/qbd/record.js.map +1 -0
- package/dist/qbd/record.test.d.ts +27 -0
- package/dist/qbd/record.test.d.ts.map +1 -0
- package/dist/qbd/record.test.js +607 -0
- package/dist/qbd/record.test.js.map +1 -0
- package/dist/rule-engine.test.js +85 -0
- package/dist/rule-engine.test.js.map +1 -1
- package/dist/session-id.d.ts.map +1 -1
- package/dist/session-id.js +19 -3
- package/dist/session-id.js.map +1 -1
- package/dist/session-id.test.js +35 -0
- package/dist/session-id.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writer tests for the query-before-derive sensor (mmnto-ai/totem#2510).
|
|
3
|
+
*
|
|
4
|
+
* The induced-failure blocks follow the ADR-115 § 2 three-pack convention used
|
|
5
|
+
* by `mail-degraded-e4.test.ts`:
|
|
6
|
+
* 1. per-item accounting fires — the specific failing item is NAMED in the
|
|
7
|
+
* warnings channel;
|
|
8
|
+
* 2. the loud backstop throws — for this MUTATING path that is a literal
|
|
9
|
+
* throw from `recordDeriveAction`, and the ledger is left in prior-good
|
|
10
|
+
* state (the derive row present, simply uncorrelated) rather than
|
|
11
|
+
* "presenting as success while partial";
|
|
12
|
+
* 3. a recovery / control assertion — with the fault removed the same call
|
|
13
|
+
* returns to green, and a healthy control never warns.
|
|
14
|
+
*
|
|
15
|
+
* **The two ADR-115 § 2 packs** induce their failures with real errnos (a file
|
|
16
|
+
* where a directory belongs) or real on-disk state (a hand-written pointer),
|
|
17
|
+
* never by mocking the module under test — that is what makes them evidence
|
|
18
|
+
* rather than assertion.
|
|
19
|
+
*
|
|
20
|
+
* Other tests in this file DO stamp errnos onto `fs` via `vi.spyOn` (EACCES,
|
|
21
|
+
* ENOSPC). That is deliberate and scoped: ENOSPC is not inducible on a real
|
|
22
|
+
* filesystem, and those tests cover accounting branches rather than the
|
|
23
|
+
* degraded-path contract. The blanket "never by mocking" claim used to sit at
|
|
24
|
+
* file level and overstated what four of these tests do.
|
|
25
|
+
*/
|
|
26
|
+
import * as os from 'node:os';
|
|
27
|
+
import * as path from 'node:path';
|
|
28
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
29
|
+
// Mock node:fs so spyOn works in ESM — same pattern as session-id.test.ts.
|
|
30
|
+
// Spreads the real module, so every unmocked call is the genuine one.
|
|
31
|
+
vi.mock('node:fs', async () => {
|
|
32
|
+
const actual = await vi.importActual('node:fs');
|
|
33
|
+
return { ...actual, default: actual };
|
|
34
|
+
});
|
|
35
|
+
import * as fs from 'node:fs';
|
|
36
|
+
import { TotemError } from '../errors.js';
|
|
37
|
+
import { cleanTmpDir } from '../test-utils.js';
|
|
38
|
+
import { computeQbdCompliance, scanQbdLedger } from './compliance.js';
|
|
39
|
+
import { mintQbdCorrelationId, QBD_CORRELATION_WINDOW_MS } from './correlation-id.js';
|
|
40
|
+
import { recordCorpusQuery, recordDeriveAction, resolveQbdAgentSource, senseCorpusQuery, senseDeriveAction, } from './record.js';
|
|
41
|
+
const T0 = Date.parse('2026-07-28T12:00:00.000Z');
|
|
42
|
+
const SESSION_A = '550e8400-e29b-41d4-a716-446655440000';
|
|
43
|
+
const SESSION_B = '550e8400-e29b-41d4-a716-446655440001';
|
|
44
|
+
/**
|
|
45
|
+
* Correlation is fail-closed: it requires a session id on BOTH sides and a
|
|
46
|
+
* matching seat. So the ordinary "a query grounded this derive" fixture must
|
|
47
|
+
* supply both, exactly as a real instrumented session does.
|
|
48
|
+
*/
|
|
49
|
+
function env(sessionId = SESSION_A, agent = 'seat-a') {
|
|
50
|
+
return { TOTEM_SESSION_ID: sessionId, TOTEM_SELF_AGENT: agent };
|
|
51
|
+
}
|
|
52
|
+
let totemDir;
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
totemDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-qbd-'));
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
cleanTmpDir(totemDir);
|
|
58
|
+
});
|
|
59
|
+
function ledgerLines() {
|
|
60
|
+
const file = path.join(totemDir, 'ledger', 'events.ndjson');
|
|
61
|
+
if (!fs.existsSync(file))
|
|
62
|
+
return [];
|
|
63
|
+
return fs
|
|
64
|
+
.readFileSync(file, 'utf-8')
|
|
65
|
+
.split('\n')
|
|
66
|
+
.filter((l) => l.trim().length > 0)
|
|
67
|
+
.map((l) => JSON.parse(l));
|
|
68
|
+
}
|
|
69
|
+
function pointerFile() {
|
|
70
|
+
return path.join(totemDir, 'ledger', '.qbd-correlation');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Park a hand-written pointer. Session + seat MATCH the fixture env on purpose:
|
|
74
|
+
* correlation is fail-closed, so a mismatched pointer would be ignored before
|
|
75
|
+
* the contract check ever runs and the induced failure would never fire.
|
|
76
|
+
*/
|
|
77
|
+
function writeForgedPointer(id, mintedAtMs) {
|
|
78
|
+
fs.mkdirSync(path.join(totemDir, 'ledger'), { recursive: true });
|
|
79
|
+
fs.writeFileSync(pointerFile(), JSON.stringify({ id, mintedAtMs, sessionId: SESSION_A, agentSource: 'seat-a' }), 'utf-8');
|
|
80
|
+
}
|
|
81
|
+
describe('recordCorpusQuery', () => {
|
|
82
|
+
it('writes a corpus_query row whose ID is minted at the row instant', () => {
|
|
83
|
+
const result = recordCorpusQuery({
|
|
84
|
+
totemDir,
|
|
85
|
+
source: 'lint',
|
|
86
|
+
surface: 'totem_search',
|
|
87
|
+
nowMs: T0,
|
|
88
|
+
env: env(),
|
|
89
|
+
});
|
|
90
|
+
expect(result.written).toBe(true);
|
|
91
|
+
expect(result.warnings).toEqual([]);
|
|
92
|
+
const rows = ledgerLines();
|
|
93
|
+
expect(rows).toHaveLength(1);
|
|
94
|
+
expect(rows[0].type).toBe('corpus_query');
|
|
95
|
+
expect(rows[0].activity_name).toBe('totem_search');
|
|
96
|
+
expect(rows[0].timestamp).toBe(new Date(T0).toISOString());
|
|
97
|
+
expect(rows[0].qbd_correlation_id).toBe(result.correlationId);
|
|
98
|
+
});
|
|
99
|
+
it('parks the minted ID for the derives that follow', () => {
|
|
100
|
+
const result = recordCorpusQuery({
|
|
101
|
+
totemDir,
|
|
102
|
+
source: 'lint',
|
|
103
|
+
surface: 'totem_search',
|
|
104
|
+
nowMs: T0,
|
|
105
|
+
env: env(),
|
|
106
|
+
});
|
|
107
|
+
const pointer = JSON.parse(fs.readFileSync(pointerFile(), 'utf-8'));
|
|
108
|
+
expect(pointer.id).toBe(result.correlationId);
|
|
109
|
+
expect(pointer.mintedAtMs).toBe(T0);
|
|
110
|
+
});
|
|
111
|
+
it('stamps the seat from TOTEM_SELF_AGENT', () => {
|
|
112
|
+
recordCorpusQuery({
|
|
113
|
+
totemDir,
|
|
114
|
+
source: 'bot',
|
|
115
|
+
surface: 'search_knowledge',
|
|
116
|
+
nowMs: T0,
|
|
117
|
+
env: { TOTEM_SELF_AGENT: 'totem-claude' },
|
|
118
|
+
});
|
|
119
|
+
expect(ledgerLines()[0].agent_source).toBe('totem-claude');
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('recordDeriveAction', () => {
|
|
123
|
+
it('correlates to a query fired inside the window', () => {
|
|
124
|
+
const query = recordCorpusQuery({
|
|
125
|
+
totemDir,
|
|
126
|
+
source: 'lint',
|
|
127
|
+
surface: 'totem_search',
|
|
128
|
+
nowMs: T0,
|
|
129
|
+
env: env(),
|
|
130
|
+
});
|
|
131
|
+
const derive = recordDeriveAction({
|
|
132
|
+
totemDir,
|
|
133
|
+
source: 'lint',
|
|
134
|
+
surface: 'spec',
|
|
135
|
+
nowMs: T0 + 60_000,
|
|
136
|
+
env: env(),
|
|
137
|
+
});
|
|
138
|
+
expect(derive.correlationId).toBe(query.correlationId);
|
|
139
|
+
const rows = ledgerLines();
|
|
140
|
+
expect(rows).toHaveLength(2);
|
|
141
|
+
expect(rows[1].type).toBe('derive_action');
|
|
142
|
+
expect(rows[1].qbd_correlation_id).toBe(query.correlationId);
|
|
143
|
+
});
|
|
144
|
+
it('records an UNcorrelated derive when no query preceded it', () => {
|
|
145
|
+
// Falsifier 1: this row is the whole point of the metric. It must exist.
|
|
146
|
+
const derive = recordDeriveAction({
|
|
147
|
+
totemDir,
|
|
148
|
+
source: 'lint',
|
|
149
|
+
surface: 'orient',
|
|
150
|
+
nowMs: T0,
|
|
151
|
+
env: env(),
|
|
152
|
+
});
|
|
153
|
+
expect(derive.written).toBe(true);
|
|
154
|
+
expect(derive.correlationId).toBeUndefined();
|
|
155
|
+
const rows = ledgerLines();
|
|
156
|
+
expect(rows).toHaveLength(1);
|
|
157
|
+
expect(rows[0].type).toBe('derive_action');
|
|
158
|
+
expect(rows[0].qbd_correlation_id).toBeUndefined();
|
|
159
|
+
});
|
|
160
|
+
it('does not correlate to a query older than the window', () => {
|
|
161
|
+
recordCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() });
|
|
162
|
+
const derive = recordDeriveAction({
|
|
163
|
+
totemDir,
|
|
164
|
+
source: 'lint',
|
|
165
|
+
surface: 'review',
|
|
166
|
+
nowMs: T0 + QBD_CORRELATION_WINDOW_MS + 1000,
|
|
167
|
+
env: env(),
|
|
168
|
+
});
|
|
169
|
+
expect(derive.correlationId).toBeUndefined();
|
|
170
|
+
expect(derive.warnings).toEqual([]);
|
|
171
|
+
expect(ledgerLines()[1].qbd_correlation_id).toBeUndefined();
|
|
172
|
+
});
|
|
173
|
+
it('does not correlate across sessions', () => {
|
|
174
|
+
recordCorpusQuery({
|
|
175
|
+
totemDir,
|
|
176
|
+
source: 'lint',
|
|
177
|
+
surface: 'totem_search',
|
|
178
|
+
nowMs: T0,
|
|
179
|
+
env: env(SESSION_A),
|
|
180
|
+
});
|
|
181
|
+
const derive = recordDeriveAction({
|
|
182
|
+
totemDir,
|
|
183
|
+
source: 'lint',
|
|
184
|
+
surface: 'spec',
|
|
185
|
+
nowMs: T0 + 60_000,
|
|
186
|
+
env: env(SESSION_B),
|
|
187
|
+
});
|
|
188
|
+
expect(derive.correlationId).toBeUndefined();
|
|
189
|
+
});
|
|
190
|
+
it('does not correlate across SEATS sharing one working tree', () => {
|
|
191
|
+
// Cohort seats share one tree per repo, so seat B can reach the pointer
|
|
192
|
+
// seat A parked. `agent_source` was recorded but never consulted.
|
|
193
|
+
recordCorpusQuery({
|
|
194
|
+
totemDir,
|
|
195
|
+
source: 'lint',
|
|
196
|
+
surface: 'totem_search',
|
|
197
|
+
nowMs: T0,
|
|
198
|
+
env: env(SESSION_A, 'seat-a'),
|
|
199
|
+
});
|
|
200
|
+
const derive = recordDeriveAction({
|
|
201
|
+
totemDir,
|
|
202
|
+
source: 'lint',
|
|
203
|
+
surface: 'spec',
|
|
204
|
+
nowMs: T0 + 60_000,
|
|
205
|
+
env: env(SESSION_A, 'seat-b'),
|
|
206
|
+
});
|
|
207
|
+
expect(derive.correlationId).toBeUndefined();
|
|
208
|
+
expect(ledgerLines()[1].agent_source).toBe('seat-b');
|
|
209
|
+
});
|
|
210
|
+
it('is fail-CLOSED when either side carries no session id', () => {
|
|
211
|
+
// A hookless run must not inherit whatever pointer is lying around.
|
|
212
|
+
recordCorpusQuery({
|
|
213
|
+
totemDir,
|
|
214
|
+
source: 'lint',
|
|
215
|
+
surface: 'totem_search',
|
|
216
|
+
nowMs: T0,
|
|
217
|
+
env: { TOTEM_SELF_AGENT: 'seat-a' },
|
|
218
|
+
});
|
|
219
|
+
const derive = recordDeriveAction({
|
|
220
|
+
totemDir,
|
|
221
|
+
source: 'lint',
|
|
222
|
+
surface: 'spec',
|
|
223
|
+
nowMs: T0 + 1000,
|
|
224
|
+
env: { TOTEM_SELF_AGENT: 'seat-a' },
|
|
225
|
+
});
|
|
226
|
+
expect(derive.correlationId).toBeUndefined();
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
describe('consume-on-use — one query grounds ONE derive', () => {
|
|
230
|
+
it('does not let a single query credit an unbounded run of derives', () => {
|
|
231
|
+
const query = recordCorpusQuery({
|
|
232
|
+
totemDir,
|
|
233
|
+
source: 'lint',
|
|
234
|
+
surface: 'totem_search',
|
|
235
|
+
nowMs: T0,
|
|
236
|
+
env: env(),
|
|
237
|
+
});
|
|
238
|
+
const first = recordDeriveAction({
|
|
239
|
+
totemDir,
|
|
240
|
+
source: 'lint',
|
|
241
|
+
surface: 'spec',
|
|
242
|
+
nowMs: T0 + 1000,
|
|
243
|
+
env: env(),
|
|
244
|
+
});
|
|
245
|
+
expect(first.correlationId).toBe(query.correlationId);
|
|
246
|
+
// Every subsequent derive is uncorrelated — the query was already spent.
|
|
247
|
+
for (let i = 2; i <= 5; i++) {
|
|
248
|
+
const next = recordDeriveAction({
|
|
249
|
+
totemDir,
|
|
250
|
+
source: 'lint',
|
|
251
|
+
surface: 'spec',
|
|
252
|
+
nowMs: T0 + i * 1000,
|
|
253
|
+
env: env(),
|
|
254
|
+
});
|
|
255
|
+
expect(next.correlationId).toBeUndefined();
|
|
256
|
+
}
|
|
257
|
+
const derives = ledgerLines().filter((r) => r.type === 'derive_action');
|
|
258
|
+
expect(derives).toHaveLength(5);
|
|
259
|
+
expect(derives.filter((r) => r.qbd_correlation_id !== undefined)).toHaveLength(1);
|
|
260
|
+
});
|
|
261
|
+
it('re-arms after a fresh query', () => {
|
|
262
|
+
recordCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() });
|
|
263
|
+
recordDeriveAction({
|
|
264
|
+
totemDir,
|
|
265
|
+
source: 'lint',
|
|
266
|
+
surface: 'spec',
|
|
267
|
+
nowMs: T0 + 1000,
|
|
268
|
+
env: env(),
|
|
269
|
+
});
|
|
270
|
+
const second = recordCorpusQuery({
|
|
271
|
+
totemDir,
|
|
272
|
+
source: 'lint',
|
|
273
|
+
surface: 'totem_search',
|
|
274
|
+
nowMs: T0 + 2000,
|
|
275
|
+
env: env(),
|
|
276
|
+
});
|
|
277
|
+
const derive = recordDeriveAction({
|
|
278
|
+
totemDir,
|
|
279
|
+
source: 'lint',
|
|
280
|
+
surface: 'spec',
|
|
281
|
+
nowMs: T0 + 3000,
|
|
282
|
+
env: env(),
|
|
283
|
+
});
|
|
284
|
+
expect(derive.correlationId).toBe(second.correlationId);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
describe('induced failure — forged correlation pointer (ADR-115 § 2)', () => {
|
|
288
|
+
it('throws the loud backstop, still records the derive, and recovers', () => {
|
|
289
|
+
// ── Control: a healthy run correlates cleanly and warns about nothing.
|
|
290
|
+
recordCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() });
|
|
291
|
+
const healthy = senseDeriveAction({
|
|
292
|
+
totemDir,
|
|
293
|
+
source: 'lint',
|
|
294
|
+
surface: 'spec',
|
|
295
|
+
nowMs: T0 + 1000,
|
|
296
|
+
env: env(),
|
|
297
|
+
});
|
|
298
|
+
expect(healthy.correlationId).toBeDefined();
|
|
299
|
+
expect(healthy.warnings).toEqual([]);
|
|
300
|
+
// ── Induce: park an ID minted AFTER the derive that will claim it. This is
|
|
301
|
+
// the post-hoc correlation shape — an ID that did not exist when the derive
|
|
302
|
+
// ran cannot have grounded it.
|
|
303
|
+
const forged = mintQbdCorrelationId(T0 + 3_600_000);
|
|
304
|
+
writeForgedPointer(forged, T0 + 3_600_000);
|
|
305
|
+
// Pack 2 — the loud backstop THROWS on the mutating path.
|
|
306
|
+
let thrown;
|
|
307
|
+
try {
|
|
308
|
+
recordDeriveAction({
|
|
309
|
+
totemDir,
|
|
310
|
+
source: 'lint',
|
|
311
|
+
surface: 'spec',
|
|
312
|
+
nowMs: T0 + 2000,
|
|
313
|
+
env: env(),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
thrown = err;
|
|
318
|
+
}
|
|
319
|
+
expect(thrown).toBeInstanceOf(TotemError);
|
|
320
|
+
expect(thrown.code).toBe('QBD_CORRELATION_CONTRACT');
|
|
321
|
+
expect(thrown.message).toContain('derive-id-minted-after-derive');
|
|
322
|
+
// Prior-good state preserved: the derive row IS on disk, uncorrelated — the
|
|
323
|
+
// denominator never shrinks because someone tampered with the sensor, and
|
|
324
|
+
// the forged ID was never persisted.
|
|
325
|
+
const afterThrow = ledgerLines();
|
|
326
|
+
const lastRow = afterThrow[afterThrow.length - 1];
|
|
327
|
+
expect(lastRow.type).toBe('derive_action');
|
|
328
|
+
expect(lastRow.qbd_correlation_id).toBeUndefined();
|
|
329
|
+
expect(afterThrow.some((r) => r.qbd_correlation_id === forged)).toBe(false);
|
|
330
|
+
// Pack 1 — per-item accounting fires on the sensor path, naming the item,
|
|
331
|
+
// and the instrumented command is NOT broken (no throw).
|
|
332
|
+
const warnings = [];
|
|
333
|
+
const sensed = senseDeriveAction({ totemDir, source: 'lint', surface: 'spec', nowMs: T0 + 3000, env: env() }, (msg) => warnings.push(msg));
|
|
334
|
+
expect(sensed.written).toBe(true);
|
|
335
|
+
expect(sensed.correlationId).toBeUndefined();
|
|
336
|
+
expect(warnings.some((w) => w.includes('derive-id-minted-after-derive'))).toBe(true);
|
|
337
|
+
// Pack 3 — recovery: remove the fault, and the same call returns to green.
|
|
338
|
+
fs.rmSync(pointerFile());
|
|
339
|
+
recordCorpusQuery({
|
|
340
|
+
totemDir,
|
|
341
|
+
source: 'lint',
|
|
342
|
+
surface: 'totem_search',
|
|
343
|
+
nowMs: T0 + 4000,
|
|
344
|
+
env: env(),
|
|
345
|
+
});
|
|
346
|
+
const recoveredWarnings = [];
|
|
347
|
+
const recovered = senseDeriveAction({ totemDir, source: 'lint', surface: 'spec', nowMs: T0 + 5000, env: env() }, (msg) => recoveredWarnings.push(msg));
|
|
348
|
+
expect(recovered.correlationId).toBeDefined();
|
|
349
|
+
expect(recoveredWarnings).toEqual([]);
|
|
350
|
+
});
|
|
351
|
+
it('names a malformed pointer without breaking the command', () => {
|
|
352
|
+
fs.mkdirSync(path.join(totemDir, 'ledger'), { recursive: true });
|
|
353
|
+
fs.writeFileSync(pointerFile(), '{not json', 'utf-8');
|
|
354
|
+
const warnings = [];
|
|
355
|
+
const result = senseDeriveAction({ totemDir, source: 'lint', surface: 'orient', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
356
|
+
expect(result.written).toBe(true);
|
|
357
|
+
expect(warnings.some((w) => w.includes('not valid JSON'))).toBe(true);
|
|
358
|
+
expect(ledgerLines()).toHaveLength(1);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
describe('not an instrumented project', () => {
|
|
362
|
+
it('records nothing and warns about nothing when there is no .totem directory', () => {
|
|
363
|
+
// The derive-class commands run from anywhere. A sensor that materialised a
|
|
364
|
+
// stray `.totem/ledger/` in an unrelated directory would be a side effect,
|
|
365
|
+
// not a measurement. Absent totemDir is a NORMAL state, so: silent skip.
|
|
366
|
+
const absent = path.join(totemDir, 'no-such-project');
|
|
367
|
+
const warnings = [];
|
|
368
|
+
const result = senseDeriveAction({ totemDir: absent, source: 'lint', surface: 'orient', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
369
|
+
expect(result.written).toBe(false);
|
|
370
|
+
expect(result.skipped).toBe(true);
|
|
371
|
+
expect(warnings).toEqual([]);
|
|
372
|
+
expect(fs.existsSync(absent)).toBe(false);
|
|
373
|
+
});
|
|
374
|
+
it('does not treat a FILE at the totemDir path as a project', () => {
|
|
375
|
+
const asFile = path.join(totemDir, 'dot-totem-is-a-file');
|
|
376
|
+
fs.writeFileSync(asFile, 'not a directory', 'utf-8');
|
|
377
|
+
const result = senseCorpusQuery({
|
|
378
|
+
totemDir: asFile,
|
|
379
|
+
source: 'lint',
|
|
380
|
+
surface: 'totem_search',
|
|
381
|
+
nowMs: T0,
|
|
382
|
+
env: env(),
|
|
383
|
+
});
|
|
384
|
+
expect(result.skipped).toBe(true);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
describe('induced failure — unwritable ledger (ADR-115 § 2)', () => {
|
|
388
|
+
/**
|
|
389
|
+
* Induce a REAL errno inside a genuine project: totemDir exists as a
|
|
390
|
+
* directory, but the `ledger` path it must create is occupied by a FILE, so
|
|
391
|
+
* `mkdirSync` fails. This is a degradation (unlike an absent project) and
|
|
392
|
+
* must therefore be reported, not skipped.
|
|
393
|
+
*/
|
|
394
|
+
function blockedProject() {
|
|
395
|
+
const root = path.join(totemDir, 'blocked-project');
|
|
396
|
+
fs.mkdirSync(root, { recursive: true });
|
|
397
|
+
fs.writeFileSync(path.join(root, 'ledger'), 'not a directory', 'utf-8');
|
|
398
|
+
return root;
|
|
399
|
+
}
|
|
400
|
+
it('reports the write failure per-item and never breaks the instrumented command', () => {
|
|
401
|
+
const blocked = blockedProject();
|
|
402
|
+
const warnings = [];
|
|
403
|
+
const result = senseCorpusQuery({ totemDir: blocked, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
404
|
+
// Pack 1 — accounting fires and names the failing subsystem AND the real
|
|
405
|
+
// underlying errno. Asserting only the unconditional `query-before-derive:`
|
|
406
|
+
// prefix would pass even if the message carried no diagnosis at all, so pin
|
|
407
|
+
// the errno the OS actually raised (ENOTDIR on POSIX, EEXIST on Windows).
|
|
408
|
+
expect(result.written).toBe(false);
|
|
409
|
+
expect(warnings).toHaveLength(1);
|
|
410
|
+
expect(warnings[0]).toContain('query-before-derive');
|
|
411
|
+
expect(warnings[0]).toMatch(/ENOTDIR|EEXIST|ENOENT/);
|
|
412
|
+
// Pack 2 — for this sensor the "backstop" contract is that the failure is
|
|
413
|
+
// LOUD (surfaced above) while the instrumented command survives: sensor
|
|
414
|
+
// failure is not command failure (Tenet 13). No throw escaped.
|
|
415
|
+
expect(() => senseCorpusQuery({
|
|
416
|
+
totemDir: blocked,
|
|
417
|
+
source: 'lint',
|
|
418
|
+
surface: 'totem_search',
|
|
419
|
+
nowMs: T0,
|
|
420
|
+
env: env(),
|
|
421
|
+
})).not.toThrow();
|
|
422
|
+
// Pack 3 — recovery: a writable totemDir records cleanly again.
|
|
423
|
+
const recoveredWarnings = [];
|
|
424
|
+
const recovered = senseCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() }, (msg) => recoveredWarnings.push(msg));
|
|
425
|
+
expect(recovered.written).toBe(true);
|
|
426
|
+
expect(recoveredWarnings).toEqual([]);
|
|
427
|
+
});
|
|
428
|
+
it('reports the derive write failure ONCE, on every platform', () => {
|
|
429
|
+
// Cross-platform pin. Probing `<blocked>/ledger/.qbd-correlation` when
|
|
430
|
+
// `ledger` is a file raises ENOTDIR on POSIX and ENOENT on Windows. Both
|
|
431
|
+
// mean "no pointer here", so the pointer read must stay silent on both and
|
|
432
|
+
// the ONLY warning is the ledger write failure. Counting warnings (rather
|
|
433
|
+
// than matching one) is what makes a platform-specific extra warning fail.
|
|
434
|
+
const blocked = blockedProject();
|
|
435
|
+
const warnings = [];
|
|
436
|
+
const result = senseDeriveAction({ totemDir: blocked, source: 'lint', surface: 'spec', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
437
|
+
expect(result.written).toBe(false);
|
|
438
|
+
expect(warnings).toHaveLength(1);
|
|
439
|
+
expect(warnings[0]).toContain('query-before-derive');
|
|
440
|
+
expect(warnings[0]).not.toContain('pointer unreadable');
|
|
441
|
+
// And never the session-id layer throwing before the write path is reached.
|
|
442
|
+
expect(warnings[0]).not.toContain('Unexpected error reading session ID');
|
|
443
|
+
});
|
|
444
|
+
it('survives a POSIX-style ENOTDIR from the session-id probe (CI reproduction)', () => {
|
|
445
|
+
// This IS the ubuntu/macos CI failure, reproduced on any platform.
|
|
446
|
+
//
|
|
447
|
+
// With `ledger` occupied by a file, POSIX raises ENOTDIR when statting
|
|
448
|
+
// `<blocked>/ledger/.session-id`. `session-id.ts` did not list ENOTDIR as a
|
|
449
|
+
// benign errno, so it threw "Unexpected error reading session ID" from the
|
|
450
|
+
// session-id layer BEFORE the ledger write path — and its errno-bearing
|
|
451
|
+
// accounting — ever ran. Windows raises ENOENT for the identical state, so
|
|
452
|
+
// the whole suite passed locally and failed on two other platforms.
|
|
453
|
+
//
|
|
454
|
+
// Only the `.session-id` probe is faked: `isInstrumentedProject` also uses
|
|
455
|
+
// statSync, and faking that too would make the writer skip and prove
|
|
456
|
+
// nothing.
|
|
457
|
+
const blocked = blockedProject();
|
|
458
|
+
const realStatSync = fs.statSync.bind(fs);
|
|
459
|
+
const spy = vi.spyOn(fs, 'statSync').mockImplementation(((target) => {
|
|
460
|
+
if (String(target).endsWith('.session-id')) {
|
|
461
|
+
const err = new Error('not a directory');
|
|
462
|
+
err.code = 'ENOTDIR';
|
|
463
|
+
throw err;
|
|
464
|
+
}
|
|
465
|
+
return realStatSync(target);
|
|
466
|
+
}));
|
|
467
|
+
try {
|
|
468
|
+
const warnings = [];
|
|
469
|
+
const result = senseCorpusQuery({ totemDir: blocked, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
470
|
+
expect(result.written).toBe(false);
|
|
471
|
+
expect(warnings).toHaveLength(1);
|
|
472
|
+
// The ledger write's real errno, NOT the session-id layer throwing.
|
|
473
|
+
expect(warnings[0]).toMatch(/ENOTDIR|EEXIST|ENOENT/);
|
|
474
|
+
expect(warnings[0]).not.toContain('Unexpected error reading session ID');
|
|
475
|
+
}
|
|
476
|
+
finally {
|
|
477
|
+
spy.mockRestore();
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
it('does not park a correlation pointer when the query row failed to write', () => {
|
|
481
|
+
// Otherwise a later derive would cite a query row that does not exist —
|
|
482
|
+
// manufacturing an orphan correlation out of a write failure.
|
|
483
|
+
const blocked = blockedProject();
|
|
484
|
+
senseCorpusQuery({
|
|
485
|
+
totemDir: blocked,
|
|
486
|
+
source: 'lint',
|
|
487
|
+
surface: 'totem_search',
|
|
488
|
+
nowMs: T0,
|
|
489
|
+
env: env(),
|
|
490
|
+
});
|
|
491
|
+
expect(fs.existsSync(path.join(blocked, 'ledger', '.qbd-correlation'))).toBe(false);
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
describe('accounting branches fire (positive coverage)', () => {
|
|
495
|
+
it('reports a failure to CONSUME the pointer', () => {
|
|
496
|
+
// The over-credit path the read-side duplicate check backstops: if the
|
|
497
|
+
// pointer survives, one query can ground several derives.
|
|
498
|
+
recordCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() });
|
|
499
|
+
const spy = vi.spyOn(fs, 'rmSync').mockImplementation(() => {
|
|
500
|
+
const err = new Error('permission denied');
|
|
501
|
+
err.code = 'EACCES';
|
|
502
|
+
throw err;
|
|
503
|
+
});
|
|
504
|
+
try {
|
|
505
|
+
const warnings = [];
|
|
506
|
+
const result = senseDeriveAction({ totemDir, source: 'lint', surface: 'spec', nowMs: T0 + 1000, env: env() }, (msg) => warnings.push(msg));
|
|
507
|
+
expect(result.correlationId).toBeDefined();
|
|
508
|
+
expect(warnings.some((w) => w.includes('could not consume'))).toBe(true);
|
|
509
|
+
expect(warnings.some((w) => w.includes('over-credit'))).toBe(true);
|
|
510
|
+
}
|
|
511
|
+
finally {
|
|
512
|
+
spy.mockRestore();
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
it('reports a correlation-pointer WRITE failure', () => {
|
|
516
|
+
const spy = vi.spyOn(fs, 'writeFileSync').mockImplementation(((target) => {
|
|
517
|
+
if (String(target).endsWith('.qbd-correlation')) {
|
|
518
|
+
const err = new Error('disk full');
|
|
519
|
+
err.code = 'ENOSPC';
|
|
520
|
+
throw err;
|
|
521
|
+
}
|
|
522
|
+
}));
|
|
523
|
+
try {
|
|
524
|
+
const warnings = [];
|
|
525
|
+
senseCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() }, (msg) => warnings.push(msg));
|
|
526
|
+
expect(warnings.some((w) => w.includes('correlation pointer write failed'))).toBe(true);
|
|
527
|
+
}
|
|
528
|
+
finally {
|
|
529
|
+
spy.mockRestore();
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
it('reports an UNREADABLE correlation pointer (errno other than absent)', () => {
|
|
533
|
+
recordCorpusQuery({ totemDir, source: 'lint', surface: 'totem_search', nowMs: T0, env: env() });
|
|
534
|
+
const realRead = fs.readFileSync.bind(fs);
|
|
535
|
+
const spy = vi.spyOn(fs, 'readFileSync').mockImplementation(((target, opts) => {
|
|
536
|
+
if (String(target).endsWith('.qbd-correlation')) {
|
|
537
|
+
const err = new Error('permission denied');
|
|
538
|
+
err.code = 'EACCES';
|
|
539
|
+
throw err;
|
|
540
|
+
}
|
|
541
|
+
return realRead(target, opts);
|
|
542
|
+
}));
|
|
543
|
+
try {
|
|
544
|
+
const warnings = [];
|
|
545
|
+
senseDeriveAction({ totemDir, source: 'lint', surface: 'spec', nowMs: T0 + 1000, env: env() }, (msg) => warnings.push(msg));
|
|
546
|
+
expect(warnings.some((w) => w.includes('correlation pointer unreadable'))).toBe(true);
|
|
547
|
+
}
|
|
548
|
+
finally {
|
|
549
|
+
spy.mockRestore();
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
describe('concurrent derives on one query (best-effort)', () => {
|
|
554
|
+
it('cannot both be credited once the ledger is read back', () => {
|
|
555
|
+
// `readPointer` then `clearPointer` is not atomic, so two derives racing in
|
|
556
|
+
// separate processes can both read the same pointer. The write side cannot
|
|
557
|
+
// prevent that without a lock; the READ side is where it is caught, which is
|
|
558
|
+
// why the race is accepted rather than papered over. Simulated by
|
|
559
|
+
// suppressing the consume between the two derives.
|
|
560
|
+
const query = recordCorpusQuery({
|
|
561
|
+
totemDir,
|
|
562
|
+
source: 'lint',
|
|
563
|
+
surface: 'totem_search',
|
|
564
|
+
nowMs: T0,
|
|
565
|
+
env: env(),
|
|
566
|
+
});
|
|
567
|
+
const spy = vi.spyOn(fs, 'rmSync').mockImplementation(() => { });
|
|
568
|
+
try {
|
|
569
|
+
const a = recordDeriveAction({
|
|
570
|
+
totemDir,
|
|
571
|
+
source: 'lint',
|
|
572
|
+
surface: 'spec',
|
|
573
|
+
nowMs: T0 + 1000,
|
|
574
|
+
env: env(),
|
|
575
|
+
});
|
|
576
|
+
const b = recordDeriveAction({
|
|
577
|
+
totemDir,
|
|
578
|
+
source: 'lint',
|
|
579
|
+
surface: 'spec',
|
|
580
|
+
nowMs: T0 + 1001,
|
|
581
|
+
env: env(),
|
|
582
|
+
});
|
|
583
|
+
// Both wrote the same ID — the race really is reachable.
|
|
584
|
+
expect(a.correlationId).toBe(query.correlationId);
|
|
585
|
+
expect(b.correlationId).toBe(query.correlationId);
|
|
586
|
+
}
|
|
587
|
+
finally {
|
|
588
|
+
spy.mockRestore();
|
|
589
|
+
}
|
|
590
|
+
// And the scanner refuses to credit both, so the number stays honest.
|
|
591
|
+
const raw = fs.readFileSync(path.join(totemDir, 'ledger', 'events.ndjson'), 'utf-8');
|
|
592
|
+
const report = computeQbdCompliance(scanQbdLedger(raw));
|
|
593
|
+
expect(report.window).toEqual({ derives: 2, correlated: 1 });
|
|
594
|
+
expect(report.anomalies.duplicateCorrelations).toBe(1);
|
|
595
|
+
expect(report.degraded).toBe(true);
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
describe('resolveQbdAgentSource', () => {
|
|
599
|
+
it('takes the first non-empty comma-separated seat', () => {
|
|
600
|
+
expect(resolveQbdAgentSource({ TOTEM_SELF_AGENT: ' , totem-gemini , extra' })).toBe('totem-gemini');
|
|
601
|
+
});
|
|
602
|
+
it('is undefined when unset or blank', () => {
|
|
603
|
+
expect(resolveQbdAgentSource({})).toBeUndefined();
|
|
604
|
+
expect(resolveQbdAgentSource({ TOTEM_SELF_AGENT: ' ' })).toBeUndefined();
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
//# sourceMappingURL=record.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.test.js","sourceRoot":"","sources":["../../src/qbd/record.test.ts"],"names":[],"mappings":"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"}
|