@geonosis/doctor 1.0.0 → 1.2.0

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.
@@ -1,12 +1,13 @@
1
1
  import {
2
+ CHECKS,
2
3
  formatDoctor,
3
4
  formatJson,
4
5
  runDoctor
5
- } from "./chunk-R4AHDFE3.js";
6
+ } from "./chunk-ZJCUTDQW.js";
6
7
 
7
8
  // src/doctor-cli.ts
8
9
  import { resolve } from "path";
9
- var USAGE = `geonosis-doctor [--root <dir>] [--json] [--strict] [--baseline-against [<ref>]] [--oxlint <path>]
10
+ var USAGE = `geonosis-doctor [--root <dir>] [--only <check,\u2026>] [--json] [--strict] [--baseline-against [<ref>]] [--oxlint <path>]
10
11
 
11
12
  Five questions a version bump is not finished until something has asked. The first four are ways
12
13
  enforcement has reported green while measuring nothing; the fifth asks whether it is still there.
@@ -42,14 +43,22 @@ enforcement has reported green while measuring nothing; the fifth asks whether i
42
43
  geonosis.json set, no .claude/settings.json installing the plugin, and a
43
44
  geonosis.json block whose package is not installed (or the reverse).
44
45
 
46
+ deployed What the pipeline REPORTED deploying, in .geonosis/deployed.json, against what the
47
+ tree declares in the wrangler configs geonosis.json names and release.secrets.
48
+ "versions upload" applies no triggers, so a cron edited in a config is silently
49
+ ignored in production for ever with a green pipeline; a secret can be put outside the
50
+ gate entirely. SKIPs with the sentence when the file is absent \u2014 its absence is not a
51
+ pass \u2014 and reads the file rather than importing @geonosis/release.
52
+
45
53
  exercised reads the corpus the loaded plugin ships, and \u2014 when geonosis.json names one under
46
54
  doctor.corpus \u2014 the corpus THIS repo ships for its own options. Three rules cannot be answered any
47
55
  other way: layer-walls fires on a repo's own layer names, no-brand-names on its brand, and
48
56
  plugin-route-namespaced on its package root, while the shipped corpus says acme and layers/core.
49
57
 
