@geonosis/doctor 1.4.0 → 2.1.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.
package/README.md CHANGED
@@ -24,7 +24,7 @@ geonosis-doctor [--root <dir>] [--json] [--strict] [--baseline-against [<ref>]]
24
24
 
25
25
  ## One check, asked alone
26
26
 
27
- `geonosis-doctor --only loaded` runs that check and no other, in well under a second: a manifest read and a resolution per config. It exists because the doctor subsumed a consumer's own declared-vs-loaded script that lived in a 2.5 s local gate, and eleven seconds for seven checks cannot live there — so the question that catches a stale nested copy earliest had fallen out of the gate that runs most often (during.day, 2026-08-30: `bun add` across eleven workspaces left `packages/workflows` loading 1.0.0 against configs written for 1.1.0, and the script about to be deleted caught it). `--only loaded,runner` takes a list; a name the doctor does not have is refused with the seven it does. A `loaded` FAIL now says the remedy: remove the nested copies and reinstall.
27
+ `geonosis-doctor --only loaded` runs that check and no other, in well under a second: a manifest read and a resolution per config. It exists because the doctor subsumed a consumer's own declared-vs-loaded script that lived in a 2.5 s local gate, and eleven seconds for seven checks cannot live there — so the question that catches a stale nested copy earliest had fallen out of the gate that runs most often (measured in a consumer, 2026-08-30: a per-workspace `bun add` left one workspace loading 1.0.0 against configs written for 1.1.0, and the script about to be deleted caught it). `--only loaded,runner` takes a list; a name the doctor does not have is refused with the seven it does. A `loaded` FAIL now says the remedy: remove the nested copies and reinstall.
28
28
 
29
29
  ## The seven checks
30
30
 
@@ -55,6 +55,29 @@ npm and pnpm alike.
55
55
  A declared range this check cannot read is a **FAIL**, not a pass. A version it cannot judge is a
56
56
  refusal.
57
57
 
