Skip to content

Commit 451bf61

Browse files
test(cli): load the os doctor suites' oclif Config without the command scan (#23181 slice 8) (#25633)
Part of #23181 (slice 8). The card is a series and stays open. Clause-②: no Metadata-protocol: none ## Rows this PR addresses Eight `@objectstack/cli` unit-tier rows from the card's table, the `os doctor` in-process suites. They share one cause, which this PR removes: | file (unit tier) | card CI reading | local before (3 runs) | local after (3 runs) | after / before (medians) | CI reading × ratio | status | |:--|--:|--:|--:|--:|--:|:--| | `src/commands/doctor-ledger-read-failure.test.ts` | 17.0 s | 34.35 / 28.07 / 26.37 | 16.50 / 13.85 / 13.03 | 0.49 | 8.4 s | reduced, projected under 10 s, not proven | | `src/commands/doctor-ledger-posture-independence.test.ts` | 16.6 s | 24.46 / 29.89 / 27.00 | 17.37 / 15.12 / 14.69 | 0.56 | 9.3 s | reduced, projected under 10 s, not proven | | `src/commands/doctor-unexamined-spec-tree.test.ts` | 14.3 s | 18.02 / 18.65 / 19.55 | 10.41 / 11.20 / 11.12 | 0.60 | 8.5 s | reduced, projected under 10 s, not proven | | `src/commands/doctor-node-env-default.test.ts` | 14.0 s | 24.42 / 18.29 / 18.08 | 13.00 / 13.86 / 14.47 | 0.76 | 10.6 s | reduced, **not closed** | | `src/commands/doctor-deprecation-hint-commands.test.ts` | 11.6 s | 13.70 / 17.26 / 14.19 | 7.03 / 6.64 / 6.91 | 0.49 | 5.6 s | done | | `src/commands/doctor-config-load-cause.test.ts` | 11.6 s | 13.58 / 12.94 / 14.16 | 6.41 / 6.50 / 5.77 | 0.47 | 5.5 s | done | | `src/commands/doctor-ledger-dir-authority.test.ts` | 10.3 s | 18.78 / 19.57 / 14.62 | 7.28 / 7.08 / 6.45 | 0.38 | 3.9 s | done | | `src/commands/doctor-config-env-overlay.test.ts` | 10.2 s | 12.23 / 11.89 / 12.32 | 5.37 / 5.01 / 4.71 | 0.41 | 4.2 s | done | The pin is the card's: the next landed refresh's per-file list no longer names a "done" row. The "projected" rows rest on a ratio applied to the card's old CI reading, so CI decides them, not this table. ## The cause and the fix Each suite drives the real command with `Doctor.run(argv, { root: CLI_ROOT })`. Given a root, oclif loads a fresh `Config`. `@objectstack/cli` ships no `oclif.manifest.json`, so that load builds the command manifest by importing every compiled command under `dist/commands` (73 commands). Measured in-process: **6.6 s** for that `Config.load`, paid by each file's first test. `doctor.ts` never reads `this.config`, so the command list is pure overhead for these suites. `packages/cli/src/utils/__tests__/doctor-config.ts` (new, 36 lines) loads one `Config` per file from the package's own `package.json` with only `oclif.commands` dropped. Hooks still load (the `preparse` separator strip is present: `hooks` = `["preparse"]`), and the load takes 36 ms. The eight files pass `await doctorConfig()` instead of `{ root: CLI_ROOT }` (12 call sites) and drop the now-unused `CLI_ROOT` / `HERE` / `fileURLToPath` lines. - It lives under `src/**/__tests__/`, the path `tsconfig.build.json` already excludes, next to `src/utils/__tests__/server-body.ts`. It is not under `test/helpers/`, because `tsconfig.json`'s `rootDir: src` refuses a `src/` test importing from `test/` (TS6059, measured). It is not under `src/commands/`, because `environments.test.ts` walks every `.ts` there as a command source and would have modelled a phantom `__tests__ doctor-config` command id (measured: the unit tier went from 4812 to 4813 tests). - No test was deleted, renamed or re-tiered, and no timeout changed. All 139 tests pass in every run, with test full names identical before and after, file by file. ## Why these rows (A2: win per changed line) One 36-line helper plus 12 one-line call-site swaps (+57 / −48) removes 6.6 s from each of eight rows and brings four under the line. Rows looked at and not taken: - The `@objectstack/cli` integration files at 90 to 301 s (`data-commands.absent-database`, `stack-conversion-record-door`, `package-install-local-*`, ...). Each spawns the real CLI per fixture. Their fix is either a per-file restructuring or the `test-budget:` header method (slice 6), and that method needs a CI reading this container could not obtain (see A1). - `test/scaffold-emission-typechecks.test.ts` (unit, 33.3 s): a type-graph compile, a `test-budget` class candidate, so the same CI-reading constraint applies. - `migrate-meta-*` and `explain-rule-id` unit rows (10.2 to 18.1 s): not measured in this slice. - The other packages' rows: slices 1 to 5 and 7 took `runtime`, `client`, `verify`, `rest` and `create-objectstack`. ## A1: the work list PR #25409 (`97be89bb3b`), the newest landed refresh, carries **no per-file list**: its `--diff` refused (exit 1) on `packages/cli/src/commands/migrate/audit-mail-bodies.archive.integration.test.ts:2` (`test-budget: 85`, off the 10 s grid). `origin/main` at `e649c2d9` already reads `90` there, so the next refresh can list files. Reproducing the diff locally was not possible: the `test-core-timings-N-of-6` captures are retained one day, so only 2 of the window's 8 runs still had them, and this container's proxy refuses the artifact blob host (HTTP 403). So the rows above come from the card's table, each re-measured on `e649c2d9` (every one still read over 10 s locally before the change). ## What the remaining time is (for the next slice) Measured per warm `Doctor.run` (about 0.6 to 0.9 s): the three real tool probes `pnpm -v` (0.4 to 0.9 s under vitest's PATH), `tsc -v` (0.1 to 0.4 s) and `git --version` (about 15 ms). On top of that, each file's first run pays the lazy `@objectstack/cloud-connection` import (4.3 s). The files still near or over the line are the ones with 13 to 18 runs. Stubbing the probes is a separate decision, because the suites then stop seeing the real probe rows. It is not taken here. ## Proof - Measurement, same way before and after: `bash scripts/pm/os-verify-lock.sh -c 'cd packages/cli && pnpm exec vitest run --project unit --maxWorkers=2 --reporter=json --outputFile=FILE' + the 8 files`. Per-file = the json reporter's `endTime − startTime` (the per-file module line CI reports; it sums to vitest's `tests` total). "Before" restored the 8 files from `e649c2d9` (tree only), then restored from `HEAD` (`git diff HEAD` empty afterwards). Shared box: absolute seconds are box readings, so ratios are the comparable figure. - Shared fixture check: the helper is new and only these eight files import it. `doctor.ts` and every other `Doctor.run` suite (`doctor-env-provenance`, `doctor-tenancy-posture-report`) are untouched. - `pnpm --filter @objectstack/cli typecheck` (tsc + `check:test-typecheck` OK): exit 0 at `f0e74dd1d`. The `--noEmit` program includes the helper; the build program (`tsconfig.build.json --listFilesOnly`, 1318 files, `doctor.ts` among them) includes nothing under `__tests__`. - cli unit tier at `f0e74dd1d`: 326/327 files, 4811/4812 tests. The one failure is `src/utils/boot-preparation-parity.test.ts`, a 5 s vitest timeout under load (9.15 s) in a file this diff does not touch. Re-run alone: 37/37, exit 0. The two earlier full runs passed it (327/327). The integration tier is declared to CI: the diff touches no integration file and no spawn entry. - `node scripts/pm/dispatch-gates.mjs --commands` at `f0e74dd1d`: 58 commands, all exit 0. `--ran`: "58 derived, 58 run, 0 NOT-MEASURED, 0 UNRUN". - `eslint --no-inline-config packages/cli`: exit 0. - `pnpm lint` (`eslint . --no-inline-config`, the whole repo): exit 0 at `f0e74dd1d`. ## Changeset `skip-changeset`: nothing published changes. Every changed file is a `*.test.ts` or sits under `src/**/__tests__/`, which `tsconfig.build.json` excludes, so no changed file reaches `dist/` (`files: ["dist", ...]`). ## Acceptance notes - `@objectstack/cli` ships no `oclif.manifest.json`, so any `Config.load` from the package root imports every command. Whether the published `os` binary pays the same cost per invocation was NOT MEASURED here. This is an observation only. - `src/utils/boot-preparation-parity.test.ts` "every SERVE_ONLY entry is still used by serve.ts" ran 9.15 s against vitest's 5 s default in one contended full-tier run. Observed once. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013fXj9gbwakFbBp5U9x4EjF --- _Generated by [Claude Code](https://claude.ai/code/session_013fXj9gbwakFbBp5U9x4EjF)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b694e56 commit 451bf61

