Skip to content

Commit 214f67c

Browse files
baozhoutaoclaude
andauthored
fix(cli): os doctor tells a broken cloud-connection install from an absent one (#5644) (#5658)
* fix(cli): `os doctor` tells a broken cloud-connection install from an absent one (#5644) `readInstalledPackageEntries()` reached the installed-package ledger through a dynamic `import('@objectstack/cloud-connection')` whose `catch` meant "the optional package is not installed". That covered two states with opposite remedies: a specifier that does not resolve (genuinely absent — silence is correct and stays), and a package that IS installed and will not load (unbuilt or pruned `dist/`, interrupted install, an artefact that throws while it evaluates). The second was answered with the first one's silence, so the ADR-0120 D5e advisory saw "no installed packages" and printed `✓ Unique scope` over a ledger nobody read — the false PASS #5412 removed at the `readdir` boundary and #5413 at the entry boundary, one boundary up. The two are separated by resolution, not by the `import()` having thrown: `isModuleNotFoundError()` first (an error that is not module-not-found came from the package itself), then `import.meta.resolve()`, which answers "is the package there" without stating its entry file. New `utils/optional-package.ts` owns the classification and the measurements behind it; doctor renders the present-but-broken state as a `Unique scope` warning row through the same renderer its two siblings use, and withholds the success line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh * docs(cli): state what loadOptionalPackage's specifier accepts (#5644) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5b60b36 commit 214f67c

5 files changed

Lines changed: 725 additions & 40 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
"@objectstack/cli": patch
3+
---
4+
5+
fix(cli): `os doctor` no longer treats a broken `@objectstack/cloud-connection` install as "not installed" (#5644)
6+
7+
`readInstalledPackageEntries()` reached the installed-package ledger through a
8+
dynamic `import('@objectstack/cloud-connection')` whose `catch` meant "the
9+
optional package is not installed". That is right for one of the two things it
10+
caught:
11+
12+
- **The specifier does not resolve** — the optional package really is not
13+
there. Silence is correct and unchanged: `os doctor` must run to completion in
14+
a checkout that never had it.
15+
- **The package is installed and will not load** — a pruned or unbuilt `dist/`,
16+
an interrupted install, an artefact that throws while it evaluates, a
17+
transitive dependency missing under it. It threw too, so it was answered with
18+
the same silence.
19+
20+
The ADR-0120 D5e unique-scope advisory then saw "no installed packages", found
21+
nothing to report, and the run printed:
22+
23+
```
24+
✓ Unique scope No unconfirmed installation-wide uniques for this 'isolated' environment
25+
```
26+
27+
Measured: with the package present-but-unloadable and a ledger declaring an
28+
installation-wide `unique`, that line was printed and the finding appeared
29+
nowhere, `--verbose` included. It is the same false PASS #5412 removed at the
30+
`readdir` boundary and #5413 at the entry boundary, one boundary further up —
31+
and `os serve`, loading the same package in the same directory, has always named
32+
the failure out loud.
33+
34+
The two states are now separated by **resolution**, not by the `import()` having
35+
thrown (`isModuleNotFoundError()` first — an error that is not a module-not-found
36+
error came from the package itself, so it is present by definition; then
37+
`import.meta.resolve()`, which answers "is the package there" without stating its
38+
entry file, unlike `createRequire().resolve()`). Only the genuinely-absent half
39+
is silent. The other prints an ordinary `HealthCheckResult` through the same
40+
renderer every other check uses:
41+
42+
```
43+
⚠ Unique scope Could not load the installed-package ledger reader (installed packages
44+
NOT checked for installation-wide uniques) — Cannot find module …
45+
```
46+
47+
**Warning, not error**, and the exit code is unchanged, matching its two
48+
siblings: the environment still runs; what broke is doctor's ability to see part
49+
of it. The cause is quoted from the thrower, and `--verbose` expands it together
50+
with the remedy — reinstall, or build the package in a monorepo checkout.
51+
52+
The row is **not** conditional on `.objectstack/installed-packages/` existing.
53+
Doctor cannot honestly say a ledger is absent when the constant naming the
54+
ledger's location is an export of the package that would not load.
55+
56+
One consequence worth stating: in a monorepo checkout where
57+
`packages/cloud-connection` has not been built, `os doctor` under the `isolated`
58+
posture now prints this warning instead of a clean bill. That state is exactly
59+
what sent #5612 chasing a report face that had never regressed.

0 commit comments

Comments
 (0)