@mindrian_os/cli 2.0.0-beta.33 → 2.0.0-beta.37
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +88 -0
- package/bin/mindrian-brain-mcp-client.cjs +14 -0
- package/commands/doctor.md +4 -3
- package/data/brain-census.generated.json +2827 -1523
- package/data/hooks-markers.json +25 -0
- package/hooks/hooks.json +0 -23
- package/lib/core/brain-client.cjs +83 -3
- package/lib/core/brain-prewarm.cjs +164 -0
- package/lib/core/doctor/class-m-brain-smoke.cjs +182 -26
- package/lib/core/doctor/class-m-brain-smoke.test.cjs +441 -82
- package/lib/core/install-id.cjs +232 -0
- package/lib/core/integration-registry.cjs +96 -20
- package/lib/mcp/brain-composition-census.cjs +22 -6
- package/lib/mcp/brain-route-bound.cjs +66 -0
- package/lib/mcp/brain-router.cjs +25 -10
- package/lib/mcp/hook-adapter-audit.cjs +13 -9
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/scripts/build-brain-census.cjs +321 -4
- package/scripts/doctor.cjs +57 -7
- package/scripts/session-start +22 -0
- package/skills/doctor/SKILL.md +4 -3
|
@@ -4,15 +4,18 @@
|
|
|
4
4
|
/*
|
|
5
5
|
* Phase 127-02 Task 2 (TDD RED -> GREEN) -- Class M Brain smoke probe tests.
|
|
6
6
|
* Extended by quick task 260819-c9b (WS-E1) for the L6 store_identity layer.
|
|
7
|
+
* Extended by quick task 260911-axz (AXZ-01) for the L0 origin-and-shadow
|
|
8
|
+
* layer prepended ahead of the original 6, making this a 7-layer probe.
|
|
7
9
|
*
|
|
8
|
-
* Covers BRAIN-MCP-127-08 acceptance (CONTEXT Deliverable 4):
|
|
9
|
-
* Test 1: LAYERS constant -- exactly
|
|
10
|
-
* Test 2: checkBrainSmoke() returns { ok, layers: [
|
|
10
|
+
* Covers BRAIN-MCP-127-08 acceptance (CONTEXT Deliverable 4), plus AXZ-01:
|
|
11
|
+
* Test 1: LAYERS constant -- exactly 7 entries with stable ids, origin_shadow first
|
|
12
|
+
* Test 2: checkBrainSmoke() returns { ok, layers: [7 x {id,name,ok,reason,ms}], overall_ms }
|
|
11
13
|
* Test 3: L1 broken topology -> L2-L6 SKIPPED with reason "skipped-prior-layer-failed"
|
|
14
|
+
* (L0 still runs and passes; it never blinds nor is blinded by L1)
|
|
12
15
|
* Test 4: L1 OK + L2 no-key -> L3-L6 SKIPPED
|
|
13
16
|
* Test 5: L1 + L2 OK + L3 unreachable -> L4-L6 SKIPPED
|
|
14
17
|
* Test 6: L1 + L2 + L3 OK + L4 timeout -> L5-L6 SKIPPED
|
|
15
|
-
* Test 7: All
|
|
18
|
+
* Test 7: All 7 layers pass when all mocks succeed; overall_ms < 30000
|
|
16
19
|
* Test 8: Each layer.ms >= 0 (sanity); ms fields are numbers
|
|
17
20
|
* Test 9: fixBrainSmoke is a no-op (diagnostic-only invariant)
|
|
18
21
|
* Test 10: opts injection seams (mockResolveRoot/mockResolveKey/mockSchema/mockSpawn
|
|
@@ -21,25 +24,54 @@
|
|
|
21
24
|
* (non-signature) failure, canon pass with payload, null-stats fail
|
|
22
25
|
* closed, and the GraphRagMeta stamp present/absent cases
|
|
23
26
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
27
|
+
* Test A: shadow present (user scope) -- not-ok, names scope, host, fix line,
|
|
28
|
+
* plugin-provides sentence, and no secret of any kind leaks
|
|
29
|
+
* Test B: shadow present (local scope) -- not-ok, scope local, fix line -s local
|
|
30
|
+
* Test C: no shadow -- ok true, reason says none found
|
|
31
|
+
* Test D: the plugin's own .mcp.json shim is never consulted by this layer
|
|
32
|
+
* (reader called exactly once, with the Claude Code config path)
|
|
33
|
+
* Test E: resolved-origin row -- resolved_origin/is_theo/override/theo_health
|
|
34
|
+
* all carried in payload, reason names the origin
|
|
35
|
+
* Test F: theo_health rejection degrades honestly, never changes ok, never throws
|
|
36
|
+
* Test G: non-Theo origin with MINDRIAN_BRAIN_URL override -- is_theo false,
|
|
37
|
+
* override true, verdict follows the shadow half only
|
|
38
|
+
* Test H: shadow present AND every L1-L6 mock passing -> all 7 layers run,
|
|
39
|
+
* L0 not-ok, L1-L6 all ok, zero "skipped-prior-layer-failed" anywhere
|
|
40
|
+
* (this is the arm that proves L0 is information-bearing, never a
|
|
41
|
+
* short circuit)
|
|
42
|
+
* Test I: THEO_NODE_FLOOR exported and === 27000; CANON_NODE_FLOOR unchanged
|
|
43
|
+
* at 29000; a Theo-origin count 1 below the floor fails naming both
|
|
44
|
+
* the count and the floor, a count at the measured 27951 passes
|
|
45
|
+
*
|
|
46
|
+
* Hermetic via the opts injection seams -- NO real network IO, NO real spawn,
|
|
47
|
+
* and Test A/B/C/D use a temp fixture file path for the L0 config reader,
|
|
48
|
+
* NEVER the real ~/.claude.json. Every all-pass option bag carries the L0 and
|
|
49
|
+
* L6 seams so neither layer ever reaches a real filesystem read of
|
|
50
|
+
* ~/.claude.json nor lib/core/brain-client.cjs (and therefore never the
|
|
51
|
+
* network) from this suite, with the sole deliberate exception of Tests
|
|
52
|
+
* A/B/C, which point the REAL lib/core/integration-registry.cjs reader at a
|
|
53
|
+
* temp fixture file to prove the projection itself (not a stand-in) strips
|
|
54
|
+
* secrets. The shell harness in tests/test-127-02-doctor-class-m.sh
|
|
28
55
|
* exercises real spawn against the actual shim binary.
|
|
29
56
|
*
|
|
30
57
|
* Canon parts:
|
|
31
58
|
* - Part 7 (reuse): LAYERS L1/L2/L3 import the existing resolver chokepoints
|
|
32
59
|
* (active-plugin-root, resolve-brain-key, brain-client.schema);
|
|
33
|
-
* L6 reuses the brain-client stats/query chokepoints
|
|
60
|
+
* L6 reuses the brain-client stats/query chokepoints; L0
|
|
61
|
+
* reuses lib/core/integration-registry.cjs's
|
|
62
|
+
* readScopedMcpServers (no third reader minted).
|
|
34
63
|
* - Part 8 (graph boundary): the smoke probe queries brain_schema and store
|
|
35
64
|
* metadata only (generic methodology handles);
|
|
36
65
|
* zero user content egress in the smoke surface.
|
|
66
|
+
* L0's projection never carries headers, the
|
|
67
|
+
* full url, or env -- only name/scope/url_host.
|
|
37
68
|
*
|
|
38
69
|
* HARD RULE: no em-dashes.
|
|
39
70
|
*/
|
|
40
71
|
|
|
41
72
|
const assert = require('node:assert/strict');
|
|
42
73
|
const fs = require('node:fs');
|
|
74
|
+
const os = require('node:os');
|
|
43
75
|
const path = require('node:path');
|
|
44
76
|
|
|
45
77
|
const REPO_ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
@@ -73,34 +105,67 @@ function freshLoad() {
|
|
|
73
105
|
return require(SMOKE_PATH);
|
|
74
106
|
}
|
|
75
107
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
108
|
+
function mkTmpConfigDir() {
|
|
109
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'axz-claude-json-'));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Shared hermetic seam bag covering EVERY layer (L0 through L6), so every
|
|
113
|
+
// test below -- including the ones that only care about L0's behavior --
|
|
114
|
+
// stays fully hermetic: L0 never blinds L1-L6 (Test H proves this), which
|
|
115
|
+
// means L1-L6 keep running even in a test that is only trying to exercise
|
|
116
|
+
// L0, and if they are not mocked they fall through to the REAL resolvers
|
|
117
|
+
// (active-plugin-root, resolve-brain-key, brain-client schema/spawn/stats),
|
|
118
|
+
// which means real filesystem/network calls. Every test below therefore
|
|
119
|
+
// spreads ALL_PASS_SEAMS FIRST and its own overrides LAST (Object.assign
|
|
120
|
+
// applies later sources over earlier ones), so a test can narrow its focus
|
|
121
|
+
// to one layer while every other layer stays mocked-and-passing.
|
|
122
|
+
//
|
|
123
|
+
// mockScopedServers here returns an empty array (no shadow) by default;
|
|
124
|
+
// Tests A/B/C/D override it (to `undefined` for A/B/C, forcing the REAL
|
|
125
|
+
// integration-registry.cjs reader against a temp fixture, or to a spy
|
|
126
|
+
// function for D) to exercise the actual reader rather than a stand-in.
|
|
127
|
+
const ALL_PASS_SEAMS = {
|
|
128
|
+
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
129
|
+
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
130
|
+
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
131
|
+
mockSpawn: async () => ({ ok: true, reason: 'ok' }),
|
|
132
|
+
mockScopedServers: () => [],
|
|
81
133
|
mockBrainUrl: () => CANON_BRAIN_URL,
|
|
134
|
+
mockTheoHealth: async () => null,
|
|
82
135
|
mockStats: async () => ({ totalRecordCount: 30000 }),
|
|
83
136
|
mockQuery: async () => null,
|
|
84
137
|
};
|
|
85
138
|
|
|
139
|
+
// The L0-only subset, for cascade tests (3-6) that deliberately override one
|
|
140
|
+
// specific L1-L4 mock to fail and need L0 (and, ahead of the failure point,
|
|
141
|
+
// the earlier L1-L4 layers) to pass cleanly. These tests spread
|
|
142
|
+
// Object.assign({}, ALL_PASS_SEAMS, L0_PASS_SEAMS_OVERRIDE_NOTE, { the one
|
|
143
|
+
// broken mock }) -- see each test body.
|
|
144
|
+
const L0_PASS_SEAMS = {
|
|
145
|
+
mockScopedServers: ALL_PASS_SEAMS.mockScopedServers,
|
|
146
|
+
mockBrainUrl: ALL_PASS_SEAMS.mockBrainUrl,
|
|
147
|
+
mockTheoHealth: ALL_PASS_SEAMS.mockTheoHealth,
|
|
148
|
+
};
|
|
149
|
+
|
|
86
150
|
// ---------------------------------------------------------------------------
|
|
87
151
|
// Test 1: LAYERS constant shape.
|
|
88
152
|
// ---------------------------------------------------------------------------
|
|
89
153
|
(async function test1_layers_constant() {
|
|
90
|
-
const label = 'LAYERS constant:
|
|
154
|
+
const label = 'LAYERS constant: 7 frozen entries with stable ids, origin_shadow first';
|
|
91
155
|
try {
|
|
92
156
|
const mod = freshLoad();
|
|
93
157
|
assert.ok(Array.isArray(mod.LAYERS), 'LAYERS must be an array');
|
|
94
|
-
assert.equal(mod.LAYERS.length,
|
|
158
|
+
assert.equal(mod.LAYERS.length, 7, 'LAYERS must have exactly 7 entries');
|
|
95
159
|
const ids = mod.LAYERS.map(l => l.id);
|
|
96
160
|
assert.deepEqual(ids, [
|
|
161
|
+
'origin_shadow',
|
|
97
162
|
'plugin_root',
|
|
98
163
|
'key_resolver',
|
|
99
164
|
'https_schema',
|
|
100
165
|
'stdio_handshake',
|
|
101
166
|
'e2e_brain_schema',
|
|
102
167
|
'store_identity',
|
|
103
|
-
], 'LAYERS ids must match the canonical
|
|
168
|
+
], 'LAYERS ids must match the canonical 7-layer probe order, L0 first');
|
|
104
169
|
for (const l of mod.LAYERS) {
|
|
105
170
|
assert.equal(typeof l.id, 'string', 'each layer has string id');
|
|
106
171
|
assert.equal(typeof l.name, 'string', 'each layer has string name');
|
|
@@ -113,7 +178,7 @@ const L6_PASS_SEAMS = {
|
|
|
113
178
|
// Test 2: checkBrainSmoke() return shape.
|
|
114
179
|
// ---------------------------------------------------------------------------
|
|
115
180
|
(async function test2_return_shape() {
|
|
116
|
-
const label = 'checkBrainSmoke() returns { ok, layers:[
|
|
181
|
+
const label = 'checkBrainSmoke() returns { ok, layers:[7], overall_ms }';
|
|
117
182
|
try {
|
|
118
183
|
const mod = freshLoad();
|
|
119
184
|
const result = await mod.checkBrainSmoke(Object.assign({
|
|
@@ -122,10 +187,10 @@ const L6_PASS_SEAMS = {
|
|
|
122
187
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
123
188
|
mockSchema: async () => ({ labels: ['Framework'], rel_types: [] }),
|
|
124
189
|
mockSpawn: async (_shimPath, opts) => ({ ok: true, reason: 'mocked ' + opts.intent }),
|
|
125
|
-
},
|
|
190
|
+
}, ALL_PASS_SEAMS));
|
|
126
191
|
assert.equal(typeof result.ok, 'boolean', 'ok must be boolean');
|
|
127
192
|
assert.ok(Array.isArray(result.layers), 'layers must be an array');
|
|
128
|
-
assert.equal(result.layers.length,
|
|
193
|
+
assert.equal(result.layers.length, 7, 'layers must have 7 entries');
|
|
129
194
|
assert.equal(typeof result.overall_ms, 'number', 'overall_ms must be number');
|
|
130
195
|
assert.ok(result.overall_ms >= 0, 'overall_ms must be >= 0');
|
|
131
196
|
for (const l of result.layers) {
|
|
@@ -140,23 +205,26 @@ const L6_PASS_SEAMS = {
|
|
|
140
205
|
})();
|
|
141
206
|
|
|
142
207
|
// ---------------------------------------------------------------------------
|
|
143
|
-
// Test 3: L1 broken -> L2..L6 skipped.
|
|
208
|
+
// Test 3: L1 broken -> L2..L6 skipped. L0 still runs and passes (index 0);
|
|
209
|
+
// L1 is now at index 1.
|
|
144
210
|
// ---------------------------------------------------------------------------
|
|
145
211
|
(async function test3_l1_broken_cascade() {
|
|
146
|
-
const label = 'L1 broken -> L2-L6 cascade to skipped-prior-layer-failed';
|
|
212
|
+
const label = 'L1 broken -> L2-L6 cascade to skipped-prior-layer-failed (L0 unaffected, passes)';
|
|
147
213
|
try {
|
|
148
214
|
const mod = freshLoad();
|
|
149
|
-
const result = await mod.checkBrainSmoke({
|
|
215
|
+
const result = await mod.checkBrainSmoke(Object.assign({
|
|
150
216
|
mockResolveRoot: () => ({ root: null, source: 'not-found', topology: 'not-found' }),
|
|
151
|
-
});
|
|
217
|
+
}, L0_PASS_SEAMS));
|
|
152
218
|
assert.equal(result.ok, false, 'overall must be false');
|
|
153
|
-
assert.equal(result.layers[0].id, '
|
|
154
|
-
assert.equal(result.layers[0].ok,
|
|
155
|
-
assert.
|
|
156
|
-
|
|
157
|
-
|
|
219
|
+
assert.equal(result.layers[0].id, 'origin_shadow', 'L0 id');
|
|
220
|
+
assert.equal(result.layers[0].ok, true, 'L0 must pass (no shadow injected, L1 failure does not blind it)');
|
|
221
|
+
assert.equal(result.layers[1].id, 'plugin_root', 'L1 id');
|
|
222
|
+
assert.equal(result.layers[1].ok, false, 'L1 must be false');
|
|
223
|
+
assert.match(result.layers[1].reason, /plugin root not resolved/i, 'L1 reason matches');
|
|
224
|
+
for (let i = 2; i < 7; i++) {
|
|
225
|
+
assert.equal(result.layers[i].ok, false, 'layer index ' + i + ' must be false (skipped)');
|
|
158
226
|
assert.equal(result.layers[i].reason, 'skipped-prior-layer-failed',
|
|
159
|
-
'
|
|
227
|
+
'layer index ' + i + ' reason must be skipped-prior-layer-failed');
|
|
160
228
|
}
|
|
161
229
|
ok(label);
|
|
162
230
|
} catch (e) { fail(label, e); }
|
|
@@ -169,18 +237,19 @@ const L6_PASS_SEAMS = {
|
|
|
169
237
|
const label = 'L1 OK + L2 no key -> L3-L6 cascade to skipped';
|
|
170
238
|
try {
|
|
171
239
|
const mod = freshLoad();
|
|
172
|
-
const result = await mod.checkBrainSmoke({
|
|
240
|
+
const result = await mod.checkBrainSmoke(Object.assign({
|
|
173
241
|
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
174
242
|
mockResolveKey: () => ({ key: null, source: 'not-found', available: false, reason: 'MINDRIAN_BRAIN_KEY not set (env) ...' }),
|
|
175
|
-
});
|
|
243
|
+
}, L0_PASS_SEAMS));
|
|
176
244
|
assert.equal(result.ok, false, 'overall must be false');
|
|
177
|
-
assert.equal(result.layers[0].ok, true, '
|
|
178
|
-
assert.equal(result.layers[1].ok,
|
|
179
|
-
assert.
|
|
180
|
-
|
|
181
|
-
|
|
245
|
+
assert.equal(result.layers[0].ok, true, 'L0 must pass');
|
|
246
|
+
assert.equal(result.layers[1].ok, true, 'L1 must be true');
|
|
247
|
+
assert.equal(result.layers[2].ok, false, 'L2 must be false');
|
|
248
|
+
assert.match(result.layers[2].reason, /MINDRIAN_BRAIN_KEY not set/, 'L2 reason carries the resolver reason');
|
|
249
|
+
for (let i = 3; i < 7; i++) {
|
|
250
|
+
assert.equal(result.layers[i].ok, false, 'layer index ' + i + ' must be false (skipped)');
|
|
182
251
|
assert.equal(result.layers[i].reason, 'skipped-prior-layer-failed',
|
|
183
|
-
'
|
|
252
|
+
'layer index ' + i + ' reason must be skipped-prior-layer-failed');
|
|
184
253
|
}
|
|
185
254
|
ok(label);
|
|
186
255
|
} catch (e) { fail(label, e); }
|
|
@@ -193,20 +262,21 @@ const L6_PASS_SEAMS = {
|
|
|
193
262
|
const label = 'L1+L2 OK + L3 returns null -> L4-L6 cascade to skipped';
|
|
194
263
|
try {
|
|
195
264
|
const mod = freshLoad();
|
|
196
|
-
const result = await mod.checkBrainSmoke({
|
|
265
|
+
const result = await mod.checkBrainSmoke(Object.assign({
|
|
197
266
|
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
198
267
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
199
268
|
mockSchema: async () => null,
|
|
200
|
-
});
|
|
269
|
+
}, L0_PASS_SEAMS));
|
|
201
270
|
assert.equal(result.ok, false, 'overall must be false');
|
|
202
|
-
assert.equal(result.layers[0].ok, true, '
|
|
203
|
-
assert.equal(result.layers[1].ok, true, '
|
|
204
|
-
assert.equal(result.layers[2].ok,
|
|
205
|
-
assert.
|
|
206
|
-
|
|
207
|
-
|
|
271
|
+
assert.equal(result.layers[0].ok, true, 'L0 ok');
|
|
272
|
+
assert.equal(result.layers[1].ok, true, 'L1 ok');
|
|
273
|
+
assert.equal(result.layers[2].ok, true, 'L2 ok');
|
|
274
|
+
assert.equal(result.layers[3].ok, false, 'L3 must be false');
|
|
275
|
+
assert.match(result.layers[3].reason, /HTTPS|schema|unreachable/i, 'L3 reason matches');
|
|
276
|
+
for (let i = 4; i < 7; i++) {
|
|
277
|
+
assert.equal(result.layers[i].ok, false, 'layer index ' + i + ' must be false (skipped)');
|
|
208
278
|
assert.equal(result.layers[i].reason, 'skipped-prior-layer-failed',
|
|
209
|
-
'
|
|
279
|
+
'layer index ' + i + ' reason must be skipped-prior-layer-failed');
|
|
210
280
|
}
|
|
211
281
|
ok(label);
|
|
212
282
|
} catch (e) { fail(label, e); }
|
|
@@ -219,7 +289,7 @@ const L6_PASS_SEAMS = {
|
|
|
219
289
|
const label = 'L1+L2+L3 OK + L4 timeout -> L5-L6 cascade to skipped';
|
|
220
290
|
try {
|
|
221
291
|
const mod = freshLoad();
|
|
222
|
-
const result = await mod.checkBrainSmoke({
|
|
292
|
+
const result = await mod.checkBrainSmoke(Object.assign({
|
|
223
293
|
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
224
294
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
225
295
|
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
@@ -227,23 +297,23 @@ const L6_PASS_SEAMS = {
|
|
|
227
297
|
if (opts.intent === 'handshake') return { ok: false, reason: 'handshake timed out after 10000ms' };
|
|
228
298
|
return { ok: true, reason: 'should-not-be-called' };
|
|
229
299
|
},
|
|
230
|
-
});
|
|
300
|
+
}, L0_PASS_SEAMS));
|
|
231
301
|
assert.equal(result.ok, false, 'overall must be false');
|
|
232
|
-
assert.equal(result.layers[
|
|
233
|
-
assert.match(result.layers[
|
|
234
|
-
assert.equal(result.layers[
|
|
235
|
-
assert.equal(result.layers[
|
|
236
|
-
assert.equal(result.layers[
|
|
237
|
-
assert.equal(result.layers[
|
|
302
|
+
assert.equal(result.layers[4].ok, false, 'L4 must be false');
|
|
303
|
+
assert.match(result.layers[4].reason, /handshake|timeout/i, 'L4 reason matches');
|
|
304
|
+
assert.equal(result.layers[5].ok, false, 'L5 must be false (skipped)');
|
|
305
|
+
assert.equal(result.layers[5].reason, 'skipped-prior-layer-failed', 'L5 reason skipped');
|
|
306
|
+
assert.equal(result.layers[6].ok, false, 'L6 must be false (skipped)');
|
|
307
|
+
assert.equal(result.layers[6].reason, 'skipped-prior-layer-failed', 'L6 reason skipped');
|
|
238
308
|
ok(label);
|
|
239
309
|
} catch (e) { fail(label, e); }
|
|
240
310
|
})();
|
|
241
311
|
|
|
242
312
|
// ---------------------------------------------------------------------------
|
|
243
|
-
// Test 7: All
|
|
313
|
+
// Test 7: All 7 layers pass; overall_ms < 30000.
|
|
244
314
|
// ---------------------------------------------------------------------------
|
|
245
315
|
(async function test7_all_pass() {
|
|
246
|
-
const label = 'All
|
|
316
|
+
const label = 'All 7 layers PASS via mocks; overall_ms < 30000 (30s budget)';
|
|
247
317
|
try {
|
|
248
318
|
const mod = freshLoad();
|
|
249
319
|
const result = await mod.checkBrainSmoke(Object.assign({
|
|
@@ -251,7 +321,7 @@ const L6_PASS_SEAMS = {
|
|
|
251
321
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
252
322
|
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
253
323
|
mockSpawn: async (_shimPath, _opts) => ({ ok: true, reason: 'mocked-success' }),
|
|
254
|
-
},
|
|
324
|
+
}, ALL_PASS_SEAMS));
|
|
255
325
|
assert.equal(result.ok, true, 'overall must be true');
|
|
256
326
|
for (const l of result.layers) {
|
|
257
327
|
assert.equal(l.ok, true, 'layer ' + l.id + ' must be true');
|
|
@@ -273,7 +343,7 @@ const L6_PASS_SEAMS = {
|
|
|
273
343
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
274
344
|
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
275
345
|
mockSpawn: async (_shimPath, _opts) => ({ ok: true, reason: 'ok' }),
|
|
276
|
-
},
|
|
346
|
+
}, ALL_PASS_SEAMS));
|
|
277
347
|
for (const l of result.layers) {
|
|
278
348
|
assert.equal(typeof l.ms, 'number', 'layer.ms is number');
|
|
279
349
|
assert.ok(l.ms >= 0, 'layer.ms must be >= 0 (got ' + l.ms + ')');
|
|
@@ -307,16 +377,16 @@ const L6_PASS_SEAMS = {
|
|
|
307
377
|
// Verify all four seams individually substitute their layer.
|
|
308
378
|
let mockSchemaCalled = false;
|
|
309
379
|
let mockSpawnCalled = false;
|
|
310
|
-
const result = await mod.checkBrainSmoke(Object.assign({
|
|
380
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
311
381
|
mockResolveRoot: () => ({ root: '/tmp/seam', source: 'opts-mock', topology: 'dev-clone' }),
|
|
312
382
|
mockResolveKey: () => ({ key: 'seam-key', source: 'opts-mock', available: true, reason: null }),
|
|
313
383
|
mockSchema: async () => { mockSchemaCalled = true; return { labels: [], rel_types: [] }; },
|
|
314
384
|
mockSpawn: async (_shimPath, _opts) => { mockSpawnCalled = true; return { ok: true, reason: 'seam-mock' }; },
|
|
315
|
-
}
|
|
385
|
+
}));
|
|
316
386
|
assert.equal(result.ok, true, 'all seams provided -> overall true');
|
|
317
387
|
assert.equal(mockSchemaCalled, true, 'mockSchema seam invoked for L3');
|
|
318
388
|
assert.equal(mockSpawnCalled, true, 'mockSpawn seam invoked for L4 and L5');
|
|
319
|
-
assert.equal(result.layers[
|
|
389
|
+
assert.equal(result.layers[1].reason, 'resolved (source=opts-mock, topology=dev-clone)', 'L1 reason carries source');
|
|
320
390
|
// Source-level class letter check (CRITICAL: plan uses Class M, not K).
|
|
321
391
|
const src = fs.readFileSync(SMOKE_PATH, 'utf8');
|
|
322
392
|
assert.match(src, /Class[- ]?M/, 'source must reference Class M (not Class K -- K is taken by --stale-first-touch)');
|
|
@@ -327,42 +397,42 @@ const L6_PASS_SEAMS = {
|
|
|
327
397
|
|
|
328
398
|
// ---------------------------------------------------------------------------
|
|
329
399
|
// Test 11: L6 store_identity contract (quick task 260819-c9b, WS-E1).
|
|
400
|
+
// Now at layers[6] (L0 prepended at index 0).
|
|
330
401
|
// ---------------------------------------------------------------------------
|
|
331
402
|
(async function test11_store_identity_contract() {
|
|
332
403
|
const label = 'L6 store_identity: stale-replica signature, below-floor, canon pass, null fail-closed, stamp present/absent';
|
|
333
404
|
try {
|
|
334
405
|
const mod = freshLoad();
|
|
335
|
-
const passBase = {
|
|
406
|
+
const passBase = Object.assign({
|
|
336
407
|
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
337
408
|
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
338
409
|
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
339
410
|
mockSpawn: async (_shimPath, _opts) => ({ ok: true, reason: 'ok' }),
|
|
340
411
|
mockBrainUrl: () => CANON_BRAIN_URL,
|
|
341
|
-
}
|
|
412
|
+
}, L0_PASS_SEAMS, {
|
|
413
|
+
mockBrainUrl: () => CANON_BRAIN_URL, // shared by L0 and L6; kept explicit here
|
|
414
|
+
});
|
|
342
415
|
|
|
343
416
|
// Case A: the stale-replica count 28325 fails and names stale_replica_signature.
|
|
344
417
|
const staleResult = await mod.checkBrainSmoke(Object.assign({}, passBase, {
|
|
345
418
|
mockStats: async () => ({ totalRecordCount: 28325 }),
|
|
346
419
|
mockQuery: async () => null,
|
|
347
420
|
}));
|
|
348
|
-
const L6stale = staleResult.layers[
|
|
421
|
+
const L6stale = staleResult.layers[6];
|
|
349
422
|
assert.equal(L6stale.id, 'store_identity', 'L6 id');
|
|
350
423
|
assert.equal(L6stale.ok, false, '28325 must FAIL');
|
|
351
424
|
assert.match(L6stale.reason, /stale_replica_signature/, 'reason names stale_replica_signature');
|
|
352
425
|
|
|
353
426
|
// Case B: below the floor but NOT the stale signature -> a DIFFERENT
|
|
354
|
-
// failure reason, without the stale_replica_signature token. 500
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
// pass. 500 sits below BOTH the incumbent floor (29000) and the coming
|
|
359
|
-
// Theo floor (1000), and it is not STALE_REPLICA_NODE_COUNT (28325),
|
|
360
|
-
// so this arm keeps testing the generic floor, not the named signature.
|
|
427
|
+
// failure reason, without the stale_replica_signature token. 500 sits
|
|
428
|
+
// below BOTH the incumbent floor (29000) and the Theo floor (27000), and
|
|
429
|
+
// it is not STALE_REPLICA_NODE_COUNT (28325), so this arm keeps testing
|
|
430
|
+
// the generic floor, not the named signature.
|
|
361
431
|
const belowFloorResult = await mod.checkBrainSmoke(Object.assign({}, passBase, {
|
|
362
432
|
mockStats: async () => ({ totalRecordCount: 500 }),
|
|
363
433
|
mockQuery: async () => null,
|
|
364
434
|
}));
|
|
365
|
-
const L6belowFloor = belowFloorResult.layers[
|
|
435
|
+
const L6belowFloor = belowFloorResult.layers[6];
|
|
366
436
|
assert.equal(L6belowFloor.ok, false, 'below-floor count must FAIL');
|
|
367
437
|
assert.equal(/stale_replica_signature/.test(L6belowFloor.reason), false,
|
|
368
438
|
'below-floor failure must NOT carry the stale_replica_signature token');
|
|
@@ -373,7 +443,7 @@ const L6_PASS_SEAMS = {
|
|
|
373
443
|
mockStats: async () => ({ totalRecordCount: 30000 }),
|
|
374
444
|
mockQuery: async () => null,
|
|
375
445
|
}));
|
|
376
|
-
const L6pass = passResult.layers[
|
|
446
|
+
const L6pass = passResult.layers[6];
|
|
377
447
|
assert.equal(L6pass.ok, true, '30000 must PASS');
|
|
378
448
|
assert.ok(L6pass.payload, 'passing layer carries a payload');
|
|
379
449
|
assert.equal(L6pass.payload.endpoint, CANON_BRAIN_URL, 'payload.endpoint');
|
|
@@ -384,15 +454,12 @@ const L6_PASS_SEAMS = {
|
|
|
384
454
|
// Case C2 (Phase 339, FLIP-11 prep): a Theo-SHAPED stats payload
|
|
385
455
|
// ({ nodes, relationships, labels }, no totalRecordCount at all) also
|
|
386
456
|
// passes and reports the same node_count, proving the `nodes` half of
|
|
387
|
-
// the dual read. 30000
|
|
388
|
-
// deliberately: it clears BOTH the incumbent floor (29000) and the
|
|
389
|
-
// coming Theo floor (1000), so this arm tests the SHAPE READ alone and
|
|
390
|
-
// cannot be knocked over by a floor change on either side of the flip.
|
|
457
|
+
// the dual read. 30000 clears both floors (29000 and 27000).
|
|
391
458
|
const theoShapeResult = await mod.checkBrainSmoke(Object.assign({}, passBase, {
|
|
392
459
|
mockStats: async () => ({ nodes: 30000, relationships: 40000, labels: 14 }),
|
|
393
460
|
mockQuery: async () => null,
|
|
394
461
|
}));
|
|
395
|
-
const L6theoShape = theoShapeResult.layers[
|
|
462
|
+
const L6theoShape = theoShapeResult.layers[6];
|
|
396
463
|
assert.equal(L6theoShape.ok, true, 'Theo-shaped stats (nodes) must PASS');
|
|
397
464
|
assert.equal(L6theoShape.payload.node_count, 30000, 'payload.node_count reads the nodes field');
|
|
398
465
|
ok('L6 store_identity: Theo-shaped stats ({nodes,relationships,labels}) dual-read PASS (added, not retargeted)');
|
|
@@ -405,7 +472,7 @@ const L6_PASS_SEAMS = {
|
|
|
405
472
|
mockStats: async () => ({ labels: 14 }),
|
|
406
473
|
mockQuery: async () => null,
|
|
407
474
|
}));
|
|
408
|
-
const L6neitherField = neitherFieldResult.layers[
|
|
475
|
+
const L6neitherField = neitherFieldResult.layers[6];
|
|
409
476
|
assert.equal(L6neitherField.ok, false, 'a payload with neither field must FAIL');
|
|
410
477
|
assert.match(L6neitherField.reason, /totalRecordCount/, 'reason names totalRecordCount');
|
|
411
478
|
assert.match(L6neitherField.reason, /nodes/, 'reason names nodes');
|
|
@@ -416,7 +483,7 @@ const L6_PASS_SEAMS = {
|
|
|
416
483
|
mockStats: async () => null,
|
|
417
484
|
mockQuery: async () => null,
|
|
418
485
|
}));
|
|
419
|
-
assert.equal(nullStatsResult.layers[
|
|
486
|
+
assert.equal(nullStatsResult.layers[6].ok, false, 'null stats must FAIL closed');
|
|
420
487
|
|
|
421
488
|
// Case E: a mockQuery returning a records array carrying a non-null
|
|
422
489
|
// schema_version puts a stamp on the payload.
|
|
@@ -424,7 +491,7 @@ const L6_PASS_SEAMS = {
|
|
|
424
491
|
mockStats: async () => ({ totalRecordCount: 30000 }),
|
|
425
492
|
mockQuery: async () => ({ records: [{ schema_version: '1.0', last_reconciled: null, refreshed_at: '2026-08-19' }] }),
|
|
426
493
|
}));
|
|
427
|
-
const L6stamp = stampResult.layers[
|
|
494
|
+
const L6stamp = stampResult.layers[6];
|
|
428
495
|
assert.equal(L6stamp.ok, true, 'stamp case still passes on count');
|
|
429
496
|
assert.ok(L6stamp.payload.stamp, 'payload carries a stamp key');
|
|
430
497
|
assert.equal(L6stamp.payload.stamp.schema_version, '1.0', 'stamp.schema_version present');
|
|
@@ -435,6 +502,298 @@ const L6_PASS_SEAMS = {
|
|
|
435
502
|
} catch (e) { fail(label, e); }
|
|
436
503
|
})();
|
|
437
504
|
|
|
505
|
+
// ---------------------------------------------------------------------------
|
|
506
|
+
// Test A (AXZ-01): shadow present, user scope. Uses the REAL
|
|
507
|
+
// integration-registry.cjs reader against a temp fixture path -- never the
|
|
508
|
+
// real ~/.claude.json.
|
|
509
|
+
// ---------------------------------------------------------------------------
|
|
510
|
+
(async function testA_shadow_user_scope() {
|
|
511
|
+
const label = 'Test A: shadow present (user scope) -- not-ok, names scope/host, exact fix line, plugin-provides sentence, zero secret leak';
|
|
512
|
+
let tmpDir;
|
|
513
|
+
try {
|
|
514
|
+
const mod = freshLoad();
|
|
515
|
+
tmpDir = mkTmpConfigDir();
|
|
516
|
+
const fixturePath = path.join(tmpDir, 'claude.json');
|
|
517
|
+
fs.writeFileSync(fixturePath, JSON.stringify({
|
|
518
|
+
mcpServers: {
|
|
519
|
+
'mindrian-brain': {
|
|
520
|
+
type: 'http',
|
|
521
|
+
url: 'https://mindrian-brain.onrender.com/mcp',
|
|
522
|
+
headers: { Authorization: 'Bearer sk-SHOULD-NEVER-APPEAR' },
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
}));
|
|
526
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
527
|
+
mockScopedServers: undefined, // force the REAL reader for this arm
|
|
528
|
+
claudeConfigPath: fixturePath,
|
|
529
|
+
projectDir: '/nonexistent-project-dir',
|
|
530
|
+
}));
|
|
531
|
+
const L0 = result.layers[0];
|
|
532
|
+
assert.equal(L0.id, 'origin_shadow', 'L0 id');
|
|
533
|
+
assert.equal(L0.ok, false, 'L0 must be not-ok when a shadow is present');
|
|
534
|
+
assert.match(L0.reason, /\buser\b/, 'reason names scope user');
|
|
535
|
+
assert.match(L0.reason, /mindrian-brain\.onrender\.com/, 'reason contains the host');
|
|
536
|
+
assert.ok(
|
|
537
|
+
L0.reason.indexOf('claude mcp remove mindrian-brain -s user') !== -1,
|
|
538
|
+
'reason contains the exact removal command'
|
|
539
|
+
);
|
|
540
|
+
assert.match(L0.reason, /the plugin provides this server/, 'reason states the plugin provides this server');
|
|
541
|
+
const serialized = JSON.stringify(result);
|
|
542
|
+
assert.equal(serialized.indexOf('sk-SHOULD-NEVER-APPEAR'), -1, 'must not leak the planted secret');
|
|
543
|
+
assert.equal(serialized.indexOf('Bearer'), -1, 'must not leak the word Bearer');
|
|
544
|
+
assert.equal(serialized.indexOf('Authorization'), -1, 'must not leak the word Authorization');
|
|
545
|
+
assert.equal(serialized.indexOf('/mcp'), -1, 'must not leak the full /mcp URL path');
|
|
546
|
+
ok(label);
|
|
547
|
+
} catch (e) { fail(label, e); } finally {
|
|
548
|
+
if (tmpDir) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
549
|
+
}
|
|
550
|
+
})();
|
|
551
|
+
|
|
552
|
+
// ---------------------------------------------------------------------------
|
|
553
|
+
// Test B (AXZ-01): shadow present, local scope (projects[dir].mcpServers).
|
|
554
|
+
// ---------------------------------------------------------------------------
|
|
555
|
+
(async function testB_shadow_local_scope() {
|
|
556
|
+
const label = 'Test B: shadow present (local scope) -- scope local, fix line -s local';
|
|
557
|
+
let tmpDir;
|
|
558
|
+
try {
|
|
559
|
+
const mod = freshLoad();
|
|
560
|
+
tmpDir = mkTmpConfigDir();
|
|
561
|
+
const fixturePath = path.join(tmpDir, 'claude.json');
|
|
562
|
+
const projectDir = '/some/dir';
|
|
563
|
+
fs.writeFileSync(fixturePath, JSON.stringify({
|
|
564
|
+
projects: {
|
|
565
|
+
[projectDir]: {
|
|
566
|
+
mcpServers: {
|
|
567
|
+
'mindrian-brain': {
|
|
568
|
+
type: 'http',
|
|
569
|
+
url: 'https://mindrian-brain.onrender.com/mcp',
|
|
570
|
+
headers: { Authorization: 'Bearer sk-SHOULD-NEVER-APPEAR-2' },
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
}));
|
|
576
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
577
|
+
mockScopedServers: undefined,
|
|
578
|
+
claudeConfigPath: fixturePath,
|
|
579
|
+
projectDir: projectDir,
|
|
580
|
+
}));
|
|
581
|
+
const L0 = result.layers[0];
|
|
582
|
+
assert.equal(L0.ok, false, 'must be not-ok for a local-scope shadow');
|
|
583
|
+
assert.match(L0.reason, /\blocal\b/, 'reason names scope local');
|
|
584
|
+
assert.ok(
|
|
585
|
+
L0.reason.indexOf('claude mcp remove mindrian-brain -s local') !== -1,
|
|
586
|
+
'reason contains the exact local-scope removal command'
|
|
587
|
+
);
|
|
588
|
+
ok(label);
|
|
589
|
+
} catch (e) { fail(label, e); } finally {
|
|
590
|
+
if (tmpDir) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
591
|
+
}
|
|
592
|
+
})();
|
|
593
|
+
|
|
594
|
+
// ---------------------------------------------------------------------------
|
|
595
|
+
// Test C (AXZ-01): no shadow -- unrelated servers only.
|
|
596
|
+
// ---------------------------------------------------------------------------
|
|
597
|
+
(async function testC_no_shadow() {
|
|
598
|
+
const label = 'Test C: no shadow -- ok true, reason says none found';
|
|
599
|
+
let tmpDir;
|
|
600
|
+
try {
|
|
601
|
+
const mod = freshLoad();
|
|
602
|
+
tmpDir = mkTmpConfigDir();
|
|
603
|
+
const fixturePath = path.join(tmpDir, 'claude.json');
|
|
604
|
+
fs.writeFileSync(fixturePath, JSON.stringify({
|
|
605
|
+
mcpServers: {
|
|
606
|
+
theo: { command: 'node', args: ['theo.cjs'] },
|
|
607
|
+
pinecone: { type: 'http', url: 'https://pinecone.example.com/mcp' },
|
|
608
|
+
},
|
|
609
|
+
}));
|
|
610
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
611
|
+
mockScopedServers: undefined,
|
|
612
|
+
claudeConfigPath: fixturePath,
|
|
613
|
+
projectDir: '/nonexistent-project-dir',
|
|
614
|
+
}));
|
|
615
|
+
const L0 = result.layers[0];
|
|
616
|
+
assert.equal(L0.ok, true, 'no shadow -> ok true');
|
|
617
|
+
assert.match(L0.reason, /no shadowing/i, 'reason says no shadowing entry found');
|
|
618
|
+
ok(label);
|
|
619
|
+
} catch (e) { fail(label, e); } finally {
|
|
620
|
+
if (tmpDir) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
621
|
+
}
|
|
622
|
+
})();
|
|
623
|
+
|
|
624
|
+
// ---------------------------------------------------------------------------
|
|
625
|
+
// Test D (AXZ-01): the plugin's own .mcp.json shim is never consulted by
|
|
626
|
+
// this layer -- the reader is called exactly once, and always with the
|
|
627
|
+
// Claude Code config path, never a .mcp.json path.
|
|
628
|
+
// ---------------------------------------------------------------------------
|
|
629
|
+
(async function testD_shim_never_shadow() {
|
|
630
|
+
const label = "Test D: the plugin's own .mcp.json shim is never consulted; reader called once with the Claude Code path";
|
|
631
|
+
let tmpDir;
|
|
632
|
+
try {
|
|
633
|
+
const mod = freshLoad();
|
|
634
|
+
tmpDir = mkTmpConfigDir();
|
|
635
|
+
const mcpJsonPath = path.join(tmpDir, '.mcp.json');
|
|
636
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify({ mcpServers: { 'mindrian-brain': { command: 'node' } } }));
|
|
637
|
+
const claudeCodePath = path.join(tmpDir, 'claude.json');
|
|
638
|
+
fs.writeFileSync(claudeCodePath, JSON.stringify({ mcpServers: {} }));
|
|
639
|
+
|
|
640
|
+
let callCount = 0;
|
|
641
|
+
const calls = [];
|
|
642
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
643
|
+
mockScopedServers: function (readerOpts) {
|
|
644
|
+
callCount += 1;
|
|
645
|
+
calls.push(readerOpts);
|
|
646
|
+
return [];
|
|
647
|
+
},
|
|
648
|
+
claudeConfigPath: claudeCodePath,
|
|
649
|
+
projectDir: tmpDir,
|
|
650
|
+
}));
|
|
651
|
+
assert.ok(result, 'result present');
|
|
652
|
+
assert.equal(callCount, 1, 'the reader is called exactly once');
|
|
653
|
+
assert.equal(calls[0].configPath, claudeCodePath, 'reader called with the Claude Code config path');
|
|
654
|
+
assert.notEqual(calls[0].configPath, mcpJsonPath, 'reader is never called with the .mcp.json path');
|
|
655
|
+
ok(label);
|
|
656
|
+
} catch (e) { fail(label, e); } finally {
|
|
657
|
+
if (tmpDir) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
658
|
+
}
|
|
659
|
+
})();
|
|
660
|
+
|
|
661
|
+
// ---------------------------------------------------------------------------
|
|
662
|
+
// Test E (AXZ-01): resolved-origin row, always reported.
|
|
663
|
+
// ---------------------------------------------------------------------------
|
|
664
|
+
(async function testE_resolved_origin_row() {
|
|
665
|
+
const label = 'Test E: resolved-origin row -- resolved_origin/is_theo/override/theo_health carried, reason names origin';
|
|
666
|
+
try {
|
|
667
|
+
const mod = freshLoad();
|
|
668
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
669
|
+
mockScopedServers: () => [],
|
|
670
|
+
mockBrainUrl: () => CANON_BRAIN_URL,
|
|
671
|
+
mockTheoHealth: async () => ({ mode: 'ok', build_stamp: { sha: 'abc1234' } }),
|
|
672
|
+
}));
|
|
673
|
+
const L0 = result.layers[0];
|
|
674
|
+
assert.equal(L0.payload.resolved_origin, CANON_BRAIN_URL, 'payload.resolved_origin');
|
|
675
|
+
assert.equal(L0.payload.is_theo, true, 'payload.is_theo true for a Theo origin');
|
|
676
|
+
assert.equal(L0.payload.override, false, 'payload.override false when MINDRIAN_BRAIN_URL is unset');
|
|
677
|
+
assert.ok(L0.payload.theo_health, 'payload.theo_health present');
|
|
678
|
+
assert.equal(L0.payload.theo_health.mode, 'ok', 'theo_health.mode');
|
|
679
|
+
assert.equal(L0.payload.theo_health.build_sha, 'abc1234', 'theo_health.build_sha');
|
|
680
|
+
assert.ok(L0.reason.indexOf(CANON_BRAIN_URL) !== -1, 'reason names the resolved origin');
|
|
681
|
+
ok(label);
|
|
682
|
+
} catch (e) { fail(label, e); }
|
|
683
|
+
})();
|
|
684
|
+
|
|
685
|
+
// ---------------------------------------------------------------------------
|
|
686
|
+
// Test F (AXZ-01): theo_health rejection degrades honestly.
|
|
687
|
+
// ---------------------------------------------------------------------------
|
|
688
|
+
(async function testF_origin_degrades_honestly() {
|
|
689
|
+
const label = 'Test F: theo_health rejection degrades honestly -- no throw, no theo_health key, ok unaffected';
|
|
690
|
+
try {
|
|
691
|
+
const mod = freshLoad();
|
|
692
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
693
|
+
mockScopedServers: () => [],
|
|
694
|
+
mockBrainUrl: () => CANON_BRAIN_URL,
|
|
695
|
+
mockTheoHealth: async () => { throw new Error('boom'); },
|
|
696
|
+
}));
|
|
697
|
+
const L0 = result.layers[0];
|
|
698
|
+
assert.equal(L0.ok, true, 'ok unaffected by a theo_health rejection (no shadow present)');
|
|
699
|
+
assert.equal('theo_health' in L0.payload, false, 'theo_health key absent on rejection');
|
|
700
|
+
ok(label);
|
|
701
|
+
} catch (e) { fail(label, e); }
|
|
702
|
+
})();
|
|
703
|
+
|
|
704
|
+
// ---------------------------------------------------------------------------
|
|
705
|
+
// Test G (AXZ-01): non-Theo origin with MINDRIAN_BRAIN_URL override.
|
|
706
|
+
// ---------------------------------------------------------------------------
|
|
707
|
+
(async function testG_non_theo_origin() {
|
|
708
|
+
const label = 'Test G: non-Theo origin, MINDRIAN_BRAIN_URL override -- is_theo false, override true, ok follows shadow only';
|
|
709
|
+
// A non-Theo origin literal, deliberately NOT a real onrender.com host:
|
|
710
|
+
// tests/test-339-origin-single-source.cjs scans lib/ for exactly those
|
|
711
|
+
// origin literals and this file is not on its two-entry allowlist. Any
|
|
712
|
+
// fixture host outside THEO_ORIGINS exercises the is_theo=false branch
|
|
713
|
+
// just as well.
|
|
714
|
+
const NON_THEO_ORIGIN = 'https://not-theo-origin.example.test';
|
|
715
|
+
const prevEnv = process.env.MINDRIAN_BRAIN_URL;
|
|
716
|
+
try {
|
|
717
|
+
process.env.MINDRIAN_BRAIN_URL = NON_THEO_ORIGIN;
|
|
718
|
+
const mod = freshLoad();
|
|
719
|
+
const result = await mod.checkBrainSmoke(Object.assign({}, ALL_PASS_SEAMS, {
|
|
720
|
+
mockScopedServers: () => [],
|
|
721
|
+
mockBrainUrl: () => NON_THEO_ORIGIN,
|
|
722
|
+
mockTheoHealth: async () => null,
|
|
723
|
+
}));
|
|
724
|
+
const L0 = result.layers[0];
|
|
725
|
+
assert.equal(L0.payload.is_theo, false, 'is_theo false for a non-Theo origin');
|
|
726
|
+
assert.equal(L0.payload.override, true, 'override true when MINDRIAN_BRAIN_URL is set');
|
|
727
|
+
assert.equal(L0.ok, true, 'ok reflects the shadow verdict only (no shadow present here)');
|
|
728
|
+
ok(label);
|
|
729
|
+
} catch (e) { fail(label, e); } finally {
|
|
730
|
+
if (prevEnv === undefined) delete process.env.MINDRIAN_BRAIN_URL;
|
|
731
|
+
else process.env.MINDRIAN_BRAIN_URL = prevEnv;
|
|
732
|
+
}
|
|
733
|
+
})();
|
|
734
|
+
|
|
735
|
+
// ---------------------------------------------------------------------------
|
|
736
|
+
// Test H (AXZ-01): no short circuit -- shadow present AND every L1-L6 mock
|
|
737
|
+
// passing must still run and report L1-L6 truthfully.
|
|
738
|
+
// ---------------------------------------------------------------------------
|
|
739
|
+
(async function testH_no_short_circuit() {
|
|
740
|
+
const label = 'Test H: shadow present does not blind L1-L6 -- all 7 layers run, zero skipped-prior-layer-failed';
|
|
741
|
+
try {
|
|
742
|
+
const mod = freshLoad();
|
|
743
|
+
const result = await mod.checkBrainSmoke(Object.assign({
|
|
744
|
+
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
745
|
+
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
746
|
+
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
747
|
+
mockSpawn: async (_shimPath, _opts) => ({ ok: true, reason: 'mocked-success' }),
|
|
748
|
+
}, ALL_PASS_SEAMS, {
|
|
749
|
+
mockScopedServers: () => [{ name: 'mindrian-brain', scope: 'user', url_host: 'mindrian-brain.onrender.com', type: 'http' }],
|
|
750
|
+
}));
|
|
751
|
+
assert.equal(result.layers.length, 7, 'layers.length === 7');
|
|
752
|
+
assert.equal(result.layers[0].id, 'origin_shadow', 'layers[0].id');
|
|
753
|
+
assert.equal(result.layers[0].ok, false, 'layers[0].ok false (shadow present)');
|
|
754
|
+
for (let i = 1; i < 7; i++) {
|
|
755
|
+
assert.equal(result.layers[i].ok, true, 'layer index ' + i + ' must PASS, not be blinded by L0');
|
|
756
|
+
assert.notEqual(result.layers[i].reason, 'skipped-prior-layer-failed', 'layer index ' + i + ' must never be skipped');
|
|
757
|
+
}
|
|
758
|
+
ok(label);
|
|
759
|
+
} catch (e) { fail(label, e); }
|
|
760
|
+
})();
|
|
761
|
+
|
|
762
|
+
// ---------------------------------------------------------------------------
|
|
763
|
+
// Test I (AXZ-01): THEO_NODE_FLOOR moved to 27000; CANON_NODE_FLOOR unchanged.
|
|
764
|
+
// ---------------------------------------------------------------------------
|
|
765
|
+
(async function testI_floor() {
|
|
766
|
+
const label = 'Test I: THEO_NODE_FLOOR === 27000 (exported), CANON_NODE_FLOOR unchanged at 29000';
|
|
767
|
+
try {
|
|
768
|
+
const mod = freshLoad();
|
|
769
|
+
assert.equal(mod.THEO_NODE_FLOOR, 27000, 'THEO_NODE_FLOOR must be 27000');
|
|
770
|
+
assert.equal(mod.CANON_NODE_FLOOR, 29000, 'CANON_NODE_FLOOR must stay 29000');
|
|
771
|
+
|
|
772
|
+
const commonMocks = {
|
|
773
|
+
mockResolveRoot: () => ({ root: '/tmp/fake', source: 'env', topology: 'dev-clone' }),
|
|
774
|
+
mockResolveKey: () => ({ key: 'k', source: 'env', available: true, reason: null }),
|
|
775
|
+
mockSchema: async () => ({ labels: ['Framework'] }),
|
|
776
|
+
mockSpawn: async () => ({ ok: true, reason: 'ok' }),
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
const belowResult = await mod.checkBrainSmoke(Object.assign({}, commonMocks, ALL_PASS_SEAMS, {
|
|
780
|
+
mockStats: async () => ({ nodes: 26999 }),
|
|
781
|
+
}));
|
|
782
|
+
const L6below = belowResult.layers[6];
|
|
783
|
+
assert.equal(L6below.ok, false, '26999 must fail the 27000 floor');
|
|
784
|
+
assert.match(L6below.reason, /26999/, 'reason names the count');
|
|
785
|
+
assert.match(L6below.reason, /27000/, 'reason names the floor');
|
|
786
|
+
|
|
787
|
+
const aboveResult = await mod.checkBrainSmoke(Object.assign({}, commonMocks, ALL_PASS_SEAMS, {
|
|
788
|
+
mockStats: async () => ({ nodes: 27951 }),
|
|
789
|
+
}));
|
|
790
|
+
const L6above = aboveResult.layers[6];
|
|
791
|
+
assert.equal(L6above.ok, true, '27951 (the 2026-09-11 measured count) must pass the 27000 floor');
|
|
792
|
+
|
|
793
|
+
ok(label);
|
|
794
|
+
} catch (e) { fail(label, e); }
|
|
795
|
+
})();
|
|
796
|
+
|
|
438
797
|
// ---------------------------------------------------------------------------
|
|
439
798
|
// Summary -- IIFEs above are async; collect results after a microtask drain.
|
|
440
799
|
// ---------------------------------------------------------------------------
|