9 files changed

Lines changed: 57 additions & 48 deletions

‎packages/cli/src/commands/doctor-config-env-overlay.test.ts‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,15 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
5454
import fs from 'node:fs';
5555
import os from 'node:os';
5656
import path from 'node:path';
57-
import { fileURLToPath } from 'node:url';
5857

58+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
5959
import Doctor, {
6060
readDotenvFiles,
6161
withDotenvOverlay,
6262
withDotenvOverlayAsync,
6363
environmentSourcesCheck,
6464
} from './doctor.js';
6565

66-
const HERE = path.dirname(fileURLToPath(import.meta.url));
67-
/** `packages/cli` — the oclif root the real command is loaded against below. */
68-
const CLI_ROOT = path.resolve(HERE, '..', '..');
69-
7066
/**
7167
* The escape is written as `\x1b`, never as the byte itself: one raw control
7268
* character makes `grep` treat the whole file as binary, and a test file no
@@ -257,7 +253,7 @@ describe('os doctor, end to end, against a config that reads .env at top level',
257253
}) as never);
258254

259255
try {
260-
await Doctor.run([], { root: CLI_ROOT });
256+
await Doctor.run([], await doctorConfig());
261257
} catch (err) {
262258
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
263259
} finally {

‎packages/cli/src/commands/doctor-config-load-cause.test.ts‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,10 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
5252
import fs from 'node:fs';
5353
import os from 'node:os';
5454
import path from 'node:path';
55-
import { fileURLToPath } from 'node:url';
5655

56+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
5757
import Doctor, { configLoadFailureCheck } from './doctor.js';
5858

59-
const HERE = path.dirname(fileURLToPath(import.meta.url));
60-
/** `packages/cli` — the oclif root the real command is loaded against below. */
61-
const CLI_ROOT = path.resolve(HERE, '..', '..');
62-
6359
/**
6460
* The escape is written as `\x1b`, never as the byte itself: one raw control
6561
* character makes `grep` treat the whole file as binary, and a test file no
@@ -199,7 +195,7 @@ describe('os doctor, end to end, against a config that cannot be loaded', () =>
199195
}) as never);
200196

201197
try {
202-
await Doctor.run(argv, { root: CLI_ROOT });
198+
await Doctor.run(argv, await doctorConfig());
203199
} catch (err) {
204200
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
205201
} finally {

‎packages/cli/src/commands/doctor-deprecation-hint-commands.test.ts‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,12 @@ import os from 'node:os';
6161
import path from 'node:path';
6262
import { fileURLToPath } from 'node:url';
6363

64+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
6465
import Doctor from './doctor.js';
6566

6667
const HERE = path.dirname(fileURLToPath(import.meta.url));
6768
/** `packages/cli/src/commands` — where oclif's pattern strategy finds commands. */
6869
const COMMANDS_DIR = HERE;
69-
/** `packages/cli` — the oclif root the real command is loaded against below. */
70-
const CLI_ROOT = path.resolve(HERE, '..', '..');
7170
const DOCTOR_SRC = path.join(COMMANDS_DIR, 'doctor.ts');
7271

