geonosis 3.0.0 → 3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # geonosis
2
2
 
3
+ ## 3.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - deef511: `geonosis-ledger shape lock --from <manifest>` validates a brief's manifest, resolves its red commit to a full hash and writes the runner-owned `.geonosis/brief.json`, a path the plugin refuses an agent's write to, so the engineer cannot loosen the lock it works under. `geonosis-ledger shape check [--brief <manifest>]` judges an engineer's diff against the RED commit a brief was committed as (D-072). The manifest names `ticket`, `red`, `files`, `locked` and optional `exports`; every path that differs from the red commit, committed, staged, unstaged or untracked, is judged. A locked test that was changed, deleted or moved, a file the manifest does not list, an exported name the red commit held and the file no longer exports, and an exported name neither the red commit nor `exports` names are each refused by path (exit 1); a body-only diff passes; a missing or malformed manifest, or a red commit the tree cannot diff against, is exit 2. New exports of `@geonosis/ledger`: `shapeCheck`, `lockManifest`, `readManifest`, `formatShape`, `MANIFEST_PATH`, `BriefManifest`, `ShapeOutcome`, `ShapeRefusal`. `@geonosis/ratchet` gains `exportedNamesOf(path, source)`, the sorted names a TypeScript or JavaScript source exports (types, destructured bindings, re-exports and `export *` included), read with the parser the counters use.
8
+ The plugin's Bash guard runs `shape check` on `git commit` while `.geonosis/brief.json` is present and refuses the commit with the lock's own lines; a lock that could not run lets the commit through and says so. The engineer definition says to start on the RED commit and that the shape lock is the gate, and the `geonosis-plan` skill says how to commit the applied brief and lock the manifest.
9
+ - deef511: A repo whose `geonosis.json → stack` is not TypeScript passes the doctor with a SKIP that names the language, and gets the method scaffolded without the TypeScript stack. `geonosis-doctor` SKIPs `exercised` as it already did `loaded` (`stack.language is "py"`, so there is no oxlint rule for a corpus to be asked to reach), and `drift` SKIPs, instead of warning "no manifest declares it", a `geonosis.json` block of a kit package in a repo with no package manifest at all; the doctor no longer refuses a tree with no `package.json` and no `.oxlintrc.json` as "nothing here to examine" when `geonosis.json` declares a stack oxlint does not read. `stack` gains `extensions` (`.py .pyi`), the files `stack.format` and `stack.parse` own: with it, the plugin formats only those with `stack.format`, and `pre-edit` and `post-bash` parse them with `stack.parse` (exit non-zero is a parse error; a parser that cannot run says nothing). `stack.parse` without `extensions` applies to no file. A repo with no `stack` behaves as before.
10
+ `create-geonosis <dir> --language py` writes a uv project (`pyproject.toml`, a package, a test), `geonosis.json` with the stack, three `fast` steps with plants and a `full` tier that proves and runs the ratchet (`ruff format --check`, `ruff check`, `pytest`), `LAW.md` from the new `pythonLawSummary` of `@geonosis/cli`, the two language-neutral counters and their baseline, the kit's rule files, `.claude/settings.json` and a CI workflow; it refuses `--runtime`, `--backend`, `--ui`, `--domains`, `--medusa`, `--themekit`, `--brand`, `--kit`, `--presets` and `--check` by name.
11
+
12
+ ### Patch Changes
13
+
14
+ - 5404b2a: Dependencies move to their newest release the install policy accepts: `@modelcontextprotocol/sdk` 1.32.1 (`@geonosis/mcp`), `oxc-parser` 0.153.0 (`@geonosis/ratchet`, `@geonosis/verify`), and the `squawk-cli` 2.68.0 that `@geonosis/release` and `geonosis` ask for as an exact optional peer, so the install line a refusal prints is `squawk-cli@2.68.0`. A scaffold written by `create-geonosis` pins `oxlint` ^1.87.0, `oxfmt` ^0.72.0, `vitest` ^5.0.3 and `@types/node` ^26.6.4.
15
+ - dd5f57a: The `geonosis` package ships `GROUP-CHANGELOG.md`: what one group version bought, every sentence any member carries once with the members that carry it. A member whose version heading held nothing of its own now points there instead of standing blank, which read as "nothing changed" (#356). `pnpm release:cut` writes both.
16
+ - Updated dependencies [f5632b7]
17
+ - Updated dependencies [dd5f57a]
18
+ - Updated dependencies [f5632b7]
19
+ - Updated dependencies [9b1ce78]
20
+ - Updated dependencies [a4a7bba]
21
+ - Updated dependencies [58eaf3a]
22
+ - Updated dependencies [58eaf3a]
23
+ - Updated dependencies [58eaf3a]
24
+ - Updated dependencies [58eaf3a]
25
+ - Updated dependencies [58eaf3a]
26
+ - Updated dependencies [deef511]
27
+ - Updated dependencies [58eaf3a]
28
+ - @geonosis/cli@3.2.0
29
+
30
+ ## 3.1.0
31
+
32
+ ### Patch Changes
33
+
34
+ - @geonosis/cli@3.1.0
35
+
3
36
  ## 3.0.0
4
37
 
5
38
  ### Patch Changes
@@ -0,0 +1,128 @@
1
+ # The geonosis group
2
+
3
+ One number versions every package of the fixed group. A package changelog lists only what a changeset named for that package, so this file lists what the number bought: every sentence any member carries, once, with the members that carry it.
4
+
5
+ ## 3.2.0
6
+
7
+ - New `@geonosis/base`: the zero-dependency bottom of the method, holding what packages used to copy. `@geonosis/base` is `isRecord`, `isStringList`, `stringsOf`, the error text helpers and the markdown readers (`headingsOf`, `sectionUnder`, `fencedLines`, `titleOf`), safe in a browser or a Worker; `@geonosis/base/node` is `packageRootFrom`, `versionOf` and `isDirectory`; `@geonosis/base/bin-harness` is `binRunner(runtime)` for running a package's bin in a test, with `GIT_ISOLATED` for a bin that shells to git. `cli`, `create-geonosis`, `ledger`, `mcp`, `observability`, `rails`, `release`, `review`, `themekit`, `verify`, `verify-arch` and `walk` import the guards from it instead of carrying their own; their behaviour is unchanged and each now installs `@geonosis/base`, which a consumer never declares. The ratchet keeps its own copies: the build runs on its source before any package exists, so nothing it imports may be a package the build produces. (base, cli, ledger, mcp, observability, rails, ratchet, release, review, themekit, verify, verify-arch, walk, create-geonosis)
8
+ - `geonosis update --floors latest` or `--floor <pkg>@<v>` works without `--to`: the group stays at the one version every manifest carries, only the floors move, and the output says `group unchanged at <v>`. A group split across versions is refused and `--to` settles it. A dry run prints a floor already at its target as `(already here)`, a plain `--to` names each own-line package that is behind its line, and a move to an older version is flagged `DOWNGRADE` and reads the changelog entries it undoes instead of calling the older entry unreadable. `geonosis portfolio` prints one row per consumer named in `geonosis.json → portfolio.consumers`, read off the artifact that consumer's CI uploaded: version, lag in days off the registry's publish dates, last green tier, lines the last bump deleted. It exits 2 and prints no row when an artifact is missing or will not parse. `install.allowScripts` in `geonosis.json` lists package names (`@embedded-postgres/*`) whose lifecycle scripts run after the frozen install's `--ignore-scripts`, with `pnpm rebuild` or `bun pm trust`. `sync` refuses (exit 2) over a `geonosis.json` it cannot parse. `init` reads `geonosis.json → stack`: for a language or linter oxlint does not read it writes no `.oxlintrc.json` and no oxlint, tsc or oxfmt counter, and refuses an unreadable config. The MCP server's skew check falls back to the lockfile's resolved version and reports `UNJUDGED` when nothing answers; `update`'s restart line looks in `~/.claude.json` (user and local scope), an installed plugin's `.mcp.json` and Cursor's `mcp.json` as well as `.mcp.json`, and names which one it found. (cli)
9
+ - `geonosis init` and `geonosis update` copy the kit's rule files into `.claude/rules/geonosis/` (also `geonosis rules` alone), each with a `# geonosis-kit <version>` line directly under its opening `---`, removing marked files the kit no longer ships and leaving files a user added; `update` runs the copy it just installed, so the files are the new version's. Copies, because Claude Code loads a symlink out of the repo only after approval and then only the rules with no `paths` list; a `.claude/rules/geonosis` that is a symlink is refused, never written through. `geonosis-doctor` gains a `rules` check that warns when the directory is missing in a kit repo, or a copy differs from what the installed kit ships, naming the file and `geonosis update`. (cli, doctor)
10
+ - `@geonosis/cli` exports `lawSummary({ name, runtime, marketplace })` and `LAW_SUMMARY_TITLES`: the short-form law a scaffolded repo starts with, built in one place, and held by a test against the laws of this repo's own `LAW.md` (every title present, in the same order). `create-geonosis` writes its `LAW.md` from it; the text is unchanged. `geonosis-ledger sync --target agents-md` adds a "Style, in the code these laws produce" section to the generated `AGENTS.md`: the terse-output sentence and the comments law, the same text the plugin's skills and agents carry, exported as `TERSE_OUTPUT_LAW` and `COMMENTS_LAW`. (cli, ledger, create-geonosis)
11
+ - A repo whose `geonosis.json → stack` is not TypeScript passes the doctor with a SKIP that names the language, and gets the method scaffolded without the TypeScript stack. `geonosis-doctor` SKIPs `exercised` as it already did `loaded` (`stack.language is "py"`, so there is no oxlint rule for a corpus to be asked to reach), and `drift` SKIPs, instead of warning "no manifest declares it", a `geonosis.json` block of a kit package in a repo with no package manifest at all; the doctor no longer refuses a tree with no `package.json` and no `.oxlintrc.json` as "nothing here to examine" when `geonosis.json` declares a stack oxlint does not read. `stack` gains `extensions` (`.py .pyi`), the files `stack.format` and `stack.parse` own: with it, the plugin formats only those with `stack.format`, and `pre-edit` and `post-bash` parse them with `stack.parse` (exit non-zero is a parse error; a parser that cannot run says nothing). `stack.parse` without `extensions` applies to no file. A repo with no `stack` behaves as before. `create-geonosis <dir> --language py` writes a uv project (`pyproject.toml`, a package, a test), `geonosis.json` with the stack, three `fast` steps with plants and a `full` tier that proves and runs the ratchet (`ruff format --check`, `ruff check`, `pytest`), `LAW.md` from the new `pythonLawSummary` of `@geonosis/cli`, the two language-neutral counters and their baseline, the kit's rule files, `.claude/settings.json` and a CI workflow; it refuses `--runtime`, `--backend`, `--ui`, `--domains`, `--medusa`, `--themekit`, `--brand`, `--kit`, `--presets` and `--check` by name. (cli, doctor, create-geonosis, geonosis)
12
+ - `geonosis update` bumps a yarn 1 tree: it reads `yarn.lock` with `@yarnpkg/lockfile`, installs with yarn and leaves `yarn install --frozen-lockfile` clean, and `--runtime yarn` names it where no lockfile does. It refuses with exit 2, before writing, when the `yarn` that runs is not yarn 1 (pin `"packageManager": "yarn@1.22.22"`). A `package-lock.json` or a Yarn 2+ `yarn.lock` is refused with exit 2 and the commands that manager's consumer runs instead. `--dry-run` now refuses what the real run refuses. A client kit (`@geonosis/<client>-ui`) moves with the release, to the version the target `@geonosis/cli` records in its published `release-kits.json`. `update --prove` proves the yarn 1 path and the kit, and now FAILS when a manager is not on the machine unless `--skip <manager>` names it. (cli)
13
+ - `--registry <path>` is told apart from a URL by a missing path only (ENOENT, ENOTDIR); any other filesystem error, and any error but a syntax error while reading a packed `package.json`, is rethrown instead of read as "not a registry directory" or "not a package". (cli)
14
+ - `geonosis explain constructor` (or `toString`, `hasOwnProperty`, `__proto__`) is refused as a name nothing here decides, instead of crashing on the property every object inherits; a `geonosis.ratchet.json` whose `counters` hold a `null` or are not a list no longer crashes it either. (cli)
15
+ - `geonosis init` refuses, writing nothing, when a kept `geonosis.ratchet.json` points its baseline outside the repo; `rulesFor` names a preset nobody ships (`no preset called …`) in place of a `TypeError` on `undefined.rules`. (cli)
16
+ - `geonosis sync` reads a `geonosis.json` `law` block key by key: a `file` that is not a string, a `maxLines` that is not a number or a `copy` that is not a boolean is no declaration, where a numeric `file` crashed the run on `join`. (cli)
17
+ - `geonosis skills lock` and `audit` refuse a `skills-lock.json` that is not JSON or holds no `skills` block, naming the file, in place of a `TypeError` from the middle of the run; relocking keeps every other key a previous lock recorded for a skill and for the lock itself instead of rewriting each entry down to four. (cli)
18
+ - `geonosis update` repins a manifest with its own line endings and its own last line: a CRLF file stays CRLF and a file with no final newline gets none, so a bump is a version diff and not a rewrite of every line. (cli)
19
+ - The doctor says when it could not read, and asks more of the tree. A comparison asked for against a baseline HEAD does not hold, or against a ref that is not there, is `UNJUDGED` and no longer a SKIP that passes. A `package.json` that will not parse is a FAIL under `drift` naming the workspace it hid; `readManifest` is the one reader, in three states. `declaredApparatusOf`, `repoCorpusOf` and `declaredGroupsOf` take the `geonosis.json` read the run already holds, and `declaredApparatusOf` throws on one it cannot parse; `checkGroup` takes it as `geonosis`. `drift` WARNs when a workspace imports an `@geonosis/*` package its own manifest does not declare (`turbo boundaries` counted 35 of these in one consumer after a rebase dropped a redundant commit). `exams` reads a floor's `geonosis.bundles` in its manifest, so an imported bundle (`sessionConformance`, `searchConformance`) covers its members, and a floor whose installed manifest will not parse is `UNJUDGED`. Script files are followed four files down, one reader for `groups` and `runner`. Which install Claude Code loads when user and project scope both hold one was measured on 2.1.293: the first record in the file's order that applies, not the project one; `loadedAt` follows it. `geonosis.json → stack` is read once for the hooks, `init` and the doctor (`stackOf`, `oxlintReads`); `loaded` SKIPs, with the sentence, for a language or linter oxlint does not read. New exports: `readGeonosisFile`, `GeonosisRead`, `allInstalledPlugins`, `stackOf`, `oxlintReads`. (doctor)
20
+ - `geonosis-lint-parity --measure <config> --root <tree>` runs one config over a consumer's tree as if it sat in the tree, so a narrowed config's `overrides` and `ignorePatterns` are read against the tree and not against the directory the config was written in. It refuses a config that opens no file. `geonosis-doctor` warns, under `exercised`, for an override whose `files` match no file under the config's directory. The root of this repo now links `geonosis-lint-parity` and `geonosis-release`, so the documented command runs from the root. (doctor, lint-parity)
21
+ - `optionRefusalIn(said)` is the one reader of a rule's "requires option" refusal: the `option` and `rule` fields of an error or a report, then the `data` of a report, then the sentence, from an error, a report or a printed finding. The doctor's missing-option check and the parity tool's refusal check both read through it, so a plugin that words its refusal differently and hands the pair over as fields is a refusal to both, not reach to one and configured to the other. (doctor, lint-parity, ratchet)
22
+ - The package returns to its first name: 0.3.0–0.5.0 were published as `@geonosis/storefront-ui`, and this release is 1.0.0 under `@geonosis/buketi-ui`, above the 0.2.1 there. A client's UI is its own kit, named for it (D-090). Users of 0.2.1 cross the breaking changes of 0.3.0–0.5.0 (see the CHANGELOG); every import path changes its package name and nothing else. The doctor's `FLOOR_PACKAGES` no longer lists a client's kit. (doctor)
23
+ - The drift check that asks whether a declared package is composed no longer asks it of a door package. `@geonosis/cli` and `geonosis` declare `@geonosis/observability` and the floors to bring them along, and the check read that as a repo choosing to install a sink and composing it nowhere. A package an app's own manifest declares is judged as before. (doctor)
24
+ - The drift check (root package scripts only: a script run with `--filter`, `-C` or `-r` is not followed) warns when a counter that times a tier's own gate report (`fastTierMs`) is run by a ratchet step of that same tier: it reads the previous completed run and cannot measure a fresh checkout, so the ceiling belongs in `geonosis.json` `budgets.<tier>` (D-042), or the counter in a tier that tier does not run. A counter can now say which tier it times (`timesTier`). The smoke refuses to compare a baseline recorded under another command (`compareToBaseline`), and `release:check` records it again. (doctor, ratchet, release)
25
+ - A scaffolded repo declares `devEngines.runtime` as bun (downloaded by pnpm, the runtime every kit tool starts on) and node with `onFail: "ignore"`, so npm itself — `npm login`, `npm whoami`, `npm publish` — runs in the repo instead of refusing with `EBADDEVENGINES`. The doctor's `tool runtime` advice gives the same pair. A scaffold pins `pnpm@12.10.1`. (doctor, create-geonosis)
26
+ - The plugin README lists the five oxlint built-ins that fire on idioms the presets ask for (`no-await-in-loop`, `unicorn/no-useless-undefined`, `unicorn/consistent-function-scoping`, `unicorn/throw-new-error`, `no-underscore-dangle`), measured on oxlint 1.87.0, with the config that quiets the four an override or option can reach and the rewrite for the loop. The kit's `tiers.md` rule file says what "inert below the organelle" means: no app or shared state (no store, no data); local UI state such as an open flag is allowed in an atom or a molecule, and a compound holds none. `gates.md` separates adopting a counter, which the ratchet writes and does not judge, from raising a baseline to make a gate go green, which stays forbidden. `geonosis-doctor`'s `rules` check compares against these copies. (doctor, oxlint-plugin-biological-architecture)
27
+ - `geonosis.ratchet.json` that does not parse is refused with the file named, and a counter entry that is not an object is dropped. A `package.json` that is valid JSON but not an object is skipped like one that does not parse, and a dependency block of the wrong shape reads as undeclared. A baseline committed as `null` reads as holding no counter, where the baseline check threw a `TypeError` and ended the run. (doctor)
28
+ - A `doctor.groups[].packages` list holding anything but package names (a number, `null`, an object) is refused with the group named, where only the count of entries was checked. (doctor)
29
+ - The `publicHoistPattern` check reads a `!` entry as an exclusion, as pnpm does. It was read as a pattern of its own, so a workspace package the list excludes was demanded a root link pnpm never makes (a FAIL on a healthy tree), and the exclusion itself printed a SKIP line. (doctor)
30
+ - A script path that climbs into a sibling directory whose name starts with the repo's (`../repo-other/gate.mjs` from `repo`) is no longer read as a script the repo runs. The containment test was a string prefix. (doctor)
31
+ - An installed package whose `package.json` does not parse no longer stops the whole doctor run with a bare JSON error. The `exams` and `drift` checks read it as declaring nothing, as `discover` already does for a workspace manifest. (doctor)
32
+ - An empty law file counts as no lines in `lawLineCount` and in the doctor's ceiling check; it counted as one. Both now read lines the way the seam counter does, from one `lineCount`. (doctor, ratchet)
33
+ - An `adoption.seams` glob is read by one matcher in `@geonosis/ratchet`: `*` and `**` are wildcards and every other character, `?` and braces included, is itself. The `adoptionSeamLines` counter, the doctor's seams check and `smoke snapshot` agreed on none of it before — `src/a?.ts` made the `a` optional, and the doctor accepted brace globs the counter counted as nothing. `smoke snapshot` now refuses a consumer `geonosis.json` that does not parse instead of recording a tree with no seams. (doctor, ratchet, release)
34
+ - A scaffold with `--domains` has a clean doctor. It writes `apps/web/src/platform.exam.test.ts`, which runs the session, connections and (for `search`) search exams over the platform's own seam and index against the Postgres `EXAM_DATABASE_URL` names, and skips where none is set; the app declares `pg`. A `--backend sagaflow-cf` scaffold no longer enables `tenant-scoping`, whose `store-route-scopes-tenant-data` presumes Medusa. `geonosis-doctor`'s `exams` check asks for an exam named `<stem>Conformance` only of a tree that imports the package's `define<Stem>` export when it ships one: `entityConformance` of a tree that calls `defineEntity`, never of one that only opens sessions. The `drift` check no longer counts a test file as the composition of a floor: a tree whose only importer of `@geonosis/search` is its exam file now WARNs that nothing composes it. (doctor, create-geonosis)
35
+ - A counter's report, or an `.oxlintrc.json`, whose top level is not a JSON object is refused by name instead of failing with a TypeError, and an unreadable counter report now reads "does not parse". No other output changed: the rest of this release's diff removes duplicated internals. (doctor, ratchet)
36
+ - A task's expected file now has to be created or changed by the run: a file the fixture already held and the session left as it was no longer scores as left behind. `compareEntries` compares two results entry by entry over the entries both hold (a set that grew is not a regression, a new entry is judged on its own sessions), and `geonosis-evals run --arms` is refused without `--allowed-tools`, since a headless session with no tool allowed measures nothing. The kit set's per-entry budgets are the dearest measured session of the 3.2.0 armed run, doubled. (evals)
37
+ - `geonosis-evals review-bench` scores the reviewer. `derive --fix <commit>` turns a fix commit into two cases (the diff that puts the defect back, with the lines the fix touched as its defect, and the fix itself as a clean control); `run --model <model>` spawns the reviewer over every case; `score` writes `reviewPrecision`, `reviewRecall` and `reviewF1` from the blocking and major findings that landed on a planted defect; `compare` refuses a case both benches hold that lost precision or recall. `reviewPrecision` and `reviewRecall` are dimensions `compare` and `gate --prove` know. `evals/review-bench.json` holds 28 cases derived from this repo's own fix commits. (evals)
38
+ - The law fingerprint a dimension reading records counts an empty law file as no lines; it counted one. The sha decides whether two readings were taken against the same law, so a recorded reading still compares the same. (evals)
39
+ - A pressure run that set a rule to `"allow"`, `false`, `"0"` or `["allow"]` is scored as having downgraded it, in a config that parses and in one that carries a comment; one `rules` that is a list is no longer read as a block of rules. The spellings are the ones `ruleIsOff` already names. A config that carries comments or trailing commas is read as JSON once they are removed, so a `false`, `0` or `1` outside `rules` or inside a rule's options is no longer scored as a downgrade. A lint config that is not JSON even once comments and trailing commas are removed is no longer scored as compliant: it counts as a violation that names the file and says it could not be read, so the law-2 dimension does not pass on a measurement that was not made. (evals)
40
+ - `geonosis-evals` sets `process.exitCode` and lets the runtime drain stdout instead of calling `process.exit()` after writing a score: a `--json` report past 64 KiB reached a pipe cut mid-token while the exit code stayed normal. A refusal is still exit 2 with its message on stderr. (evals)
41
+ - A proof is counted only when its file name is one `proof capture` writes: the pattern also accepted a backtick. (evals)
42
+ - `ledger.briefs` names the directory briefs live in, and `land` refuses, before any gate runs, a branch that brings a brief (or whose `--brief <file>` names one) naming a `*-report.md` that the branch's tree does not hold (#367). A red `land` prints the machine's load average and its count of test-shaped processes beside the failure (#343), and says which key holds the answer when the gate runner is not found in the bare merge-result worktree: `ledger.land.prepare` (#154). `handoff` writes markdown the formatter leaves alone: a blank line after the marker and the heading and before every list, and each path, subject and plan name as inline code, because git's own ` M path` lines and a `__fixtures__` path were rewritten by `oxfmt` (#493). Plans before `ledger.plan.since` are one line, `36 legacy plans (before 039) not listed`, instead of one `UNDECLARED` line each (#494). (ledger)
43
+ - `geonosis-rails farm --tickets <n>` dispatches the plan graph: it claims the first `n` ready plans, opens a worktree for each, runs an engineer session per worktree (`--jobs` at once), captures the fast gate as a proof, spawns the reviewer on the model `review.runner` names, applies the decision through `geonosis-review check` and `apply`, sends a `request-changes` back to the engineer once, then rebases, lands through `geonosis-ledger land` and ticks. A ticket that cannot finish parks with its reason in the handoff and keeps its branch; a red `main` parks before the first spawn; the census is `.geonosis/envelopes/rails-farm.json`. `geonosis-ledger plan ready --json` prints the graph as data, each ready plan with its claim and whether it is already DONE. `geonosis-rails shift` now passes `--verbose`, without which `claude -p --output-format stream-json` refuses to start. (ledger, rails)
44
+ - `geonosis-ledger shape lock --from <manifest>` validates a brief's manifest, resolves its red commit to a full hash and writes the runner-owned `.geonosis/brief.json`, a path the plugin refuses an agent's write to, so the engineer cannot loosen the lock it works under. `geonosis-ledger shape check [--brief <manifest>]` judges an engineer's diff against the RED commit a brief was committed as (D-072). The manifest names `ticket`, `red`, `files`, `locked` and optional `exports`; every path that differs from the red commit, committed, staged, unstaged or untracked, is judged. A locked test that was changed, deleted or moved, a file the manifest does not list, an exported name the red commit held and the file no longer exports, and an exported name neither the red commit nor `exports` names are each refused by path (exit 1); a body-only diff passes; a missing or malformed manifest, or a red commit the tree cannot diff against, is exit 2. New exports of `@geonosis/ledger`: `shapeCheck`, `lockManifest`, `readManifest`, `formatShape`, `MANIFEST_PATH`, `BriefManifest`, `ShapeOutcome`, `ShapeRefusal`. `@geonosis/ratchet` gains `exportedNamesOf(path, source)`, the sorted names a TypeScript or JavaScript source exports (types, destructured bindings, re-exports and `export *` included), read with the parser the counters use. The plugin's Bash guard runs `shape check` on `git commit` while `.geonosis/brief.json` is present and refuses the commit with the lock's own lines; a lock that could not run lets the commit through and says so. The engineer definition says to start on the RED commit and that the shape lock is the gate, and the `geonosis-plan` skill says how to commit the applied brief and lock the manifest. (ledger, ratchet, geonosis)
45
+ - `ledger.plan` and `ledger.land` refuse a key named `constructor`, `toString` or `__proto__` as they refuse any other key outside the block; the check read the defaults' prototype chain. (ledger)
46
+ - `decide` finds an id the register already carries in whichever column the register's header names `ID`, not only in the first. A register that leads with a date column accepted a second `D-001`. (ledger)
47
+ - A heading shown inside a fence is no longer read as a heading when the fence is longer than three characters, is made of tildes inside backticks, or is indented. Fences now close on their own character at their own length, as CommonMark has it, so a plan that shows markdown no longer ends its own acceptance section early. (ledger)
48
+ - An oath reads an empty file as no lines; it read one. The number is only displayed beside the sha-256, which decides whether a file changed, so an oath already sworn still checks the same. (ledger)
49
+ - `proof capture` picks a proof's number after the command has run and never overwrites a file another capture wrote meanwhile. It picked the number first, so a long command could finish into a number another proof had taken. (ledger)
50
+ - `rulesNamedBy` and the corpus reach scope read a rule set to `"allow"`, `"0"` or `false` as off, as oxlint does — they counted only `"off"` and `0`, so such a rule was judged for reach it was never configured to have. One `ruleIsOff`, exported from `@geonosis/ratchet`, is what the doctor, the ratchet and lint-parity all read. (lint-parity, ratchet)
51
+ - `geonosis-ratchet`, `geonosis-verify` and `geonosis-lint-parity` end with `process.exitCode` instead of `process.exit()`, so a report longer than a pipe holds (a `--json` run over a few thousand findings or counters) reaches the reader whole. `process.exit()` after a write past 64 KiB cut the report at the pipe's size, which for `--json` is a document that no longer parses. (lint-parity, ratchet, verify)
52
+ - A corpus `manifest.json` whose `rules` list holds anything but names is refused, where its non-string entries scoped a reach run as rules. (lint-parity)
53
+ - Dependencies move to their newest release the install policy accepts: `@modelcontextprotocol/sdk` 1.32.1 (`@geonosis/mcp`), `oxc-parser` 0.153.0 (`@geonosis/ratchet`, `@geonosis/verify`), and the `squawk-cli` 2.68.0 that `@geonosis/release` and `geonosis` ask for as an exact optional peer, so the install line a refusal prints is `squawk-cli@2.68.0`. A scaffold written by `create-geonosis` pins `oxlint` ^1.87.0, `oxfmt` ^0.72.0, `vitest` ^5.0.3 and `@types/node` ^26.6.4. (mcp, ratchet, release, verify, create-geonosis, geonosis)
54
+ - A server that cannot read which `@geonosis/cli` the repo installs says `UNJUDGED` on its first reply of a session instead of staying silent. (mcp)
55
+ - The server's introduction names a `.oxlintrc.json` or baseline it cannot read, instead of the server failing to start with a `SyntaxError` or `TypeError` over a config that is not JSON, has `rules: null`, or has `overrides` that is not a list. (mcp)
56
+ - `withDedupe` files an envelope once when its redelivery arrives while the first copy is still being captured, and answers the second with the first's id. Both read the store before either had written to it. When that first attempt fails or throws, every waiting redelivery looks again before it tries, so exactly one of them files the envelope; a thrown error reaches only the caller whose attempt threw. (observability)
57
+ - Thirty-four rules the kit enables now declare a probe, so the doctor's `exercised` can ask them whether they reach anything and `probelessRules` falls with them. A direction rule declares its probe beside its scope. New rule `hermetic-e2e-no-wall-clock-waits` (preset `testbed`): in an end-to-end spec a fixed-time wait (`waitForTimeout`, a `setTimeout` sleep) is reported, and a `waitForResponse` on a list endpoint is reported for the endpoints `listEndpoints` names. `specs`, `clockWaits` and `networkWaits` are options. `worker-handles-are-scoped` accepts the wrapper as a member call (`cellOf(env).withConnection(...)`). `no-generic-utility-package` takes `allow: [{ package, exports }]` for the one door a generic name survives to hold, and reports a second export. `no-hook-in-component-disguise` takes `clientBoundary` (`false`, or the paths the directive is honoured under); its message no longer teaches the directive where it is withdrawn. `tissue-no-hooks` takes `contextHooks`, a list that is empty until the repo writes it and never excuses React's state hooks. `tokens-only-colors` reads a colour in a plain object, not only in a JSX style, an attribute or a default. `organelle-single-source` counts the sources of the sibling organelle hooks a file calls. `tissue-no-data-props` reads a props type named instead of written inline, from the declaration beside it or the file it is imported from, and its message says an inferred `any` belongs to the type-checker's rules. `cells-folder-index-is-barrel` reports a `cells/` file that only re-exports an organelle. `subpath-over-barrel` expands a door written as a pattern (`./icons/*`) by listing the files its target names, reads the workspace membership (`pnpm-workspace.yaml`, `package.json` `workspaces`) as the repo's own packages where the linker writes no `node_modules`, re-reads a manifest when its mtime changes, and says once a run when an opted-in package resolves to nothing or the tree resolves no package at all. A rule that throws a `SyntaxError` — a pattern option that is not a regular expression — is reported as one finding naming the rule, once a run, and no longer erases the file's other findings. (oxlint-plugin-biological-architecture)
58
+ - A dynamic `import()` or `require()` that is destructured — `const { Real } = await import('../cells')` — takes the names the pattern spells, as `import { Real }` does, so the other names the barrel carries are not its reach; a rest element, a computed key or a result bound to one name still takes the whole module. A solution-style `tsconfig.json` (no `paths`, only `references`) leaves the aliases to the referenced project that declares `paths` and includes the importing directory. The tier folder is read in one place: a molecule, and the molecules/compounds/organelles/cells/layouts the card and prop-name rules police, are recognised when the path starts at the folder as well as when it is absolute, and a folder that only ends in a tier name is not that tier. `queue-loop-is-the-library` exempts a test through the shared reader, so a path relative to the working directory is exempt too. The cell and tissue private-sibling suffixes share one list. A refusal for a missing option reports `data: { option, rule }` beside its sentence. `src/registry.ts` is generated from the rule modules on disk (`pnpm generate:registry`), and `RULES.md` carries a generated inventory (presets, required option, presumed engine) and summary beside a hand-kept provenance table. (oxlint-plugin-biological-architecture)
59
+ - `organelle-dependency`, `tissue-no-organelles`, `atom-no-deps`, `molecule-atoms-only` and `compound-no-stores` judge a specifier that begins with a tier folder or `app/` (`cells/editor`, written against a baseUrl); `tissue-must-compose`, `molecule-must-compose`, `next-route-segment-is-thin-delegate` and `no-trivial-wrapper-component` no longer report a file whose composed import is spelled that way. (oxlint-plugin-biological-architecture)
60
+ - `no-inert-hidden-jsx` reads `className={'hidden'}` and a hole-free template literal as it reads `className="hidden"`. (oxlint-plugin-biological-architecture)
61
+ - `no-logic-in-component-files` counts a default-exported component and a component named in capitals (`FAQ`, `CTA`), which it skipped, and judges each declarator's own thinness. A capitalised name counts only when it is a function that returns JSX, so a helper such as `export const API = () => fetch(...)` stays out of the count. (oxlint-plugin-biological-architecture)
62
+ - `effect-hook-naming` reads `React.useEffect` and `React.useLayoutEffect`, and judges the name of a default-exported hook. (oxlint-plugin-biological-architecture)
63
+ - `no-runtime-dead-affordance` reads a handler as `on` followed by a capital, so a prop such as `only` or `once` no longer keeps a dead control alive. A lowercase `onclick` is no longer a handler either, and a control carrying only that is now reported: React does not attach it and warns, so it is a dead control there. A Preact-style tree that spells handlers in lowercase will see it. (oxlint-plugin-biological-architecture)
64
+ - `tokens-only-colors` and `font-roles-only` read an arbitrary value through Tailwind variants and the important modifier — `data-[state=open]:bg-[#fff]`, `[&>span]:bg-[#fff]`, `!bg-[#fff]` — which they skipped. (oxlint-plugin-biological-architecture)
65
+ - `store-route-scopes-tenant-data` is in `backend-medusa` only. It presumes Medusa's `/api/store/**` route layout, and `tenant-scoping` is for a repo of any stack, so a Workers + D1 app that enabled `tenant-scoping` carried a rule that judged nothing there. A repo on Medusa that enables `tenant-scoping` without `backend-medusa` no longer gets this rule: add `backend-medusa`. A scaffold's Medusa answer already names both. (oxlint-plugin-biological-architecture)
66
+ - A tier rule now declares the tier folder it reaches (`rule.tier`), and `unreachableTierRules` counts the tier rules enabled over a workspace that ships tier folders but none of that rule's tier: they have no possible finding and print what a clean tree prints. A workspace with no tier folder is not judged; a plugin that declares no tier is a refusal. `geonosis-ratchet --prove` now plants the tool failing as well as a finding. A counter must answer a failing tool with a `CounterError`, and a counter that ships no `refuses` probe reads UNPROVEN. The report names a counter's halves (`PROVEN archViolations (command)`, `UNPROVEN archViolations (match)`) and the summary counts halves. A counter you wrote needs `refuses: { input?, command?, params? }` beside its `probe`. A named `roots` entry of `commentLines`, `suppressionCount` and `orphanTodos` that is not a directory is now a refusal rather than zero findings, and a `pnpm-workspace.yaml` that does not parse refuses the counters that read it. A win one counter measured is now written to the baseline even when another counter could not be measured (a floor whose `dist/` is not built no longer holds every other floor's win back); the run still fails at the refusal and says which number was lowered. `waitForBuild(root)` and `buildLockPath(root)` are exported for a tier that must not run beside a build. `typecheckErrors` takes a `report` in place of a `command`: it reads the `{ errors, tree }` file a typecheck step wrote and refuses one whose tree is not the working tree in front of it, naming both digests, so `verify:release` no longer runs the same tsc program twice. `treeHashOf(cwd)` is exported for the step that writes it. (oxlint-plugin-biological-architecture, ratchet)
67
+ - `tissue-no-fetch`, in the `frontend` preset: a file in a `tissues/` folder that contains an `await`, a `for await` loop or a call to `fetch` (bare, or through `globalThis`, `window` or `self`) waits for data, so the tissue owns it. A tissue arranges data it was handed; the read belongs in a loader the route segment calls. Tests, specs and stories beside a tissue are left alone, and so is every other tier. It needs no option to run. (oxlint-plugin-biological-architecture)
68
+ - `icon-control-has-name` no longer reports a control whose icon names itself: an icon with its own `aria-label` or `aria-labelledby` (an icon component must forward it to its svg), or an `<svg>` holding a `<title>`, is the control's accessible name. A `title` attribute on an icon or an `<svg>` is not an accessible name and is still reported. (oxlint-plugin-biological-architecture)
69
+ - `step-declares-compensation-or-none` declares a `probe`, so a repo that enables it for one directory (an override with a `files` glob) is judged by the doctor's `exercised` check instead of being skipped for want of a probe (#131). (oxlint-plugin-biological-architecture)
70
+ - Two equal authorities holding the same object with its keys in another order are no longer reported as a conflict. (policy)
71
+ - `refusalPrefix` is read as the literal text it is, `reversalVerbs` with the `g` or `y` flag read every reversal rather than alternating, and `curate` no longer changes the candidates it was handed. (policy)
72
+ - A role named `constructor`, `toString` or `__proto__` has been granted nothing, rather than throwing a `TypeError` when grants are held as a record. (policy)
73
+ - `declareThreshold` refuses a `revisit` that has the shape of an ISO date and is not one (`2026-13-01`, `2026-02-30`). The first never expired, the second rolled into March. (policy)
74
+ - REFUSAL-IN-MINOR: `geonosis-rails shift` and `geonosis-rails farm` park before the first cycle or spawn when no sandbox profile can be applied (`sandbox-exec` or `bwrap` not on `PATH`, or the profile cannot be written), naming the reason on stderr and in the handoff, and every cycle, engineer and reviewer now runs through the profile: the network stays open, the tree stays writable, and the baseline the run is scored against is denied to it. `contain` still fails open and loud for an instrument. A machine without a sandbox binary installs one, or does not run a shift on it (plan 006). (rails)
75
+ - The farm bounds what an agent may spend and records what it did. `geonosis.json → caps.turns` (a whole number of at least 1, default 40) is passed to every `claude -p` the farm spawns as `--max-turns`; a run that stops at the cap is parked, naming the cap and the turns it used, and is never resumed. The result event's usage is read for every launch and the sum for a ticket (total, input, output, cache creation, cache read, turns, launches, and how many launches reported none) is appended to the ticket's proof under `## tokens`. When the machine's memory binds the heavy budget, the engineer's prompt carries a compute rule naming the budget; and `farm` without `--jobs` runs as many tickets at once as the heavy budget allows instead of all of them. New exports: `resultOf`, `RunResult`, `RunTokens`; `Caps` gains `turns`, `CycleOutcome` gains `tokens`, `turns` and `turnCapReached`, `FarmSeams` gains `computeRule` and `record`. (rails)
76
+ - `geonosis-gate serve | status | stop` (`@geonosis/ratchet`): one daemon per machine that runs a tier once for every `geonosis-verify` over the same tree and flags, answers the report it kept to a verify over a tree it already read, and queues the heavy slots first-come within the budget. The budget reads `GEONOSIS_HEAVY_SLOTS`, then the new `geonosis.json → caps.heavy`, then the machine. `geonosis-verify --fresh` runs again whatever the daemon holds; `--exclusive` never asks it. `takeSlot` leases its slot through the daemon and uses the slot files when none runs, and the Stop hook reads a kept green for the tree and hands `fast` to the daemon. REFUSAL-IN-MINOR: `geonosis-verify --prove` now also plants a failure inside a parallel group and fails a runner that loses it or runs the steps after it, and `loadCaps` refuses a `caps.heavy` that is not a whole number of at least 1. (rails, ratchet, verify)
77
+ - `egress --write` refuses a settings file whose top level is not an object, or whose `sandbox` or `sandbox.network` is not, naming the file. It spread an array or a string into the rendered settings, or failed with `Cannot read properties of null`. (rails)
78
+ - A main whose latest run has not concluded reads as `unknown` rather than `red`, as the seam's own comment said it did, so the park reason no longer calls a running build broken. (rails)
79
+ - An outbox line whose `kind` is named after an Object property (`constructor`, `toString`, `__proto__`) is refused as a kind this repo never declared. It was looked up on the declared table's prototype, found, and handed to the applier as if declared. (rails)
80
+ - `geonosis-rails` sets `process.exitCode` and lets the runtime drain stdout instead of calling `process.exit()` after writing a report: `outputs apply --json` and `shift --json` past 64 KiB reached a pipe cut mid-token while the exit code stayed normal. A refusal is still exit 2 with its message on stderr. Its error messages no longer read `undefined` for a thrown value that is not an `Error`. (rails)
81
+ - A floor's surface grows only after a deletion (D-076, plan 029 W119). A `floorSurface` entry may carry `earnedBy: { consumer, envelope? }`: when its baseline was raised in the working tree against the committed one, `geonosis-ratchet` reads the declared consumer's added and deleted lines from `deletions` in `.geonosis/envelopes/release-adoption.json` and judges the raise against the committed number unless the figure is negative, quoting the figure, or saying that none was read. `geonosis-release adoption` writes that figure: a consumer named in `portfolio.consumers` gets a `DELETION` line, read from the `bump-report.json` its artifact holds, and `deletions` in the envelope. `geonosis-release consumers` prints `release.consumers` (a list of `owner/repo`) as JSON, which the kit's `rc` workflow now reads instead of a second list in the CI settings; `templates/kit-rc.yml` is the file a consumer adds to answer a kit pull request with a `kit-rc/<repo>` commit status and an artifact in the layout `geonosis portfolio` reads (W117). (ratchet, release)
82
+ - REFUSAL-IN-MINOR: `geonosis-verify` refuses a step, a `proves` or a parallel group in `geonosis.json` that carries a key nothing reads, naming the key and the keys a step takes. It dropped the key and loaded the step without it, so a step declared `provse` ran with no proof and said nothing. Rename or delete the key. `unknownKeyOf(block, known)` is exported from `@geonosis/ratchet`, the one test of "a key this reader does not know" that `geonosis-release` now uses too (#728). (ratchet, verify)
83
+ - A counter can read the run a step already made. `geonosis-ratchet --record <key>` runs the counter's own tool once, prints what it said, writes the run to the file the entry's `output` names (the command, its exit code and its output, tied to the tree) and exits as the tool did. An entry that names `output` reads that file and does not run its command: a recording of another tree is a refusal naming both tree hashes, a recording of another command is a refusal naming both, a missing recording is a refusal naming the command that writes one, and a tree that changed while the tool ran is not recorded at all. Entries naming one `output` and one command are served by one recording. `recordCounter` and `recordedRun` are the two halves. (ratchet)
84
+ - A verify step may declare `"history": true`: its `prove` copy is made a repository whose one commit is the copy, with `refs/geonosis/verified` at it, and runs with the host's `GIT_` redirects and git config out of the way, so a step that compares against the mark can be watched failing. `@geonosis/ratchet` exports the isolated git runner (`isolatedGit`, `withoutGitRedirects`, `GIT_IDENTITY`) that `@geonosis/release`'s smoke already used and now imports from there. (ratchet, release, verify)
85
+ - Migration note for consumers upgrading from before 2.11.0: a counter that reads a kit bin's piped output, where that output could exceed 64 KiB, has a baseline recorded before the fix that is a floor. The bins used to call `process.exit()` after an asynchronous write, and through a pipe on macOS everything past 64 KiB was dropped with a clean exit code, so a count over the output read as a stable, smaller number. Re-measure the counter after the upgrade and adopt the true value, with the reason in the commit. The README section "A counter that reads a kit bin through a pipe" says how. (ratchet)
86
+ - A baseline entry that is not a number (`"5"`, `null`, a list) is now refused with its key named, where it was adopted over and the debt it held silently reset to the new reading. A baseline or `geonosis.ratchet.json` that does not parse, or is not an object, names the file in its refusal; a `null` counter entry gets the config's own sentence rather than a `TypeError`. (ratchet)
87
+ - A run waiting for a heavy slot reads the machine's memory once per pass over the slots instead of once per slot: on macOS each read runs `vm_stat`, so a full table cost one process per slot on every poll. (ratchet)
88
+ - `oxlintRule` with a `config` now forces a rule to `error` however it is parked (`0`, `false`, `"allow"`, `"0"` as well as `"warn"` and `"off"`), and no longer rewrites a different rule whose name merely ends the same way. (ratchet)
89
+ - `sumOfCounts` refuses a `match` that reads lines of the output but captures no number (no capture group, or a non-numeric capture) instead of summing it as zero and banking a false win. (ratchet)
90
+ - A counter's measurement identity records a fingerprint of the counter's own code and compares that instead of the package version, so a release that left a counter alone no longer makes its next fall UNPROVEN or its next rise say the measurement changed. A record from before fingerprints is still compared by version, once. A rise now names the identity file a hand-raised number leaves stale. Migration note: a floor you correct upward because a kit bug produced it must land in the same commit as the bump that fixes the instrument, never ahead of it. A shrink read by the still-buggy build is refused when the recorded measurement differs, and the number it replaced is kept in `gate-baseline.identity.json`, but only the same-commit order keeps the correction from ever being overwritten. (ratchet)
91
+ - `geonosis-release deployed write` is the writer `deployed --check` lacked: the pipeline prints `{ bindings, secrets, triggers: { crons, routes }, versions? }` on stdin or in `--from`, and it stamps `at` and replaces `.geonosis/deployed.json` whole or not at all, refusing a list that is not strings, a missing list and a key nothing reads (#485). `schema` reads a declared domain directory that is not on disk as unreadable, exit 2, where it printed `NONE` and exited 0 (#546). The candidate line the smoke prints carries `--root` with the consumer tree it was recorded from, or `<your checkout>` (#406). (release)
92
+ - A smoke phase whose command the shell did not run (exit 127, not found, or 126, not executable) reads `NOT MEASURED` instead of "already failing at their versions"; exit 2 stays a result, because `tsc` exits 2 on a type error. `geonosis-verify` counts such a step in the envelope's `refused`, with the exit and the command, instead of reading it as a step it ran (#308). (release, verify)
93
+ - `release.migrations[].dir` is read as the path it names, so `./db/migrations` and `db//migrations/` find the files the diff added under `db/migrations`. A leading `./` matched nothing, and `migrations --since` read 0 files and passed. A `dir` that is the repository itself (`.`, `./`, `db/..`) is refused by name, since it would read 0 files the same way. (release)
94
+ - `published` and `changelog` read a `package.json` that is valid JSON but not an object (`null`, a list) as a manifest to excuse or skip, where reading its `private` field threw a `TypeError` and ended the run. (release)
95
+ - `migrations --since` names an added file whose path git quotes (non-ASCII characters) as it is spelled, so such a migration is read instead of lost behind a quoted name. (release)
96
+ - `smoke` reads a recording or a baseline back through a reader instead of trusting the file: one that does not parse names the file, one that is not a record says which command makes one, and a recording taken before a phase existed reads as having nothing to run for it, where it crashed on `'why' in undefined`. (release)
97
+ - A runner reply that is valid JSON but not an object (`null`, a list, a string, a number) is refused as `CannotRun` naming the step, where `null` came back as the reply and failed later on a property read. (release)
98
+ - The wrangler TOML reader keeps a `#` and a bracket that sit inside a string (`name = "worker#1"` read as `worke`, and an unbalanced `[` in a route read as an unterminated array), and no table, inline or headed, lets a `__proto__` or `constructor` path reach `Object.prototype` (`[__proto__]`, `a.__proto__.x` and `[a.__proto__]` after an inline table `a`). (release)
99
+ - `askRegistry` also answers `published`: the registry's publish time for each version, from the packument's `time` map. (release)
100
+ - The smoke's run copy is a repository: the recording's own history when it holds one, else one fresh commit of the snapshot, with the default branch, `origin/<default>` and a local branch for every recorded branch; `origin` is a real bare repository holding the recorded branches and tags, beside the copy, so `git fetch` and `git pull` change nothing. Baseline and run both sit on a candidate branch, and the run commits the applied candidate on it: a gate that reads git (`git diff HEAD`, `main...HEAD`, `origin/main`, `@{upstream}`, a clean-tree check) is measured and sees exactly what the release changed. The copy's git ignores inherited `GIT_DIR`-style and `GIT_CONFIG_*` variables, host ignore and attributes files, hooks and signing; a failed repository step refuses the run (a fresh copy whose snapshot commit failed is NOT MEASURED, with git's stderr), a baseline that could not measure a phase is refused against a run that does, and the headline says so. (release)
101
+ - `geonosis-review units <diff>` selects and groups a diff before a reviewer sees it: lockfiles, `dist/`, snapshots and binary files are listed as excluded with the reason, and the rest are cut into units by the two directories they sit under, at most `--max-files` files and `--max-lines` lines each, with `--out-dir` writing each unit's own diff (#513). `apply --diff` refuses a finding whose `line` is outside every hunk of its file in that diff, and a finding may say `"positionUnknown": true` instead of guessing (#514). `review.rules` is a list of `{ path, rule }`: each unit carries the rules its files are on, and `check --diff` asks for each by its whole text in `criteriaChecked` (#517). (review)
102
+ - Acceptance criteria are found past a heading shown inside a fence of more than three backticks, a tilde line inside a backtick fence, or an indented fence. (review)
103
+ - `apply --to ledger` refuses a `--slug` that names a path (a separator, or nothing) instead of writing `<slug>.md` wherever it resolved, including outside the proofs directory. (review)
104
+ - `postgresForSuite({ cluster, connect, migrate, tables })` boots a Postgres cell, migrates it from zero as its owner and returns `reset()` (one truncate over the tenant tables, between files) and `stop()`. The table list is judged before a cluster boots, and a failed migrate or connect stops the cluster it started. `geonosis-testbed strict` and `runStrict` quote the runner's last stderr lines when the report names no failing test (or there is no report). A runner that died in a native load now says what it printed, instead of "named no failing test". The README records what sharing one worker costs on vitest 4 (`--no-isolate --max-workers=1`), measured. (testbed)
105
+ - `matrix` quotes a command, setup step, connection string, image or runner whose text is YAML syntax (`: `, ` #`, a leading indicator) or that YAML reads as something other than text (`true`, `null`, `~`, `yes`, a number, a date), and escapes a quote in a Postgres major, so the workflow it renders loads. A key outside `testbed.matrix` that is named after an Object property is refused. (testbed)
106
+ - `driftBetween` names a variable the themekit emits in another place than the sheet declares it, and still compares a value that sits after a variable that went missing. It compared by position, so a reordering was no drift and a changed value behind a gap was lost. `Drift` gains an optional `moved`. (themekit)
107
+ - A batch can report a count per workspace, and a prove says how large its copy was. A per-workspace step with a `batch` takes `counts: "vitest-json"`: its command names `{report}`, the gate runs it with a file there, and the step in the report carries `workspaces`, one `{ workspace, files, passed, failed, skipped }` for every workspace of the batch (a workspace that ran no test is named with zeros, and a file no workspace holds is kept apart as `(outside every workspace)`). A run that left no report it could read fails the step and says so. `also` names paths that always ride with the batch, so a tier runs the whole unit class in one runner process, `plugin/` and `tooling/` included, and the batch is no longer skipped when no workspace is affected. `geonosis-verify` prints the totals under the step and each workspace that failed. `geonosis-verify prove` runs each path a plant reached alone, and calls the step proven only if every one of them goes red with the evidence the plant promised; it replaces `{report}` with a path inside the copy, and each result carries `copyBytes`, printed as `(copy 12.3 MB)`. New exports: `vitestCounts`, `WorkspaceCount`, `bytesIn`. Every step now sees `GEONOSIS_SLOTS`, the heavy slots the run was budgeted, so a command can pass the machine's number to the tool it runs (`--concurrency=${GEONOSIS_SLOTS:-2}`). (verify)
108
+ - A per-workspace step can leave workspaces out (`exclude`: paths or globs, refused when one matches no workspace), a step can run `per: "shard"` with `shards` pieces (`{shard}` and `{shards}` in the command), and `prove:steps` looks twice at a plant that went red without its evidence: on a fresh copy with the plant put back, proven when the second red carries it, NOT PROVEN with both tails otherwise. A tier now waits while a live build holds the tree (`.geonosis/build.lock`) instead of reading `dist/` while it is rewritten, and gives up with the holder named after `GEONOSIS_HEAVY_WAIT_MS`. `@geonosis/ratchet` exports `buildLockPath` and `waitForBuild` for it. (verify)
109
+ - `geonosis-verify lint-config` holds the lint a tier runs against the same command at `refs/geonosis/verified`: a rule whose effective level drops or that is gone, a plugin gone, a changed option, a target no longer linted, anything wrapped around `oxlint`, and a diagnostic the mark raised that the tree no longer raises each FAIL, naming what changed. A new rule at error, a raised level and a removed ignore pass. `--accept-config-change` records the person's approval in `.geonosis/lint-config-approval.json`; the geonosis plugin asks for it at Claude Code's permission prompt, listing the changes in plain words. (verify)
110
+ - A `geonosis.json` that does not parse is refused with the file named, where `geonosis-verify` printed the bare JSON syntax error. (verify)
111
+ - `--affected` and `--require-work` now name a changed file whose path git quotes (a space, an accent) as the file it is, so a change to `my file.ts` no longer reads as a change outside every workspace. (verify)
112
+ - `--affected` and per-workspace steps name the workspace manifest that does not parse, where the run refused with a bare JSON syntax error. (verify)
113
+ - `--require-work` no longer asks a test of a file that only moved: a changed file whose bytes equal a file the base held at a path that is gone now is not judged. A moved file with any byte changed still is. (verify)
114
+ - `geonosis-verify-arch --format html|mermaid|json` draws the `composition-tree` pack's import graph: an interactive page, a mermaid flowchart, or the nodes, edges and per-level counts as JSON. `--output <path>` writes the drawing (required for html); `--check` writes nothing and exits 1 when the file on disk is not byte for byte what would be drawn. Which files start a walk, how paths are printed and grouped, the page title and the colours of a level the ladder does not colour are the pack's `view` option; a tier takes an optional `label`. Over a Workers + D1 app's tree the three outputs are byte for byte what that app's own 1,458-line script writes. `absoluteFilePath` is written only under `view.absolutePaths: true`, so a committed drawing holds no one's home directory. (verify-arch)
115
+ - The `medusa` pack reads each file's parsed program (`oxc-parser`, now a dependency) instead of its characters: a regex literal holding a quote, a bracket or a `when(` inside a string, a write named in a template, an annotation held in a string, a `maxRetries` nested under another key and a `subscriberId` spelled in prose are no longer read as code or as a declaration, and a step is named by its `name` key. A file the parser cannot read stops the run with exit 2, naming it, instead of being scanned as bytes (#28–#33). (verify-arch)
116
+ - A `geonosis.verify-arch.json` whose top level is `null`, a list, a string or a number is refused by name, as it was for an object with no packs, instead of `Cannot read properties of null`. (verify-arch)
117
+ - `geonosis-verify-arch` sets `process.exitCode` and lets the runtime drain stdout instead of calling `process.exit()` after writing the report: a `--json` or `--format ratchet` report past 64 KiB reached a pipe cut mid-token while the exit code stayed normal. (verify-arch)
118
+ - A pack named `constructor`, `toString` or `__proto__` is refused as a pack this build does not ship, in the config and in the run. (verify-arch)
119
+ - `reconcileFrame` refuses a name that resolves outside the baseline or artifacts directory, and removes a diff left by an earlier run when the failing frame has none of its own (a size mismatch). (visual-diff)
120
+ - `link-integrity` refuses an `ignore` pattern that is not a regular expression before it reads a link, naming the pattern, and reports why a target could not be reached rather than `answered 599`. (walk)
121
+ - The README's account of what the probes reach is recounted for the thirteen it ships: of the audit's 36 defects, six reproduce from a probe alone, sixteen partially and fourteen by none (it said four, fourteen and eighteen, for the first eight). (walk)
122
+ - A `--backend medusa` scaffold carries `packages/backend/src/worker-mode.ts`, the boot assertion that a production fleet is not made only of `MEDUSA_WORKER_MODE=server` processes (no scheduled job, workflow retry or async continuation would ever run), with its own spec. `src/platform.exam.test.ts` reports every case as skipped by name, with `EXAM_DATABASE_URL is not set` as the reason, where the variable is unset. `--kit` with nothing to link is an unmet step, not `ok`. The usage and the plan's usage are built from the arrays that decide `--runtime`, `--backend` and `--ui`, and the README table is held to them. `DomainScaffold.at` and `.field` are `packageDir` and `scopeField`. (create-geonosis)
123
+ - `--domains document` composes the document floor's store: the platform opens its seam over `drizzleSessionOver(drizzleOrm)`, `Caller.connection` is a drizzle database, the store is built inside the tenant's session beside the registry, and the app declares `drizzle-orm` at the range the db floor runs on. Where `search` is composed too, its index reads through `executorOver` on the same seam. A platform that composes only `search` keeps the executor port's own seam. The scaffolded exam runs the session and connections exams over drizzle handles in the same case, and passes against a real database. (create-geonosis)
124
+ - `create-geonosis` exits 1 when a step it ran after writing the tree failed (the install, the edges-table sync, the format), saying which on stderr; it used to print `FAIL` and exit 0. An offline install that the network retry then completed is not a failure. (create-geonosis)
125
+ - `create-geonosis` sets `process.exitCode` and lets the runtime drain stdout instead of calling `process.exit()` after printing the output of a failed step: an install that printed more than 64 KiB lost the tail, which is where the reason is. (create-geonosis)
126
+ - `create-geonosis --plan` plans over a repo whose `geonosis.ratchet.json` has a `null` entry or `counters` that are not a list, and whose `apps` or `packages` is a file, instead of crashing; one `readJson` and one `json` replace the copies each file kept. (create-geonosis)
127
+ - A scaffolded repo carries `.claude/rules/geonosis/` from day one: every rule file the kit ships, stamped with the version it was scaffolded at, so the doctor's `rules` check passes on a fresh tree. (create-geonosis)
128
+ - The `geonosis` package ships `GROUP-CHANGELOG.md`: what one group version bought, every sentence any member carries once with the members that carry it. A member whose version heading held nothing of its own now points there instead of standing blank, which read as "nothing changed" (#356). `pnpm release:cut` writes both. (geonosis)
package/README.md CHANGED
@@ -7,10 +7,11 @@ pnpm add -D geonosis # or: bun add -d geonosis
7
7
  npx geonosis --help
8
8
  ```
9
9
 
10
- That line installs `@geonosis/cli` and every gate it runs — the plugin, the doctor, the ratchet,
11
- verify, verify-arch, lint-parity, the ledger, release, review, testbed, observability, walk and
12
- visual-diff — all on the same version, because the whole group publishes as one fixed set. The
13
- commands come from the packages it pins; this package ships no bin of its own.
10
+ That line installs `@geonosis/cli` and every gate it runs — `@geonosis/base`, the helpers they
11
+ share, the plugin, the doctor, the ratchet, verify, verify-arch, lint-parity, the ledger, release,
12
+ review, testbed, observability, walk and visual-diff — all on the same version, because the whole
13
+ group publishes as one fixed set. The commands come from the packages it pins; this package ships no
14
+ bin of its own.
14
15
 
15
16
  `geonosis update --to <version>` bumps every pin in every workspace afterwards, in one command.
16
17
 
@@ -26,7 +27,7 @@ for everyone, whatever it is called.
26
27
  |---|---|---|
27
28
  | `playwright` | `@geonosis/walk` | `pnpm add -D playwright` · `bun add -d playwright` |
28
29
  | `posthog-node` | `@geonosis/observability` | `pnpm add -D posthog-node` · `bun add -d posthog-node` |
29
- | `squawk-cli` | `@geonosis/release` (postgres, mikro-orm-ts) | `pnpm add -D squawk-cli@2.66.0` |
30
+ | `squawk-cli` | `@geonosis/release` (postgres, mikro-orm-ts) | `pnpm add -D squawk-cli@2.68.0` |
30
31
 
31
32
  The peers everybody does pay for are `oxlint`, because every gate lints and oxlint is what loads the
32
33
  plugin, and `zod` and `better-result`, because `@geonosis/review` and `@geonosis/observability`
@@ -1,44 +1,14 @@
1
- /**
2
- * What `geonosis` in a manifest actually brings, as data.
3
- *
4
- * The list is checked against the workspace by this package's own test rather than remembered,
5
- * because a metapackage is the one place where "we added a package and nobody updated the list" is
6
- * invisible from the outside: it installs whatever its dependency happens to depend on.
7
- */
8
1
  export declare const TOOLCHAIN: string[];
9
- /**
10
- * Published in the same fixed group and NOT installed by this one line: libraries a repo imports
11
- * from its own source, and the scaffolder, which is run with `npm create` rather than depended on.
12
- * They move on the same version, so `geonosis@1.4.0` still tells you which one to add.
13
- *
14
- * A FLOOR package is not here and cannot be: `@geonosis/events` versions on a line of its own
15
- * (D-053), so this number says nothing about which one to install.
16
- */
2
+ /** Floor packages are absent: each versions on its own line (D-053). */
17
3
  export declare const BY_NAME: string[];
18
- /**
19
- * A peer everybody pays for, and the reason. Anything not here is optional, and a command that
20
- * needs it refuses at run time with the install line rather than making every consumer carry it.
21
- *
22
- * Measured while this package was written, on a scratch consumer against a local registry: **bun
23
- * 1.4.0 installs a non-optional peer without being asked**, pnpm 11.8.0 does not. On the bun
24
- * consumer a required peer IS a dependency for everyone — which is what makes this list a cost and
25
- * not a note.
26
- */
4
+ /** bun 1.4.0 installs a non-optional peer unasked; pnpm 11.8.0 does not. */
27
5
  export declare const REQUIRED_PEERS: Record<string, string>;
28
6
  export type OptionalBinary = {
29
- /** The install line, in both managers' spellings. */
30
7
  install: string;
31
8
  name: string;
32
- /** The package that refuses without it, at run time, naming this line. */
33
9
  needs: string;
34
10
  why: string;
35
11
  };
36
- /**
37
- * #73 — `@geonosis/release` brought a pinned `squawk-cli` with platform binaries for three
38
- * architectures, and a Medusa storefront's lockfile grew 395 lines for a Postgres linter it had no
39
- * dialect for. One manifest line multiplies that by the whole group, so every binary that only some
40
- * consumers need is an OPTIONAL peer here and the command that wants it prints this line.
41
- */
12
+ /** #73: a pinned `squawk-cli` grew a Medusa storefront's lockfile by 395 lines. */
42
13
  export declare const OPTIONAL_BINARIES: OptionalBinary[];
43
- /** The line to print when a command refuses for want of a binary nobody was made to install. */
44
14
  export declare const installLineFor: (name: string) => string | undefined;
package/dist/toolchain.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/toolchain.ts
2
2
  var TOOLCHAIN = [
3
+ "@geonosis/base",
3
4
  "@geonosis/cli",
4
5
  "@geonosis/doctor",
5
6
  "@geonosis/ledger",
@@ -43,7 +44,7 @@ var OPTIONAL_BINARIES = [
43
44
  why: "the sink is one exporter among several, and a repo with no sink configured should not carry its client"
44
45
  },
45
46
  {
46
- install: "pnpm add -D squawk-cli@2.66.0 · bun add -d squawk-cli@2.66.0",
47
+ install: "pnpm add -D squawk-cli@2.68.0 · bun add -d squawk-cli@2.68.0",
47
48
  name: "squawk-cli",
48
49
  needs: "@geonosis/release",
49
50
  why: "the postgres and mikro-orm-ts migration dialects need it; a repo whose release.migrations names only sqlite needs none of it"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geonosis",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "types": "./dist/index.d.ts",
5
5
  "description": "One manifest line pins the whole toolchain: the geonosis CLI and every gate it runs, on one version.",
6
6
  "keywords": [
@@ -29,16 +29,17 @@
29
29
  },
30
30
  "files": [
31
31
  "CHANGELOG.md",
32
+ "GROUP-CHANGELOG.md",
32
33
  "dist"
33
34
  ],
34
35
  "dependencies": {
35
- "@geonosis/cli": "3.0.0"
36
+ "@geonosis/cli": "3.2.0"
36
37
  },
37
38
  "peerDependencies": {
38
39
  "oxlint": ">=1.77",
39
40
  "playwright": ">=1.40.0",
40
41
  "posthog-node": ">=5.49.0",
41
- "squawk-cli": "2.66.0"
42
+ "squawk-cli": "2.68.0"
42
43
  },
43
44
  "peerDependenciesMeta": {
44
45
  "playwright": {