58
+ #### A geonosis bin a git hook cannot start
59
+
60
+ Every committed hook — `lefthook.yml`, `.husky/*`, `.githooks/*` — is read, and a line running a
61
+ geonosis bin through `pnpm`, `npx`, `bunx` or `yarn` is a **FAIL** naming the direct call that
62
+ replaces it.
63
+
64
+ A git hook's PATH is not the shell's: no nvm shim, no corepack shim, nothing a version manager put
65
+ there. dielime's first hooked commit was "refused" on 2026-08-30 and the ledger never ran — `pnpm`
66
+ was not found, and the sentence its author read was a version manager's failure wearing a gate's
67
+ refusal costume. That is the worst shape a gate has, because it is indistinguishable from the gate
68
+ working. `node_modules/.bin/<bin>` is linked by every package manager and needs nothing on PATH.
69
+
70
+ A hook file naming no geonosis bin is a **SKIP** with the sentence, never a vacuous OK.
71
+
72
+ The FAIL names what the fix costs elsewhere: knip's lefthook plugin does not resolve
73
+ `node_modules/.bin/<bin>` back to the package that ships it, so taking this refusal makes knip call
74
+ that dependency unused. The line carries the `ignoreDependencies` entry that answers it, to be added
75
+ in the same commit — a consumer told to do one thing by one gate and undo it by another does
76
+ neither (#176).
77
+
78
+ It is a `loaded` line, not a `drift` one: it reads a committed file and nothing else, and
79
+ during.day's fast tier runs `--only loaded`, so as a drift line it fired in CI and never locally.
80
+
58
81
  ## The options a rule actually runs under
59
82
 
60
83
  Every reader here that consumes a rule's configuration reads `overrides[]` as well as `rules`, and
@@ -169,6 +192,28 @@ nowhere in it is a FAIL — claiming evidence and shipping none is worse than cl
169
192
  It is read for the config beside `geonosis.json` and no other: a nested config sets different
170
193
  options, and asking one config's fixtures to answer for another's would report firing nowhere.
171
194
 
195
+ #### The engine a rule presumes (#159)
196
+
197
+ A rule that reaches ONE engine carries it in its own metadata — `presumes: { engine, packages }` —
198
+ and this asks every manifest the config governs — its own, the ones above it up to the root, and the
199
+ workspaces underneath — whether any of those packages is declared, naming the ones it read. A
200
+ backend one directory BELOW a root config declares the engine for the rules that config enables over
201
+ it (#227). during.day ran three Medusa rules at `error` over sagaflow trees: the default step
202
+ factory is `createStep`, sagaflow has none, and the possible findings were zero. Enabled-with-no-
203
+ engine and clean are the identical green.
204
+
205
+ A **WARN**, because which rules a repo enables is the repo's decision and the two actions — drop the
206
+ rule from that config, or install the engine — are the reader's. A plugin too old to declare any
207
+ presumption answers with none, and says nothing.
208
+
209
+ #### What the number is evidence about (#160)
210
+
211
+ The `exercised` line says, on the same line as its number, that the firing happened in the corpus
212
+ and in the probes and **says nothing about this tree**. "17 enabled, 17 exercised" was read as
213
+ liveness in a consumer; three of those 17 could never fire on the surface that repo writes, and its
214
+ own `--prove` plant was green in a spelling its code does not use. Nobody goes looking for the
215
+ denominator of a green, so it goes where the green is.
216
+
172
217
  ### `baseline` — a number that may only shrink, against another ref
173
218
 
174
219
  A ratchet lowers its **own** baseline whenever a number shrinks; that is what locks a win in, and it
@@ -201,8 +246,8 @@ naming bun. It used to be warned with vitest's sentence — eight lines of it in
201
246
  report, each blaming a runner the check had not read, which is how a reader learns to skim the
202
247
  section and miss the vitest lines beside them that are true.
203
248
 
204
- A workspace whose test script runs a runner over **zero test files** is a SKIP, not a warning:
205
- dielime's `packages/eslint-config` runs `vitest run` and has no test file under it, so there is no
249
+ A workspace whose test script runs a runner over **zero test files** is a SKIP, not a warning: one
250
+ consumer has a config-only workspace that runs `vitest run` over nothing, so there is no
206
251
  result for an exit code to be wrong about. The message says what was counted.
207
252
 
208
253
  The message names the runner it read. What it does not do is see through a wrapper: a script that
@@ -210,6 +255,17 @@ runs `bun ./scripts/vitest-strict.ts` reads as neither, and that consumer's wrap
210
255
  exemplary fix — it spawns vitest with `--reporter=json`, reads the report, and fails on a missing
211
256
  one. The verdict is right and the sentence understates it.
212
257
 
258
+ #### A falsification nothing runs
259
+
260
+ `geonosis-ratchet --prove` plants each counter's known-bad input and requires the counter to read
261
+ it — a gate that has never been seen red has not been shown to measure (D-029). The ratchet is
262
+ strict about this where the flag runs, and until now nothing asked whether the flag is ever run: a
263
+ prove that lives in the release ritual is run by the release that remembers it, and a counter can
264
+ spend a release reading zero off a mis-escaped match (#140, measured in a consumer).
265
+
266
+ A repo with counters and no `--prove` in any verify tier, script or workflow is a **WARN** naming a
267
+ tier it already declares. A repo with no ratchet configured gets no line at all.
268
+
213
269
  ### `drift` — the gate that is no longer there
214
270
 
215
271
  The other four ask whether a gate measures what it names. This one asks whether it still runs.
@@ -224,7 +280,10 @@ The other four ask whether a gate measures what it names. This one asks whether
224
280
  | workspace bins | FAIL | a script calling a bin THIS repo's own workspaces declare, with no `node_modules/.bin/<name>` at the root. pnpm links a workspace bin only for the packages that depend on it: dielime's `@dielime/gate-tools` had to become an explicit root devDependency before the gate scripts could find it, and naming that took a debugging session. External commands are not judged — that would be a guess |
225
281
  | plugin directories | FAIL | a manifest directory under the roots `no-unregistered-plugin-dir` names that the registry never mentions. SKIP when the rule is not configured — the roots are the repo's, read from the rule it already wrote, never a list invented here |
226
282
  | `publicHoistPattern` | FAIL / SKIP | a pattern in `pnpm-workspace.yaml` with no root `node_modules` link for a workspace package it matches. pnpm dropped one during an **unrelated** `add`, then answered "Already up to date" to every install afterwards over a clean `git status` — the tree was fixed only by deleting `.modules.yaml` and `.pnpm-workspace-state-v1.json`, which the line carries verbatim. Only workspace packages are judged, because one exists on disk by construction and a missing link for it cannot be "the install never ran"; the root package is never asked about, since no package manager puts a repo's root inside its own `node_modules`. A pattern matching no workspace package is SKIP, never a pass |
227
- | the law | WARN / SKIP | its measured length against `geonosis.json` → `law.maxLines`. **SKIP when the repo declares no ceiling** — during.day read "1,104 lines against a ceiling of 200" for a number it never chose, which is unactionable in both directions. The length is still printed, because that is the number a repo declares against |
283
+ | `@geonosis/observability` | WARN | it is declared in a manifest here and **no source file imports it** — installed is not composed. The kit ships the sink adapter and the reference consumer sent production errors nowhere, because nothing at its composition root ever built one; from outside the process that reads exactly like a project with nothing to report (#165). No line at all in a repo that never installed it |
284
+ | an `allowBuilds` entry | WARN | a platform-split package allowed by ONE platform name. pnpm 11.5.1 writes this file itself when it refuses a build script, and what it writes is the platform of the machine that ran the install — so every other platform refuses the install by the name that is missing, on somebody else's machine (#188, measured here). How many a family publishes is the registry's answer, so the line names the family and the shape rather than a count it would have to guess |
285
+ | a workspace's `lint` script | WARN / SKIP | the file set the script covers, against the one a committed hook lints. One consumer's app script covered its source directory and not its test one, so the pre-commit hook — which lints whatever is STAGED — was the first door ever to read a moved test file, and it found violations the package gate had never seen (#172). The line names the globs left to the hook alone. SKIP when no committed hook lints staged files: there is no second file set to be narrower than |
286
+ | the law | WARN / SKIP | its measured length against `geonosis.json` → `law.maxLines`. **SKIP when the repo declares no ceiling** — a consumer read "1,104 lines against a ceiling of 200" for a number it never chose, which is unactionable in both directions. The length is still printed, because that is the number a repo declares against |
228
287
  | `.claude/settings.json` | WARN | nothing under `enabledPlugins` enables the kit's plugin, so the gates run and the method does not (D-041). The **user-scope** `~/.claude/settings.json` is read too and acknowledged as "installed elsewhere — not this repo's to declare": both source repos got this WARN while the plugin was installed machine-wide. The key is read, never the word `geonosis` appearing somewhere in the file |
229
288
  | `geonosis.json` blocks | WARN | a block whose package **no manifest declares** — nothing reads it, and a stale `node_modules` copy is named as what a previous install left behind; a block whose package is declared and does not resolve — run the install; or a **declared** package with no block, running on defaults nobody chose |
230
289
 
@@ -238,20 +297,6 @@ The "installed with no block" direction is scoped to **direct** dependencies. `@
238
297
  a package they never installed is noise — which is how a reader learns to skip the section (#61). A
239
298
  transitive presence gets an OK line naming where it came from, and no demand.
240
299
 
241
- #### A geonosis bin a git hook cannot start
242
-
243
- Every committed hook — `lefthook.yml`, `.husky/*`, `.githooks/*` — is read, and a line running a
244
- geonosis bin through `pnpm`, `npx`, `bunx` or `yarn` is a **FAIL** naming the direct call that
245
- replaces it.
246
-
247
- A git hook's PATH is not the shell's: no nvm shim, no corepack shim, nothing a version manager put
248
- there. dielime's first hooked commit was "refused" on 2026-08-30 and the ledger never ran — `pnpm`
249
- was not found, and the sentence its author read was a version manager's failure wearing a gate's
250
- refusal costume. That is the worst shape a gate has, because it is indistinguishable from the gate
251
- working. `node_modules/.bin/<bin>` is linked by every package manager and needs nothing on PATH.
252
-
253
- A hook file naming no geonosis bin is a **SKIP** with the sentence, never a vacuous OK.
254
-
255
300
  ### `observability` — a sink nobody can reach
256
301
 
257
302
  The exporter named by the `observability` block in `geonosis.json`: is a sink configured, is its