7372
/**
@@ -251,7 +250,7 @@ describe('os doctor --scan-deprecations, end to end', () => {
251250
}) as never);
252251

253252
try {
254-
await Doctor.run(argv, { root: CLI_ROOT });
253+
await Doctor.run(argv, await doctorConfig());
255254
} catch (err) {
256255
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
257256
} finally {

‎packages/cli/src/commands/doctor-ledger-dir-authority.test.ts‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ import { describe, it, expect, beforeAll, afterEach, vi } from 'vitest';
4848
import fs from 'node:fs';
4949
import os from 'node:os';
5050
import path from 'node:path';
51-
import { fileURLToPath } from 'node:url';
5251

52+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
5353
import Doctor, {
5454
installedPackageLedgerDirAuthorityMissingCheck,
5555
installedPackageLedgerSkippedEntriesCheck,
@@ -62,10 +62,6 @@ import Doctor, {
6262
// where the same shape cost 30 ejected merge-queue builds in one night.
6363
import '@objectstack/cloud-connection';
6464

65-
const HERE = path.dirname(fileURLToPath(import.meta.url));
66-
/** `packages/cli` — the oclif root the real command is loaded against below. */
67-
const CLI_ROOT = path.resolve(HERE, '..', '..');
68-
6965
/**
7066
* The escape is written as `\x1b`, never as the byte itself: one raw control
7167
* character makes `grep` treat the whole file as binary, and a test file no
@@ -258,7 +254,7 @@ describe('os doctor, end to end, against a reader that declares no ledger direct
258254
}) as never);
259255

260256
try {
261-
await FreshDoctor.run(argv, { root: CLI_ROOT });
257+
await FreshDoctor.run(argv, await doctorConfig());
262258
} catch (err) {
263259
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
264260
} finally {
@@ -410,7 +406,7 @@ describe('os doctor, end to end, skipped-entries fix quotes the resolved directo
410406
}) as never);
411407

412408
try {
413-
await Doctor.run(['--verbose'], { root: CLI_ROOT });
409+
await Doctor.run(['--verbose'], await doctorConfig());
414410
} catch (err) {
415411
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
416412
} finally {

‎packages/cli/src/commands/doctor-ledger-posture-independence.test.ts‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from 'vite
6565
import fs from 'node:fs';
6666
import os from 'node:os';
6767
import path from 'node:path';
68-
import { fileURLToPath } from 'node:url';
6968

69+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
7070
import Doctor from './doctor.js';
7171

7272
// [#10126] Pay the first transform of these dist-resolved workspace deps at MODULE
@@ -76,10 +76,6 @@ import Doctor from './doctor.js';
7676
// where the same shape cost 30 ejected merge-queue builds in one night.
7777
import '@objectstack/cloud-connection';
7878

79-
const HERE = path.dirname(fileURLToPath(import.meta.url));
80-
/** `packages/cli` — the oclif root the real command is loaded against below. */
81-
const CLI_ROOT = path.resolve(HERE, '..', '..');
82-
8379
/**
8480
* The escape is written as `\x1b`, never as the byte itself: one raw control
8581
* character makes `grep` treat the whole file as binary, and a test file no
@@ -224,7 +220,7 @@ describe('os doctor reports ledger readability under every posture (#5429)', ()
224220
}) as never);
225221

226222
try {
227-
await Doctor.run(argv, { root: CLI_ROOT });
223+
await Doctor.run(argv, await doctorConfig());
228224
} catch (err) {
229225
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
230226
} finally {

‎packages/cli/src/commands/doctor-ledger-read-failure.test.ts‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from 'vite
8686
import fs from 'node:fs';
8787
import os from 'node:os';
8888
import path from 'node:path';
89-
import { fileURLToPath } from 'node:url';
9089

90+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
9191
import Doctor, {
9292
installedPackageLedgerFailureCheck,
9393
installedPackageLedgerReaderFailureCheck,
@@ -100,10 +100,6 @@ import Doctor, {
100100
// where the same shape cost 30 ejected merge-queue builds in one night.
101101
import '@objectstack/cloud-connection';
102102

103-
const HERE = path.dirname(fileURLToPath(import.meta.url));
104-
/** `packages/cli` — the oclif root the real command is loaded against below. */
105-
const CLI_ROOT = path.resolve(HERE, '..', '..');
106-
107103
/**
108104
* The escape is written as `\x1b`, never as the byte itself: one raw control
109105
* character makes `grep` treat the whole file as binary, and a test file no
@@ -439,7 +435,7 @@ describe('os doctor, end to end, against an unreadable installed-package ledger'
439435
}) as never);
440436

441437
try {
442-
await Doctor.run(argv, { root: CLI_ROOT });
438+
await Doctor.run(argv, await doctorConfig());
443439
} catch (err) {
444440
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
445441
} finally {
@@ -765,7 +761,7 @@ describe('the optional package INSTALLED BUT UNLOADABLE is reported (#5644)', ()
765761
}) as never);
766762

767763
try {
768-
await FreshDoctor.run(['--verbose'], { root: CLI_ROOT });
764+
await FreshDoctor.run(['--verbose'], await doctorConfig());
769765
} catch (err) {
770766
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
771767
} finally {
@@ -837,7 +833,7 @@ describe('the optional package INSTALLED BUT UNLOADABLE is reported (#5644)', ()
837833

838834
let exitCode: number | undefined;
839835
try {
840-
await FreshDoctor.run(['--verbose'], { root: CLI_ROOT });
836+
await FreshDoctor.run(['--verbose'], await doctorConfig());
841837
} catch (err) {
842838
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
843839
exitCode = Number(err.message.split(':')[1]);
@@ -931,7 +927,7 @@ describe('the optional package being genuinely ABSENT stays completely silent (#
931927
}) as never);
932928

933929
try {
934-
await FreshDoctor.run(['--verbose'], { root: CLI_ROOT });
930+
await FreshDoctor.run(['--verbose'], await doctorConfig());
935931
} catch (err) {
936932
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
937933
} finally {

‎packages/cli/src/commands/doctor-node-env-default.test.ts‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6363
import fs from 'node:fs';
6464
import os from 'node:os';
6565
import path from 'node:path';
66-
import { fileURLToPath } from 'node:url';
6766

67+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
6868
import Doctor, {
6969
nodeEnvCheck,
7070
nodeEnvSourcePosture,
@@ -73,9 +73,6 @@ import Doctor, {
7373
readDotenvFiles,
7474
} from './doctor.js';
7575

76-
/** `packages/cli` — the oclif root the real command is loaded against below. */
77-
const CLI_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
78-
7976
/**
8077
* `chalk` may or may not emit SGR codes depending on TTY detection.
8178
*
@@ -337,7 +334,7 @@ describe('[#5673] os doctor, end to end — the row reaches the report', () => {
337334
}) as never);
338335

339336
try {
340-
await Doctor.run(argv, { root: CLI_ROOT });
337+
await Doctor.run(argv, await doctorConfig());
341338
} catch (err) {
342339
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
343340
} finally {

‎packages/cli/src/commands/doctor-unexamined-spec-tree.test.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,10 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6666
import fs from 'node:fs';
6767
import os from 'node:os';
6868
import path from 'node:path';
69-
import { fileURLToPath } from 'node:url';
7069

70+
import { doctorConfig } from '../utils/__tests__/doctor-config.js';
7171
import Doctor, { monorepoTreeSkipNotice } from './doctor.js';
7272

73-
/** `packages/cli` — the oclif root the real command is loaded against below. */
74-
const CLI_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
75-
7673
/**
7774
* `chalk` may or may not emit SGR codes depending on TTY detection.
7875
*
@@ -175,7 +172,7 @@ describe('os doctor, end to end, in a user-app cwd with no packages/spec', () =>
175172
}) as never);
176173

177174
try {
178-
await Doctor.run(argv, { root: CLI_ROOT });
175+
await Doctor.run(argv, await doctorConfig());
179176
} catch (err) {
180177
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
181178
} finally {
@@ -289,7 +286,7 @@ describe('os doctor, end to end, in a monorepo-shaped cwd — the no-regression
289286
}) as never);
290287

291288
try {
292-
await Doctor.run(argv, { root: CLI_ROOT });
289+
await Doctor.run(argv, await doctorConfig());
293290
} catch (err) {
294291
if (!(err instanceof Error) || !err.message.startsWith('__PROCESS_EXIT__')) throw err;
295292
} finally {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* The oclif `Config` the in-process `os doctor` suites hand `Doctor.run()`.
5+
*
6+
* `Doctor.run(argv, { root })` makes oclif load a Config from the package root,
7+
* and this package ships no `oclif.manifest.json`, so that load builds the
8+
* command manifest by importing every compiled command under `dist/commands`:
9+
* 6.6 s of each file's first test, measured locally (#23181). `os doctor`
10+
* reads none of it — `doctor.ts` never touches `this.config` — so this Config
11+
* is the package's own `package.json` with only `oclif.commands` dropped. The
12+
* hooks (the `preparse` separator strip) and everything else still load from
13+
* the same manifest, and it loads in tens of milliseconds.
14+
*
15+
* ⛔ Not for a suite that asks the Config for a command (`findCommand`,
16+
* `config.commands`, `runCommand`): this one has none.
17+
*/
18+
19+
import { readFileSync } from 'node:fs';
20+
import { resolve } from 'node:path';
21+
import { fileURLToPath } from 'node:url';
22+
import { Config } from '@oclif/core';
23+
24+
/** `packages/cli` — the root a `Doctor.run()` loads its Config from. */
25+
const CLI_ROOT = resolve(fileURLToPath(import.meta.url), '../../../..');
26+
27+
let loaded: Promise<Config> | undefined;
28+
29+
/** One Config per test file, loaded on first use. */
30+
export function doctorConfig(): Promise<Config> {
31+
loaded ??= (async () => {
32+
const pjson = JSON.parse(readFileSync(resolve(CLI_ROOT, 'package.json'), 'utf8'));
33+
return Config.load({ root: CLI_ROOT, pjson: { ...pjson, oclif: { ...pjson.oclif, commands: undefined } } });
34+
})();
35+
return loaded;
36+
}

0 commit comments

Comments
 (0)