@geonosis/doctor 2.5.0 → 2.5.1
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/CHANGELOG.md +13 -0
- package/bin/geonosis-doctor.mjs +11 -3
- package/dist/{chunk-GXW7SYO2.js → chunk-EZB5BG4L.js} +132 -147
- package/dist/doctor-cli.js +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @geonosis/doctor
|
|
2
2
|
|
|
3
|
+
## 2.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7f24da6: The doctor's resolution is bounded to the root it was handed (#373, #386): `resolveFrom` used to
|
|
8
|
+
walk `node_modules` upward with no stop, so a tree nested under a directory that carries this kit's
|
|
9
|
+
own `node_modules` (the smoke's run copy, a monorepo of repos, a CI runner's shared cache dir) read
|
|
10
|
+
an ancestor's copy of `@geonosis/<x>` as installed here, at whatever version the ancestor has. The
|
|
11
|
+
walk now stops at the root; a hit above it is reported by the `loaded` and `group` checks as "not
|
|
12
|
+
installed here — found above the root at `<path>`, which this tree cannot see when deployed" — a
|
|
13
|
+
named FAIL rather than a silently wrong version.
|
|
14
|
+
- @geonosis/lint-parity@2.5.1
|
|
15
|
+
|
|
3
16
|
## 2.5.0
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/bin/geonosis-doctor.mjs
CHANGED
|
@@ -9,11 +9,19 @@ import { dirname, join } from 'node:path'
|
|
|
9
9
|
import { fileURLToPath } from 'node:url'
|
|
10
10
|
|
|
11
11
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
12
|
-
|
|
12
|
+
// tsup never reads a test file, so one counting as source made every bin refuse a build that had
|
|
13
|
+
// not gone stale (#399).
|
|
14
|
+
const NOT_SOURCE = (name) =>
|
|
15
|
+
name.endsWith('.test.ts') ||
|
|
16
|
+
name.endsWith('.test.tsx') ||
|
|
17
|
+
name === '__tests__' ||
|
|
18
|
+
name === '__fixtures__'
|
|
19
|
+
const newest = (dir, skip) =>
|
|
13
20
|
existsSync(dir)
|
|
14
21
|
? readdirSync(dir, { withFileTypes: true }).reduce((most, entry) => {
|
|
22
|
+
if (skip !== undefined && skip(entry.name)) return most
|
|
15
23
|
const at = join(dir, entry.name)
|
|
16
|
-
return Math.max(most, entry.isDirectory() ? newest(at) : statSync(at).mtimeMs)
|
|
24
|
+
return Math.max(most, entry.isDirectory() ? newest(at, skip) : statSync(at).mtimeMs)
|
|
17
25
|
}, 0)
|
|
18
26
|
: 0
|
|
19
27
|
const src = join(here, '..', 'src')
|
|
@@ -30,7 +38,7 @@ if (existsSync(src)) {
|
|
|
30
38
|
)
|
|
31
39
|
process.exit(2)
|
|
32
40
|
}
|
|
33
|
-
if (newest(src) > built) {
|
|
41
|
+
if (newest(src, NOT_SOURCE) > built) {
|
|
34
42
|
process.stderr.write(
|
|
35
43
|
'geonosis-doctor: dist is older than src — run pnpm build before trusting this bin.\n',
|
|
36
44
|
)
|
|
@@ -4,7 +4,13 @@ import { join, relative as relativeTo, sep } from "path";
|
|
|
4
4
|
var CONFIG_FILE = ".oxlintrc.json";
|
|
5
5
|
var MANIFEST_FILE = "package.json";
|
|
6
6
|
var RATCHET_FILE = "geonosis.ratchet.json";
|
|
7
|
-
var NEVER_WALKED = /* @__PURE__ */ new Set([
|
|
7
|
+
var NEVER_WALKED = /* @__PURE__ */ new Set([
|
|
8
|
+
"build",
|
|
9
|
+
"coverage",
|
|
10
|
+
"dist",
|
|
11
|
+
"node_modules",
|
|
12
|
+
"storybook-static"
|
|
13
|
+
]);
|
|
8
14
|
var skipped = (name) => name.startsWith(".") || NEVER_WALKED.has(name);
|
|
9
15
|
var relativePath = (root, path) => relativeTo(root, path).split(sep).join("/");
|
|
10
16
|
var walk = (dir, onFile) => {
|
|
@@ -73,10 +79,11 @@ var discoverWorkspaces = (root) => {
|
|
|
73
79
|
return found.toSorted((a, b) => a.relative.localeCompare(b.relative));
|
|
74
80
|
};
|
|
75
81
|
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
|
|
76
|
-
var testFilesUnder = (dir) =>
|
|
82
|
+
var testFilesUnder = (dir) => filesUnder(dir, (name) => TEST_FILE.test(name));
|
|
83
|
+
var filesUnder = (dir, match) => {
|
|
77
84
|
const found = [];
|
|
78
85
|
walk(dir, (path, name) => {
|
|
79
|
-
if (
|
|
86
|
+
if (match(name)) found.push(path);
|
|
80
87
|
});
|
|
81
88
|
return found;
|
|
82
89
|
};
|
|
@@ -94,6 +101,33 @@ var readRatchet = (root) => {
|
|
|
94
101
|
};
|
|
95
102
|
};
|
|
96
103
|
|
|
104
|
+
// src/types.ts
|
|
105
|
+
var CHECKS = [
|
|
106
|
+
"loaded",
|
|
107
|
+
"group",
|
|
108
|
+
"exercised",
|
|
109
|
+
"baseline",
|
|
110
|
+
"runner",
|
|
111
|
+
"envelope",
|
|
112
|
+
"drift",
|
|
113
|
+
"observability",
|
|
114
|
+
"deployed",
|
|
115
|
+
"rails",
|
|
116
|
+
"exams"
|
|
117
|
+
];
|
|
118
|
+
var findingMaker = (check) => (subject, verdict, message) => ({
|
|
119
|
+
check,
|
|
120
|
+
message,
|
|
121
|
+
subject,
|
|
122
|
+
verdict
|
|
123
|
+
});
|
|
124
|
+
var DoctorError = class extends Error {
|
|
125
|
+
constructor(message) {
|
|
126
|
+
super(message);
|
|
127
|
+
this.name = "DoctorError";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
97
131
|
// src/baseline.ts
|
|
98
132
|
import { spawnSync } from "child_process";
|
|
99
133
|
var DEFAULT_REF = "origin/main";
|
|
@@ -117,12 +151,7 @@ var numbersAt = (root, ref, path) => {
|
|
|
117
151
|
}
|
|
118
152
|
return numbers;
|
|
119
153
|
};
|
|
120
|
-
var finding = (
|
|
121
|
-
check: "baseline",
|
|
122
|
-
message,
|
|
123
|
-
subject,
|
|
124
|
-
verdict
|
|
125
|
-
});
|
|
154
|
+
var finding = findingMaker("baseline");
|
|
126
155
|
var checkBaseline = ({ ref, root }) => {
|
|
127
156
|
const ratchet = readRatchet(root);
|
|
128
157
|
if (ratchet === void 0) {
|
|
@@ -172,12 +201,8 @@ var DEPLOYED_FILE = ".geonosis/deployed.json";
|
|
|
172
201
|
var NOT_WRITTEN = "no .geonosis/deployed.json \u2014 it is written by the pipeline after promote, and its absence is not a pass";
|
|
173
202
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
174
203
|
var listOf = (found) => Array.isArray(found) ? found.filter((one) => typeof one === "string") : [];
|
|
175
|
-
var
|
|
176
|
-
|
|
177
|
-
message,
|
|
178
|
-
subject,
|
|
179
|
-
verdict
|
|
180
|
-
});
|
|
204
|
+
var make = findingMaker("deployed");
|
|
205
|
+
var finding2 = (verdict, subject, message) => make(subject, verdict, message);
|
|
181
206
|
var parseJsonc = (source) => {
|
|
182
207
|
let out = "";
|
|
183
208
|
for (let index = 0; index < source.length; index += 1) {
|
|
@@ -339,27 +364,6 @@ var repoCorpusOf = (root) => {
|
|
|
339
364
|
}
|
|
340
365
|
};
|
|
341
366
|
|
|
342
|
-
// src/types.ts
|
|
343
|
-
var CHECKS = [
|
|
344
|
-
"loaded",
|
|
345
|
-
"group",
|
|
346
|
-
"exercised",
|
|
347
|
-
"baseline",
|
|
348
|
-
"runner",
|
|
349
|
-
"envelope",
|
|
350
|
-
"drift",
|
|
351
|
-
"observability",
|
|
352
|
-
"deployed",
|
|
353
|
-
"rails",
|
|
354
|
-
"exams"
|
|
355
|
-
];
|
|
356
|
-
var DoctorError = class extends Error {
|
|
357
|
-
constructor(message) {
|
|
358
|
-
super(message);
|
|
359
|
-
this.name = "DoctorError";
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
|
|
363
367
|
// src/resolve.ts
|
|
364
368
|
import { existsSync as existsSync3, readFileSync as readFileSync4, realpathSync } from "fs";
|
|
365
369
|
import { createRequire } from "module";
|
|
@@ -369,22 +373,51 @@ var packageNameOf = (specifier) => {
|
|
|
369
373
|
const parts2 = specifier.split("/");
|
|
370
374
|
return specifier.startsWith("@") ? parts2.slice(0, 2).join("/") : parts2[0] ?? specifier;
|
|
371
375
|
};
|
|
372
|
-
var
|
|
376
|
+
var AboveRootError = class extends DoctorError {
|
|
377
|
+
foundAt;
|
|
378
|
+
constructor(message, foundAt) {
|
|
379
|
+
super(message);
|
|
380
|
+
this.name = "AboveRootError";
|
|
381
|
+
this.foundAt = foundAt;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
var aboveRootMessage = (specifier, foundAt) => `${specifier} is not installed here \u2014 found above the root at ${foundAt}, which this tree cannot see when deployed`;
|
|
385
|
+
var aboveRoot = (root, name) => {
|
|
386
|
+
let at = dirname(root);
|
|
387
|
+
for (; ; ) {
|
|
388
|
+
const dir = join4(at, "node_modules", name);
|
|
389
|
+
if (existsSync3(join4(dir, "package.json"))) return dir;
|
|
390
|
+
const parent = dirname(at);
|
|
391
|
+
if (parent === at) return void 0;
|
|
392
|
+
at = parent;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var resolveFrom = (dir, specifier, root) => {
|
|
373
396
|
if (specifier.startsWith(".") || specifier.startsWith("/")) {
|
|
374
397
|
return createRequire(join4(dir, "noop.js")).resolve(specifier);
|
|
375
398
|
}
|
|
376
399
|
const name = packageNameOf(specifier);
|
|
377
400
|
let at = dir;
|
|
401
|
+
let reachedRoot = false;
|
|
378
402
|
for (; ; ) {
|
|
379
403
|
if (existsSync3(join4(at, "node_modules", name, "package.json"))) {
|
|
380
404
|
return createRequire(join4(at, "noop.js")).resolve(specifier);
|
|
381
405
|
}
|
|
406
|
+
if (at === root) {
|
|
407
|
+
reachedRoot = true;
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
382
410
|
const parent = dirname(at);
|
|
383
411
|
if (parent === at) break;
|
|
384
412
|
at = parent;
|
|
385
413
|
}
|
|
414
|
+
if (reachedRoot) {
|
|
415
|
+
const foundAt = aboveRoot(root, name);
|
|
416
|
+
if (foundAt !== void 0)
|
|
417
|
+
throw new AboveRootError(aboveRootMessage(specifier, foundAt), foundAt);
|
|
418
|
+
}
|
|
386
419
|
throw new DoctorError(
|
|
387
|
-
`${specifier} does not resolve from ${dir} \u2014 no node_modules on the way up carries ${name}`
|
|
420
|
+
`${specifier} does not resolve from ${dir} \u2014 no node_modules on the way up to ${root} carries ${name}`
|
|
388
421
|
);
|
|
389
422
|
};
|
|
390
423
|
var packageDirOf = (entry, name) => {
|
|
@@ -460,7 +493,7 @@ var presumptionsOf = async (entry) => {
|
|
|
460
493
|
)
|
|
461
494
|
};
|
|
462
495
|
};
|
|
463
|
-
var corpusOfPlugin = (from, specifier) => join4(packageDirOf(resolveFrom(from, specifier), specifier), "corpus");
|
|
496
|
+
var corpusOfPlugin = (from, specifier, root) => join4(packageDirOf(resolveFrom(from, specifier, root), specifier), "corpus");
|
|
464
497
|
var real = (path) => {
|
|
465
498
|
try {
|
|
466
499
|
return realpathSync(path);
|
|
@@ -558,12 +591,12 @@ var declaredGroupsOf = (root) => {
|
|
|
558
591
|
});
|
|
559
592
|
};
|
|
560
593
|
var labelOf = (workspace) => workspace.relative === "" ? "root" : workspace.relative;
|
|
561
|
-
var versionOf = (dir, name) => {
|
|
594
|
+
var versionOf = (dir, name, root) => {
|
|
562
595
|
let entry;
|
|
563
596
|
try {
|
|
564
|
-
entry = resolveFrom(dir, name);
|
|
565
|
-
} catch {
|
|
566
|
-
return { kind: "absent" };
|
|
597
|
+
entry = resolveFrom(dir, name, root);
|
|
598
|
+
} catch (error) {
|
|
599
|
+
return error instanceof AboveRootError ? { foundAt: error.foundAt, kind: "aboveRoot" } : { kind: "absent" };
|
|
567
600
|
}
|
|
568
601
|
try {
|
|
569
602
|
const manifest = JSON.parse(
|
|
@@ -574,12 +607,7 @@ var versionOf = (dir, name) => {
|
|
|
574
607
|
return { kind: "unreadable", why: String(error.message).split("\n")[0] ?? "" };
|
|
575
608
|
}
|
|
576
609
|
};
|
|
577
|
-
var finding3 = (
|
|
578
|
-
check: "group",
|
|
579
|
-
message,
|
|
580
|
-
subject,
|
|
581
|
-
verdict
|
|
582
|
-
});
|
|
610
|
+
var finding3 = findingMaker("group");
|
|
583
611
|
var said = (versions) => [...versions.entries()].map(([version, from]) => `${version} (${from.join(", ")})`).join("; ");
|
|
584
612
|
var repoWide = (name, found) => {
|
|
585
613
|
const versions = /* @__PURE__ */ new Map();
|
|
@@ -601,10 +629,10 @@ var perWorkspace = (group, at, found) => {
|
|
|
601
629
|
);
|
|
602
630
|
};
|
|
603
631
|
var DOORS = ["@geonosis/cli", "geonosis"];
|
|
604
|
-
var manifestOf = (
|
|
632
|
+
var manifestOf = (root, name) => {
|
|
605
633
|
try {
|
|
606
634
|
return JSON.parse(
|
|
607
|
-
readFileSync6(join6(packageDirOf(resolveFrom(
|
|
635
|
+
readFileSync6(join6(packageDirOf(resolveFrom(root, name, root), name), "package.json"), "utf8")
|
|
608
636
|
);
|
|
609
637
|
} catch {
|
|
610
638
|
return void 0;
|
|
@@ -692,7 +720,7 @@ var checkGroup = ({
|
|
|
692
720
|
const at = labelOf(workspace);
|
|
693
721
|
const here = [];
|
|
694
722
|
for (const name of group.packages) {
|
|
695
|
-
const reading = versionOf(workspace.dir, name);
|
|
723
|
+
const reading = versionOf(workspace.dir, name, root);
|
|
696
724
|
if (reading.kind === "read") here.push({ at, name, version: reading.version });
|
|
697
725
|
if (reading.kind === "unreadable") {
|
|
698
726
|
findings.push(
|
|
@@ -703,6 +731,15 @@ var checkGroup = ({
|
|
|
703
731
|
)
|
|
704
732
|
);
|
|
705
733
|
}
|
|
734
|
+
if (reading.kind === "aboveRoot") {
|
|
735
|
+
findings.push(
|
|
736
|
+
finding3(
|
|
737
|
+
`${at} \u2192 ${name}`,
|
|
738
|
+
"FAIL",
|
|
739
|
+
`${name} is not installed here \u2014 found above the root at ${reading.foundAt}, which this tree cannot see when deployed`
|
|
740
|
+
)
|
|
741
|
+
);
|
|
742
|
+
}
|
|
706
743
|
}
|
|
707
744
|
const split2 = here.length > 0 ? perWorkspace(group, at, here) : void 0;
|
|
708
745
|
if (split2 !== void 0) findings.push(split2);
|
|
@@ -816,33 +853,7 @@ var GEONOSIS = "geonosis.json";
|
|
|
816
853
|
var LAW = "CLAUDE.md";
|
|
817
854
|
var CEILING = 200;
|
|
818
855
|
var SWITCHED_OFF = /^\s*if:\s*(?:\$\{\{\s*)?false\b/m;
|
|
819
|
-
var finding4 = (
|
|
820
|
-
check: "drift",
|
|
821
|
-
message,
|
|
822
|
-
subject,
|
|
823
|
-
verdict
|
|
824
|
-
});
|
|
825
|
-
var NEVER_WALKED2 = /* @__PURE__ */ new Set(["build", "coverage", "dist", "node_modules", "storybook-static"]);
|
|
826
|
-
var filesUnder = (dir, match) => {
|
|
827
|
-
const found = [];
|
|
828
|
-
const walk2 = (at) => {
|
|
829
|
-
let entries;
|
|
830
|
-
try {
|
|
831
|
-
entries = readdirSync3(at, { withFileTypes: true });
|
|
832
|
-
} catch {
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
for (const entry of entries) {
|
|
836
|
-
if (entry.isDirectory()) {
|
|
837
|
-
if (!entry.name.startsWith(".") && !NEVER_WALKED2.has(entry.name)) walk2(join7(at, entry.name));
|
|
838
|
-
continue;
|
|
839
|
-
}
|
|
840
|
-
if (entry.isFile() && match(entry.name)) found.push(join7(at, entry.name));
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
walk2(dir);
|
|
844
|
-
return found;
|
|
845
|
-
};
|
|
856
|
+
var finding4 = findingMaker("drift");
|
|
846
857
|
var ci = (root) => {
|
|
847
858
|
const dir = join7(root, WORKFLOWS);
|
|
848
859
|
if (!existsSync6(dir)) {
|
|
@@ -1194,7 +1205,7 @@ var sourceDirsIn = (dir) => {
|
|
|
1194
1205
|
return [];
|
|
1195
1206
|
}
|
|
1196
1207
|
return entries.filter(
|
|
1197
|
-
(entry) => entry.isDirectory() && !entry.name.startsWith(".") && !
|
|
1208
|
+
(entry) => entry.isDirectory() && !entry.name.startsWith(".") && !NEVER_WALKED.has(entry.name) && filesUnder(join7(dir, entry.name), (name) => LINTABLE.test(name)).length > 0
|
|
1198
1209
|
).map((entry) => entry.name);
|
|
1199
1210
|
};
|
|
1200
1211
|
var lintScopes = (root, workspaces) => {
|
|
@@ -1299,7 +1310,10 @@ var doorBringing = (root, name, declared) => DOORS.filter((door) => declared.has
|
|
|
1299
1310
|
var dependenciesOf = (root, name) => {
|
|
1300
1311
|
try {
|
|
1301
1312
|
return JSON.parse(
|
|
1302
|
-
readFileSync7(
|
|
1313
|
+
readFileSync7(
|
|
1314
|
+
join7(packageDirOf(resolveFrom(root, name, root), name), "package.json"),
|
|
1315
|
+
"utf8"
|
|
1316
|
+
)
|
|
1303
1317
|
).dependencies ?? {};
|
|
1304
1318
|
} catch {
|
|
1305
1319
|
return {};
|
|
@@ -1307,7 +1321,7 @@ var dependenciesOf = (root, name) => {
|
|
|
1307
1321
|
};
|
|
1308
1322
|
var resolves = (root, name) => {
|
|
1309
1323
|
try {
|
|
1310
|
-
resolveFrom(root, name);
|
|
1324
|
+
resolveFrom(root, name, root);
|
|
1311
1325
|
return true;
|
|
1312
1326
|
} catch {
|
|
1313
1327
|
return false;
|
|
@@ -1563,16 +1577,15 @@ import {
|
|
|
1563
1577
|
import { tmpdir } from "os";
|
|
1564
1578
|
import { dirname as dirname2, join as join8, resolve } from "path";
|
|
1565
1579
|
import { corpusOf, readManifest } from "@geonosis/lint-parity";
|
|
1580
|
+
|
|
1581
|
+
// src/rule-level.ts
|
|
1566
1582
|
var OFF = /* @__PURE__ */ new Set([0, "0", "allow", "off", false]);
|
|
1567
1583
|
var severityOf = (level) => Array.isArray(level) ? level[0] : level;
|
|
1584
|
+
|
|
1585
|
+
// src/exercised.ts
|
|
1568
1586
|
var enabledRulesOf = (rules, plugin) => Object.keys(rules).filter((id) => id.startsWith(`${plugin}/`) && !OFF.has(severityOf(rules[id]))).toSorted();
|
|
1569
1587
|
var passes = (findings) => !findings.some((one) => one.verdict === "FAIL" || one.verdict === "UNJUDGED");
|
|
1570
|
-
var finding5 = (
|
|
1571
|
-
check: "exercised",
|
|
1572
|
-
message,
|
|
1573
|
-
subject,
|
|
1574
|
-
verdict
|
|
1575
|
-
});
|
|
1588
|
+
var finding5 = findingMaker("exercised");
|
|
1576
1589
|
var LIMIT = 800;
|
|
1577
1590
|
var refusal = (error) => {
|
|
1578
1591
|
const said2 = String(error.message).trim();
|
|
@@ -1667,6 +1680,7 @@ var throughProbes = ({
|
|
|
1667
1680
|
corpus,
|
|
1668
1681
|
oxlint,
|
|
1669
1682
|
probes,
|
|
1683
|
+
root,
|
|
1670
1684
|
silent
|
|
1671
1685
|
}) => {
|
|
1672
1686
|
const refused = /* @__PURE__ */ new Map();
|
|
@@ -1725,7 +1739,7 @@ var throughProbes = ({
|
|
|
1725
1739
|
const probeConfig = JSON.parse(readFileSync8(config.path, "utf8"));
|
|
1726
1740
|
const configDir = dirname2(config.path);
|
|
1727
1741
|
probeConfig.jsPlugins = (probeConfig.jsPlugins ?? []).map(
|
|
1728
|
-
(spec) => spec.startsWith(".") || spec.startsWith("/") ? resolve(configDir, spec) : packageDirOf(resolveFrom(configDir, spec), spec)
|
|
1742
|
+
(spec) => spec.startsWith(".") || spec.startsWith("/") ? resolve(configDir, spec) : packageDirOf(resolveFrom(configDir, spec, root), spec)
|
|
1729
1743
|
);
|
|
1730
1744
|
const at = join8(here, ".oxlintrc-geonosis-probe.json");
|
|
1731
1745
|
writeFileSync(at, JSON.stringify(probeConfig, null, 2));
|
|
@@ -1822,7 +1836,7 @@ var checkExercised = async ({
|
|
|
1822
1836
|
let probed = { fired: /* @__PURE__ */ new Set(), refused: /* @__PURE__ */ new Map() };
|
|
1823
1837
|
if (declared.length > 0) {
|
|
1824
1838
|
try {
|
|
1825
|
-
probed = throughProbes({ config, corpus, oxlint, probes, silent: declared });
|
|
1839
|
+
probed = throughProbes({ config, corpus, oxlint, probes, root, silent: declared });
|
|
1826
1840
|
} catch (error) {
|
|
1827
1841
|
return said2("FAIL", `the declared probes could not be run \u2014 ${refusal(error)}`);
|
|
1828
1842
|
}
|
|
@@ -1863,12 +1877,8 @@ var THIS_TOOL = "doctor";
|
|
|
1863
1877
|
var OWN = `${THIS_TOOL}.json`;
|
|
1864
1878
|
var NO_ENVELOPES = "no .geonosis/envelopes/*.json \u2014 the tools write one per run, so an absent envelope is a run nobody has made here yet, and it is not a balanced one (this run\u2019s own doctor.json is not one of them: it is written after these checks, and balanced at write time)";
|
|
1865
1879
|
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1866
|
-
var
|
|
1867
|
-
|
|
1868
|
-
message,
|
|
1869
|
-
subject,
|
|
1870
|
-
verdict
|
|
1871
|
-
});
|
|
1880
|
+
var make2 = findingMaker("envelope");
|
|
1881
|
+
var finding6 = (verdict, subject, message) => make2(subject, verdict, message);
|
|
1872
1882
|
var lengthOf = (value) => Array.isArray(value) ? value.length : void 0;
|
|
1873
1883
|
var NEXT = "Next: re-run the tool that wrote it and read the numbers it prints \u2014 a run that has lost count of its own inputs is a bug in that tool, not in this tree";
|
|
1874
1884
|
var judge = (subject, name, parsed) => {
|
|
@@ -1939,12 +1949,7 @@ import { existsSync as existsSync9, readFileSync as readFileSync10 } from "fs";
|
|
|
1939
1949
|
import { dirname as dirname3, join as join10 } from "path";
|
|
1940
1950
|
var SCOPE = "@geonosis/";
|
|
1941
1951
|
var EXAM = /(?:^|[^$\w])([$\w]*Conformance)\b/g;
|
|
1942
|
-
var finding7 = (
|
|
1943
|
-
check: "exams",
|
|
1944
|
-
message,
|
|
1945
|
-
subject,
|
|
1946
|
-
verdict
|
|
1947
|
-
});
|
|
1952
|
+
var finding7 = findingMaker("exams");
|
|
1948
1953
|
var declaredBy = (workspaces) => {
|
|
1949
1954
|
const found = /* @__PURE__ */ new Map();
|
|
1950
1955
|
const provided = new Set(
|
|
@@ -1984,18 +1989,19 @@ var declarationsOf = (dir) => {
|
|
|
1984
1989
|
}
|
|
1985
1990
|
}).join("\n");
|
|
1986
1991
|
};
|
|
1987
|
-
var installedAt = (from, name) => {
|
|
1992
|
+
var installedAt = (from, name, root) => {
|
|
1988
1993
|
let at = from;
|
|
1989
1994
|
for (; ; ) {
|
|
1990
1995
|
const dir = join10(at, "node_modules", name);
|
|
1991
1996
|
if (existsSync9(join10(dir, "package.json"))) return dir;
|
|
1997
|
+
if (at === root) return void 0;
|
|
1992
1998
|
const up = dirname3(at);
|
|
1993
1999
|
if (up === at) return void 0;
|
|
1994
2000
|
at = up;
|
|
1995
2001
|
}
|
|
1996
2002
|
};
|
|
1997
|
-
var examsShippedBy = (from, name) => {
|
|
1998
|
-
const dir = installedAt(from, name);
|
|
2003
|
+
var examsShippedBy = (from, name, root) => {
|
|
2004
|
+
const dir = installedAt(from, name, root);
|
|
1999
2005
|
if (dir === void 0) return [];
|
|
2000
2006
|
return [...new Set([...declarationsOf(dir).matchAll(EXAM)].map((one) => one[1]))];
|
|
2001
2007
|
};
|
|
@@ -2006,7 +2012,7 @@ var checkExams = ({
|
|
|
2006
2012
|
const tests = testFilesUnder(root).map((path) => ({ path, source: readFileSync10(path, "utf8") }));
|
|
2007
2013
|
const found = [];
|
|
2008
2014
|
for (const { from, name } of declaredBy(workspaces)) {
|
|
2009
|
-
const exams = examsShippedBy(from, name);
|
|
2015
|
+
const exams = examsShippedBy(from, name, root);
|
|
2010
2016
|
if (exams.length === 0) continue;
|
|
2011
2017
|
for (const exam of exams) {
|
|
2012
2018
|
const importing = tests.find((one) => one.source.includes(name) && one.source.includes(exam));
|
|
@@ -2162,12 +2168,7 @@ var declaredFor = ({
|
|
|
2162
2168
|
}
|
|
2163
2169
|
return void 0;
|
|
2164
2170
|
};
|
|
2165
|
-
var finding8 = (
|
|
2166
|
-
check: "loaded",
|
|
2167
|
-
message,
|
|
2168
|
-
subject,
|
|
2169
|
-
verdict
|
|
2170
|
-
});
|
|
2171
|
+
var finding8 = findingMaker("loaded");
|
|
2171
2172
|
var firstLine = (error) => String(error.message).split("\n")[0] ?? "";
|
|
2172
2173
|
var versionAt = async (entry, specifier, root) => ({
|
|
2173
2174
|
at: relativeToRoot(root, packageDirOf(entry, specifier)),
|
|
@@ -2182,9 +2183,9 @@ var oneConfig = async ({
|
|
|
2182
2183
|
const said2 = (verdict, message) => finding8(config.relative, verdict, `${specifier}: ${message}`);
|
|
2183
2184
|
let loaded;
|
|
2184
2185
|
try {
|
|
2185
|
-
loaded = await versionAt(resolveFrom(config.dir, specifier), specifier, root);
|
|
2186
|
+
loaded = await versionAt(resolveFrom(config.dir, specifier, root), specifier, root);
|
|
2186
2187
|
} catch (error) {
|
|
2187
|
-
return said2(
|
|
2188
|
+
return error instanceof AboveRootError ? said2("FAIL", error.message) : said2(
|
|
2188
2189
|
"FAIL",
|
|
2189
2190
|
`could not resolve it from this config's directory, and oxlint resolves it from exactly there \u2014 ${firstLine(error)}`
|
|
2190
2191
|
);
|
|
@@ -2218,7 +2219,7 @@ var copiesOf = async ({
|
|
|
2218
2219
|
for (const workspace of workspaces) {
|
|
2219
2220
|
let entry;
|
|
2220
2221
|
try {
|
|
2221
|
-
entry = resolveFrom(workspace.dir, specifier);
|
|
2222
|
+
entry = resolveFrom(workspace.dir, specifier, root);
|
|
2222
2223
|
} catch {
|
|
2223
2224
|
continue;
|
|
2224
2225
|
}
|
|
@@ -2244,7 +2245,7 @@ var shipperOf = (root, bin) => {
|
|
|
2244
2245
|
const name = bin === "geonosis" ? "@geonosis/cli" : `@geonosis/${bin.replace(/^geonosis-/, "")}`;
|
|
2245
2246
|
try {
|
|
2246
2247
|
const manifest = JSON.parse(
|
|
2247
|
-
readFileSync12(join12(packageDirOf(resolveFrom(root, name), name), "package.json"), "utf8")
|
|
2248
|
+
readFileSync12(join12(packageDirOf(resolveFrom(root, name, root), name), "package.json"), "utf8")
|
|
2248
2249
|
);
|
|
2249
2250
|
const declared = manifest.bin;
|
|
2250
2251
|
return typeof declared === "object" && !Object.hasOwn(declared, bin) ? "" : name;
|
|
@@ -2342,7 +2343,7 @@ var checkLoaded = async ({
|
|
|
2342
2343
|
var trainVersion = async (root, specifiers) => {
|
|
2343
2344
|
for (const specifier of specifiers.toSorted()) {
|
|
2344
2345
|
try {
|
|
2345
|
-
return await pluginVersionOf(resolveFrom(root, specifier));
|
|
2346
|
+
return await pluginVersionOf(resolveFrom(root, specifier, root));
|
|
2346
2347
|
} catch {
|
|
2347
2348
|
continue;
|
|
2348
2349
|
}
|
|
@@ -2357,12 +2358,8 @@ var GEONOSIS_FILE2 = "geonosis.json";
|
|
|
2357
2358
|
var REACHES_NOTHING = /* @__PURE__ */ new Set(["console", "memory", "noop", "none", "null", "swallowing"]);
|
|
2358
2359
|
var DEFAULT_MAX_AGE_SECONDS = 3600;
|
|
2359
2360
|
var HEAD_TIMEOUT_MS = 3e3;
|
|
2360
|
-
var
|
|
2361
|
-
|
|
2362
|
-
message,
|
|
2363
|
-
subject,
|
|
2364
|
-
verdict
|
|
2365
|
-
});
|
|
2361
|
+
var make3 = findingMaker("observability");
|
|
2362
|
+
var finding9 = (verdict, subject, message) => make3(subject, verdict, message);
|
|
2366
2363
|
var readGeonosis2 = (root) => {
|
|
2367
2364
|
let text;
|
|
2368
2365
|
try {
|
|
@@ -2537,12 +2534,7 @@ var wrapperNamedBy = (script, dir) => {
|
|
|
2537
2534
|
var asCommand = (source) => source.replaceAll(/['"`,[\]()]/gu, " ");
|
|
2538
2535
|
var ASKS_FOR_A_REPORT = /--outputFile|--reporter[= ]\S*json/i;
|
|
2539
2536
|
var PARSES_A_REPORT = /JSON\.parse|numFailedTests/;
|
|
2540
|
-
var finding10 = (
|
|
2541
|
-
check: "runner",
|
|
2542
|
-
message,
|
|
2543
|
-
subject,
|
|
2544
|
-
verdict
|
|
2545
|
-
});
|
|
2537
|
+
var finding10 = findingMaker("runner");
|
|
2546
2538
|
var stringOf = (value) => typeof value === "string" ? value : "";
|
|
2547
2539
|
var namesOf = (workspace) => [workspace.relative, stringOf(workspace.manifest.name)].filter((one) => one !== "");
|
|
2548
2540
|
var covers = (command, workspace, workspaces) => {
|
|
@@ -2735,9 +2727,7 @@ var checkEngines = async ({
|
|
|
2735
2727
|
// src/path-grants.ts
|
|
2736
2728
|
import { readdirSync as readdirSync6 } from "fs";
|
|
2737
2729
|
import { join as join15 } from "path";
|
|
2738
|
-
var
|
|
2739
|
-
var severityOf2 = (level) => Array.isArray(level) ? level[0] : level;
|
|
2740
|
-
var NEVER_WALKED3 = /* @__PURE__ */ new Set([".git", "coverage", "dist", "node_modules"]);
|
|
2730
|
+
var NEVER_WALKED2 = /* @__PURE__ */ new Set([".git", "coverage", "dist", "node_modules"]);
|
|
2741
2731
|
var LINTABLE2 = /\.[cm]?[jt]sx?$/;
|
|
2742
2732
|
var filesUnder2 = (root, at = "") => {
|
|
2743
2733
|
let entries;
|
|
@@ -2749,7 +2739,7 @@ var filesUnder2 = (root, at = "") => {
|
|
|
2749
2739
|
return entries.flatMap((entry) => {
|
|
2750
2740
|
const here = at === "" ? entry.name : `${at}/${entry.name}`;
|
|
2751
2741
|
if (entry.isDirectory()) {
|
|
2752
|
-
return
|
|
2742
|
+
return NEVER_WALKED2.has(entry.name) ? [] : filesUnder2(root, here);
|
|
2753
2743
|
}
|
|
2754
2744
|
return LINTABLE2.test(entry.name) ? [here] : [];
|
|
2755
2745
|
});
|
|
@@ -2779,7 +2769,7 @@ var checkPathGrants = ({
|
|
|
2779
2769
|
const found = [];
|
|
2780
2770
|
for (const [id, grant] of declared) {
|
|
2781
2771
|
for (const layer of layersOf(config, id)) {
|
|
2782
|
-
if (
|
|
2772
|
+
if (OFF.has(severityOf(layer.level))) continue;
|
|
2783
2773
|
const options = bagOf(layer.level);
|
|
2784
2774
|
const patterns = stringsOf2(options[grant.paths]);
|
|
2785
2775
|
if (patterns.length === 0) continue;
|
|
@@ -2805,12 +2795,7 @@ var PROJECT = ".claude/settings.json";
|
|
|
2805
2795
|
var LOCAL = ".claude/settings.local.json";
|
|
2806
2796
|
var RUN_RECORD = ".geonosis/rails-run.json";
|
|
2807
2797
|
var managedSettingsPath = (platform = process.platform) => platform === "darwin" ? "/Library/Application Support/ClaudeCode/managed-settings.json" : "/etc/claude-code/managed-settings.json";
|
|
2808
|
-
var finding11 = (
|
|
2809
|
-
check: "rails",
|
|
2810
|
-
message,
|
|
2811
|
-
subject,
|
|
2812
|
-
verdict
|
|
2813
|
-
});
|
|
2798
|
+
var finding11 = findingMaker("rails");
|
|
2814
2799
|
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2815
2800
|
var networkIn = (parsed) => {
|
|
2816
2801
|
if (!isRecord3(parsed)) return void 0;
|
|
@@ -3009,8 +2994,8 @@ var exercisedOf = ({
|
|
|
3009
2994
|
let corpus;
|
|
3010
2995
|
let entry;
|
|
3011
2996
|
try {
|
|
3012
|
-
corpus = corpusOfPlugin(config.dir, specifier);
|
|
3013
|
-
entry = resolveFrom(config.dir, specifier);
|
|
2997
|
+
corpus = corpusOfPlugin(config.dir, specifier, root);
|
|
2998
|
+
entry = resolveFrom(config.dir, specifier, root);
|
|
3014
2999
|
} catch (error) {
|
|
3015
3000
|
return [
|
|
3016
3001
|
{
|
|
@@ -3040,13 +3025,13 @@ var exercisedOf = ({
|
|
|
3040
3025
|
})
|
|
3041
3026
|
)
|
|
3042
3027
|
);
|
|
3043
|
-
var requiredOptionsOf = async (configs) => {
|
|
3028
|
+
var requiredOptionsOf = async (configs, root) => {
|
|
3044
3029
|
const found = await Promise.all(
|
|
3045
3030
|
configs.flatMap(
|
|
3046
3031
|
(config) => config.jsPlugins.filter((name) => name.startsWith(SCOPE2)).map(async (specifier) => {
|
|
3047
3032
|
let entry;
|
|
3048
3033
|
try {
|
|
3049
|
-
entry = resolveFrom(config.dir, specifier);
|
|
3034
|
+
entry = resolveFrom(config.dir, specifier, root);
|
|
3050
3035
|
} catch {
|
|
3051
3036
|
return [];
|
|
3052
3037
|
}
|
|
@@ -3098,7 +3083,7 @@ var runDoctor = async ({
|
|
|
3098
3083
|
"loaded",
|
|
3099
3084
|
async () => [
|
|
3100
3085
|
...await checkLoaded({ configs, home, root, workspaces }),
|
|
3101
|
-
...await requiredOptionsOf(configs)
|
|
3086
|
+
...await requiredOptionsOf(configs, root)
|
|
3102
3087
|
]
|
|
3103
3088
|
],
|
|
3104
3089
|
[
|
|
@@ -3200,6 +3185,8 @@ export {
|
|
|
3200
3185
|
discoverConfigs,
|
|
3201
3186
|
discoverWorkspaces,
|
|
3202
3187
|
readRatchet,
|
|
3188
|
+
CHECKS,
|
|
3189
|
+
DoctorError,
|
|
3203
3190
|
defaultRef,
|
|
3204
3191
|
checkBaseline,
|
|
3205
3192
|
DEPLOYED_FILE,
|
|
@@ -3207,8 +3194,6 @@ export {
|
|
|
3207
3194
|
checkDeployed,
|
|
3208
3195
|
GEONOSIS_FILE,
|
|
3209
3196
|
repoCorpusOf,
|
|
3210
|
-
CHECKS,
|
|
3211
|
-
DoctorError,
|
|
3212
3197
|
resolveFrom,
|
|
3213
3198
|
packageDirOf,
|
|
3214
3199
|
pluginVersionOf,
|
package/dist/doctor-cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -378,7 +378,12 @@ declare const repoCorpusOf: (root: string) => string | undefined;
|
|
|
378
378
|
declare const formatDoctor: ({ counts, findings, ok, root }: DoctorReport) => string;
|
|
379
379
|
declare const formatJson: (report: DoctorReport) => string;
|
|
380
380
|
|
|
381
|
-
|
|
381
|
+
/**
|
|
382
|
+
* `root` is the directory the doctor was HANDED — the boundary a deployed tree actually has. A
|
|
383
|
+
* package on the way up from `dir` but past `root` is not this tree's to see; #373/#386 measured
|
|
384
|
+
* the kit's own workspace two directories above a consumer's checkout read exactly that way.
|
|
385
|
+
*/
|
|
386
|
+
declare const resolveFrom: (dir: string, specifier: string, root: string) => string;
|
|
382
387
|
/** The package a resolved entry point belongs to: up until a manifest claims the name. */
|
|
383
388
|
declare const packageDirOf: (entry: string, name: string) => string;
|
|
384
389
|
/**
|
|
@@ -388,7 +393,7 @@ declare const packageDirOf: (entry: string, name: string) => string;
|
|
|
388
393
|
*/
|
|
389
394
|
declare const pluginVersionOf: (entry: string) => Promise<string>;
|
|
390
395
|
/** Where a plugin keeps the corpus it is evidence by, if it ships one at all. */
|
|
391
|
-
declare const corpusOfPlugin: (from: string, specifier: string) => string;
|
|
396
|
+
declare const corpusOfPlugin: (from: string, specifier: string, root: string) => string;
|
|
392
397
|
/**
|
|
393
398
|
* A resolved path, said relative to the root. Both sides are realpath'd first: a resolver returns
|
|
394
399
|
* the real path, and on macOS a temp root under `/var/folders` is a symlink to `/private/var`, so
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geonosis/doctor",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"types": "./dist/index.d.ts",
|
|
5
5
|
"description": "The adoption doctor — declared ≠ loaded, enabled ≠ exercised, a baseline that grew, a runner whose exit code is the only verdict.",
|
|
6
6
|
"keywords": [
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@geonosis/lint-parity": "2.5.
|
|
39
|
+
"@geonosis/lint-parity": "2.5.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@geonosis/ratchet": "2.5.
|
|
42
|
+
"@geonosis/ratchet": "2.5.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"oxlint": ">=1.77"
|