fix(gbrain-detect): let --doctor's report drain before exit

process.exit() cut a large verdict off mid-pipe, so Step 5's jq read
truncated JSON and stopped on a healthy brain. Set exitCode instead.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-11-01 14:39:51 +00:00
1 parent 1dc99d8925
commit 18a84c3374
2 files changed
+21 -9

No files matched your search

+10 -9
View File
@@ -351,14 +351,6 @@ function main(): void {
// callers — setup, bin/dev-setup, and `gstack-config gbrain-refresh` — can
// decide whether to render the gbrain :user variant without duplicating the
// JSON grep. Prints nothing on stdout.
// --doctor: the full brain-health gate /setup-gbrain Step 5 runs. Prints the
// DoctorVerdict as JSON and exits 0 iff brain_ok.
if (process.argv.includes("--doctor")) {
const verdict = runDoctor([], 300_000);
process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
process.exit(verdict.brain_ok ? 0 : 1);
}
if (process.argv.includes("--is-ok")) {
const noCache = process.env.GSTACK_DETECT_NO_CACHE === "1";
const status = localEngineStatus({ noCache });
@@ -370,4 +362,13 @@ if (process.argv.includes("--is-ok")) {
);
}
main();
// --doctor: the full brain-health gate /setup-gbrain Step 5 runs. Prints the
// DoctorVerdict as JSON and exits 0 iff brain_ok. exitCode, not process.exit:
// exit() cuts off a large report still draining into a pipe.
if (process.argv.includes("--doctor")) {
const verdict = runDoctor([], 300_000);
process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
process.exitCode = verdict.brain_ok ? 0 : 1;
} else {
main();
}
+11
View File
@@ -141,6 +141,17 @@ describe('gstack-gbrain-detect --doctor', () => {
expect(JSON.parse(r.stdout)).toMatchObject({ brain_ok: false, brain_failures: ['pgvector'] });
});
test('prints a large report whole through a pipe', () => {
const big = { status: 'healthy', checks: Array.from({ length: 3000 }, (_, i) => ({ ...check(`c${i}`, 'brain'), message: 'x'.repeat(60) })) };
const env = { ...caseEnv('all checks pass'), FAKE_DOCTOR_DIR: path.join(tmp, 'big') };
fs.mkdirSync(env.FAKE_DOCTOR_DIR, { recursive: true });
fs.writeFileSync(path.join(env.FAKE_DOCTOR_DIR, 'scoped.json'), JSON.stringify(big));
for (let i = 0; i < 3; i++) {
const r = spawnSync('bash', ['-c', `"${DETECT}" --doctor | cat`], { env, encoding: 'utf-8', timeout: 30_000 });
expect(JSON.parse(r.stdout).report.checks).toHaveLength(3000);
}
});
test('exits 1 with the cause when doctor prints no JSON', () => {
const r = spawnSync(DETECT, ['--doctor'], { env: caseEnv('doctor prints no JSON'), encoding: 'utf-8', timeout: 30_000 });
expect(r.status).toBe(1);