50
- Exits 1 when any line is a FAIL, 2 when the run could not be made at all. --strict promotes every
51
- WARN to a FAIL. --json prints the whole report for a CI step to read.`;
52
- var VALUED = /* @__PURE__ */ new Set(["--oxlint", "--root"]);
58
+ Exits 1 when any line is a FAIL or an UNJUDGED \u2014 a question this could not ask is not a pass \u2014 and
59
+ 2 when the run could not be made at all. --strict promotes every WARN to a FAIL. --json prints the
60
+ whole report for a CI step to read.`;
61
+ var VALUED = /* @__PURE__ */ new Set(["--only", "--oxlint", "--root"]);
53
62
  var parseDoctorArgs = (argv, cwd) => {
54
63
  const read = {};
55
64
  let baseline;
@@ -77,9 +86,15 @@ var parseDoctorArgs = (argv, cwd) => {
77
86
  read[flag] = value;
78
87
  index += 1;
79
88
  }
89
+ const only = read["--only"]?.split(",").map((one) => one.trim()).filter((one) => one !== "");
90
+ const unknown = (only ?? []).filter((one) => !CHECKS.includes(one));
91
+ if (unknown.length > 0) {
92
+ throw new Error(`no check called ${unknown.join(", ")} \u2014 the checks are ${CHECKS.join(", ")}`);
93
+ }
80
94
  return {
81
95
  ...baseline === void 0 ? {} : { baseline },
82
96
  json,
97
+ ...only === void 0 || only.length === 0 ? {} : { only },
83
98
  ...read["--oxlint"] === void 0 ? {} : { oxlint: resolve(cwd, read["--oxlint"]) },
84
99
  root: resolve(cwd, read["--root"] ?? cwd),
85
100
  strict
package/dist/index.d.ts CHANGED
@@ -1,15 +1,22 @@
1
1
  /**
2
- * The five questions a bump is not finished until something has asked, in the order a run asks
3
- * them. The first four are ways enforcement has reported green while measuring nothing; the fifth
4
- * asks whether the gate is still there at all.
2
+ * The questions a bump is not finished until something has asked, in the order a run asks them.
3
+ * The first four are ways enforcement has reported green while measuring nothing; `drift` asks
4
+ * whether the gate is still there at all; `observability` and `deployed` ask the same question one
5
+ * layer out — whether what was reported is what happened.
5
6
  */
6
- declare const CHECKS: readonly ["loaded", "exercised", "baseline", "runner", "drift", "observability"];
7
+ declare const CHECKS: readonly ["loaded", "exercised", "baseline", "runner", "drift", "observability", "deployed"];
7
8
  type CheckName = (typeof CHECKS)[number];
8
9
  /**
9
10
  * `SKIP` is a first-class answer and is printed like any other: a check whose line is missing reads
10
11
  * as a check that passed, and that is the failure this whole package is about.
12
+ *
13
+ * `UNJUDGED` is the fifth, and it is neither OK nor FAIL. The question could not be ASKED — the
14
+ * corpus has no file this repo's options would reach and the rule declares no probe to make one —
15
+ * so the run does not pass, and the sentence says why instead of accusing the repo. The difference
16
+ * matters because a FAIL over a rule the repo is enforcing correctly is an invitation to delete the
17
+ * rule, and one consumer names exactly such a rule as live enforcement in its own law.
11
18
  */
12
- type Verdict = 'FAIL' | 'OK' | 'SKIP' | 'WARN';
19
+ type Verdict = 'FAIL' | 'OK' | 'SKIP' | 'UNJUDGED' | 'WARN';
13
20
  type Finding = {
14
21
  check: CheckName;
15
22
  message: string;
@@ -58,13 +65,18 @@ type DoctorOptions = {
58
65
  ref?: string;
59
66
  };
60
67
  oxlint?: string;
68
+ /** Run these checks and no other — one question, asked fast, belongs in a sub-second gate. */
69
+ only?: CheckName[];
61
70
  root: string;
62
71
  strict?: boolean;
63
72
  };
64
73
  type DoctorReport = {
65
74
  counts: Record<Verdict, number>;
66
75
  findings: Finding[];
67
- /** False as soon as one line is a FAIL — after `--strict` has promoted the warnings. */
76
+ /**
77
+ * False as soon as one line is a FAIL or an UNJUDGED — after `--strict` has promoted the
78
+ * warnings. "We could not tell" is not a pass; it is the quietest way there is of reading green.
79
+ */
68
80
  ok: boolean;
69
81
  root: string;
70
82
  };
@@ -86,6 +98,24 @@ declare const checkBaseline: ({ ref, root }: {
86
98
  root: string;
87
99
  }) => Finding[];
88
100
 
101
+ /**
102
+ * The `loaded` lie one layer out: what a pipeline SAID it deployed, against what the tree declares.
103
+ *
104
+ * `wrangler versions upload` applies no triggers, so a cron or a route edited in the config is
105
+ * silently ignored in production for ever, with a green pipeline; `wrangler secret put` creates and
106
+ * deploys a version outside the gate entirely. Nothing in either consumer measured any of it.
107
+ *
108
+ * This reads the FILE the consumer's pipeline writes after promote — `.geonosis/deployed.json` —
109
+ * and imports nothing of `@geonosis/release`, the same discipline `observability` follows: a check
110
+ * that needed the package it checks cannot run in the tree where that package is missing. The
111
+ * comparison is duplicated on purpose; it is set differences over four lists.
112
+ */
113
+ declare const DEPLOYED_FILE = ".geonosis/deployed.json";
114
+ declare const NOT_WRITTEN = "no .geonosis/deployed.json \u2014 it is written by the pipeline after promote, and its absence is not a pass";
115
+ declare const checkDeployed: ({ root }: {
116
+ root: string;
117
+ }) => Finding[];
118
+
89
119
  declare const CONFIG_FILE = ".oxlintrc.json";
90
120
  declare const MANIFEST_FILE = "package.json";
91
121
  declare const RATCHET_FILE = "geonosis.ratchet.json";
@@ -96,7 +126,7 @@ declare const discoverConfigs: (root: string) => DiscoveredConfig[];
96
126
  declare const discoverWorkspaces: (root: string) => Workspace[];
97
127
  declare const readRatchet: (root: string) => RatchetConfig | undefined;
98
128
 
99
- declare const runDoctor: ({ baseline, oxlint, root, strict, }: DoctorOptions) => Promise<DoctorReport>;
129
+ declare const runDoctor: ({ baseline, only, oxlint, root, strict, }: DoctorOptions) => Promise<DoctorReport>;
100
130
 
101
131
  /** Which kit package reads which block of `geonosis.json`. */
102
132
  declare const READERS: Record<string, string>;
@@ -133,14 +163,16 @@ declare const enabledRulesOf: (rules: Record<string, unknown>, plugin: string) =
133
163
  * place where the difference is visible, so the question is asked there, under THIS config's
134
164
  * options, because the options are usually where the reach went.
135
165
  */
136
- declare const checkExercised: ({ config, corpus, oxlint, repoCorpus, root, }: {
166
+ declare const checkExercised: ({ config, corpus, entry, oxlint, repoCorpus, root, }: {
137
167
  config: DiscoveredConfig;
138
168
  corpus: string;
169
+ /** The plugin module oxlint loads from this config's directory — where the probes are read. */
170
+ entry?: string;
139
171
  oxlint: string;
140
172
  /** The corpus this repo ships for its OWN options, when `geonosis.json` declares one. */
141
173
  repoCorpus?: string;
142
174
  root: string;
143
- }) => Finding;
175
+ }) => Promise<Finding>;
144
176
 
145
177
  /** The scope this tool asks about. A config's other plugins are somebody else's release to check. */
146
178
  declare const SCOPE = "@geonosis/";
@@ -240,16 +272,19 @@ declare const corpusOfPlugin: (from: string, specifier: string) => string;
240
272
  declare const relativeToRoot: (root: string, path: string) => string;
241
273
 
242
274
  /**
243
- * A test runner's exit code is not a verdict; its summary is.
275
+ * Whether a test runner's exit code is a verdict — asked of the runner the script actually names,
276
+ * not of runners in general.
244
277
  *
245
278
  * `@cloudflare/vitest-pool-workers` exited 0 over suites it had just reported as failing, for
246
279
  * weeks, in a consumer — so every gate that trusted the status read green over red. The fix is a
247
- * runner that writes its own report and something that reads it; this says which workspaces have
248
- * neither.
280
+ * runner that writes its own report and something that reads it; this says which vitest workspaces
281
+ * have neither. `bun test` was measured and does not have the defect, so it is told the two apart:
282
+ * a WARN that names the wrong runner's sin is a line a reader learns to skip, and the lines it
283
+ * teaches them to skip are the true ones next to it.
249
284
  */
250
285
  declare const checkRunner: ({ ratchet, workspaces, }: {
251
286
  ratchet?: RatchetConfig;
252
287
  workspaces: Workspace[];
253
288
  }) => Finding[];
254
289
 
255
- export { CHECKS, CONFIG_FILE, type CheckName, type DiscoveredConfig, DoctorError, type DoctorOptions, type DoctorReport, type Finding, GEONOSIS_FILE, type LastEventRecord, MANIFEST_FILE, type Manifest, type ObservabilityConfig, RATCHET_FILE, READERS, type RatchetConfig, SCOPE, type Verdict, type Workspace, checkBaseline, checkDrift, checkExercised, checkLoaded, checkObservability, checkRunner, corpusOfPlugin, declaredFor, defaultRef, discoverConfigs, discoverWorkspaces, enabledRulesOf, formatDoctor, formatJson, packageDirOf, pluginVersionOf, readConfig, readRatchet, relativePath, relativeToRoot, repoCorpusOf, resolveFrom, runDoctor, satisfies };
290
+ export { CHECKS, CONFIG_FILE, type CheckName, DEPLOYED_FILE, type DiscoveredConfig, DoctorError, type DoctorOptions, type DoctorReport, type Finding, GEONOSIS_FILE, type LastEventRecord, MANIFEST_FILE, type Manifest, NOT_WRITTEN, type ObservabilityConfig, RATCHET_FILE, READERS, type RatchetConfig, SCOPE, type Verdict, type Workspace, checkBaseline, checkDeployed, checkDrift, checkExercised, checkLoaded, checkObservability, checkRunner, corpusOfPlugin, declaredFor, defaultRef, discoverConfigs, discoverWorkspaces, enabledRulesOf, formatDoctor, formatJson, packageDirOf, pluginVersionOf, readConfig, readRatchet, relativePath, relativeToRoot, repoCorpusOf, resolveFrom, runDoctor, satisfies };
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  import {
2
2
  CHECKS,
3
3
  CONFIG_FILE,
4
+ DEPLOYED_FILE,
4
5
  DoctorError,
5
6
  GEONOSIS_FILE,
6
7
  MANIFEST_FILE,
8
+ NOT_WRITTEN,
7
9
  RATCHET_FILE,
8
10
  READERS,
9
11
  SCOPE,
10
12
  checkBaseline,
13
+ checkDeployed,
11
14
  checkDrift,
12
15
  checkExercised,
13
16
  checkLoaded,
@@ -31,17 +34,20 @@ import {
31
34
  resolveFrom,
32
35
  runDoctor,
33
36
  satisfies
34
- } from "./chunk-R4AHDFE3.js";
37
+ } from "./chunk-ZJCUTDQW.js";
35
38
  export {
36
39
  CHECKS,
37
40
  CONFIG_FILE,
41
+ DEPLOYED_FILE,
38
42
  DoctorError,
39
43
  GEONOSIS_FILE,
40
44
  MANIFEST_FILE,
45
+ NOT_WRITTEN,
41
46
  RATCHET_FILE,
42
47
  READERS,
43
48
  SCOPE,
44
49
  checkBaseline,
50
+ checkDeployed,
45
51
  checkDrift,
46
52
  checkExercised,
47
53
  checkLoaded,
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@geonosis/doctor",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
+ "types": "./dist/index.d.ts",
4
5
  "description": "The adoption doctor — declared ≠ loaded, enabled ≠ exercised, a baseline that grew, a runner whose exit code is the only verdict.",
5
6
  "keywords": [
6
7
  "oxlint",
@@ -24,14 +25,17 @@
24
25
  "geonosis-doctor": "bin/geonosis-doctor.mjs"
25
26
  },
26
27
  "exports": {
27
- ".": "./dist/index.js"
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ }
28
32
  },
29
33
  "files": [
30
34
  "bin",
31
35
  "dist"
32
36
  ],
33
37
  "dependencies": {
34
- "@geonosis/lint-parity": "1.0.0"
38
+ "@geonosis/lint-parity": "1.2.0"
35
39
  },
36
40
  "peerDependencies": {
37
41
  "oxlint": ">=1.77"