import { type Release } from '@geonosis/release'; import { type ReadFinding } from './doctor-checks.js'; import { type LawLine } from './law-lines.js'; import { type LockMoves, type SnapshotChange } from './lockfile.js'; import { type Manager } from './manager.js'; import { type ReplacedDep } from './replaced.js'; import { type SeamMovement } from './seams.js'; import { type YoungArrival } from './third-party.js'; import type { CommandResult } from './types.js'; import { type ByHandLint, type LintReport } from './update-lint.js'; import { type Say } from './update-progress.js'; /** A prefix cannot find them. */ export declare const UNSCOPED: string[]; export type Dep = { at: string; block: string; dir: string; name: string; spec: string; }; export type FamilyOptions = { extra?: string[]; /** Defaults to the fixed group: a floor versions on its own line (D-053), so `--to 1.5.0` says nothing about it. */ group?: readonly string[]; scope?: string; }; export declare const familyDepsIn: (root: string, options?: FamilyOptions) => Dep[]; /** Returned, not dropped: repinning a floor to the group's number names a version its line never published (#148), but ignoring it silently leaves a consumer wondering. */ export declare const outsideGroupIn: (root: string, options?: FamilyOptions) => Dep[]; /** The whole `node_modules`, never the root's. oxlint resolves its plugin from the config's directory, so a nested copy runs while the manifests say otherwise. pnpm 11.8.0: after removing only the scope directory, `pnpm install`, `--force` and a state-deleted install all print "Already up to date" over the missing package. */ export declare const purgeNested: (root: string, options?: FamilyOptions) => string[]; export type Missing = { name: string; why: string; }; /** Three buckets: a name npm has never heard of (typo) and a name published without this version (own line) have different answers outside the group. */ export declare const resolveTargets: ({ names, registry, to }: { names: string[]; registry: string; to: string; }) => Promise<{ absent: Missing[]; missing: Missing[]; releases: Release[]; unreachable: Missing[]; }>; export type Pin = { dep: Dep; to: string; }; export declare const retarget: ({ deps, to }: { deps: Dep[]; to: string; }) => string[]; export declare const STEP_NAMES: readonly ['build', 'doctor', 'install', 'lint', 'lock', 'post-update', 'purge', 'repin', 'resolve', 'verify']; export type StepName = (typeof STEP_NAMES)[number]; export declare const REPORT_FILE = ".geonosis/bump-report.json"; /** `ran` and `ok` are separate: a step that never happened did not pass (#233). */ export type Step = { command?: string; detail: string; durationMs?: number; ok: boolean; ran: boolean; resumed?: string; step: StepName; }; export type From = { manifests: string[]; version: string; }; export type ByHandRule = { config: string; option: string; rule: string; }; /** #268: the changeset text is what the author wrote for the person holding the bump, and stayed in a tarball nobody opens. */ export type ByHandChange = { change: string; package: string; version: string; }; export type ByHandFinding = ReadFinding; export type ByHand = ByHandChange | ByHandFinding | ByHandLint | ByHandRule | LawLine | ReplacedDep; export type BumpReport = { at: string; byHand: ByHand[]; dependencyOnly?: ByHandChange[]; /** Absent when this run resolved against a registry, so the next `--registry` run removes exactly these and no override of the consumer's. */ candidateOverrides?: { manager: Manager; names: string[]; }; from: From[]; behind?: string[]; downgrades?: string[]; leftAlone: string[]; lint?: LintReport; lockMoves?: LockMoves; lockSplits?: SnapshotChange[]; doctorBefore?: string; timedOut?: { passed: StepName[]; resumes: boolean; step: StepName; }; young?: { gate: string; unasked: string[]; young: YoungArrival[]; }; manifests: string[]; moved: string[]; notes?: string; seams?: SeamMovement; durationMs: number; ok: boolean; purged: string[]; registry: string; runtime: Manager; skipped: StepName[]; steps: Step[]; to: string; unchanged: string[]; }; export type UpdateInput = { /** Falls back to the registry for a package the directory lacks; refused otherwise so an RC adoption never mixes with it. */ alsoNpm?: boolean; cwd: string; dryRun?: boolean; extra?: string[]; floors?: string; floorPins?: string[]; home?: string; installArgs?: string; npmRegistry?: string; registry?: string; root?: string; runtime?: Manager; scope?: string; skip?: StepName[]; to?: string; unknownFlags?: string[]; fresh?: boolean; progress?: Say; verbose?: boolean; }; export declare const UPDATE_USAGE = "geonosis update --to [--floors latest] [--floor @]...\n [--install-args=] [--root ] [--registry ]\n [--also-npm] [--npm-registry ]\n [--runtime bun|npm|pnpm|yarn] [--dry-run] [--fresh] [--verbose] [--prove [--skip ]...]\n\nRun it from anywhere inside the repo: without --root it acts on the root, the nearest directory\nabove holding pnpm-workspace.yaml or a package.json with \"workspaces\" (failing those, a lockfile),\nand prints `workspace root: ` when that is not where it was run. The search stops at the top\nof the git repository; with nothing found and no --runtime it refuses, naming where it looked.\n\nThe bump ritual, in one command, in the order that makes it safe:\n\n 1 resolve EVERY target version against the registry, before writing anything \u2014 one missing\n refuses the whole bump, because a manifest naming a version that does not exist breaks every\n later install until somebody hand-edits it (#148, measured on bun 1.4.0)\n 2 rewrite every manifest in every workspace that names a @geonosis package\n 3 purge every nested node_modules/@geonosis \u2014 the copy oxlint actually loads\n 4 install with the manager the lockfile names\n 5 install again with a frozen lockfile: the lock proof\n 6 the `build` tier \u2014 or the root `build` script \u2014 but ONLY when the lockfile moved packages\n this bump did not repin; the report names them either way\n 7 geonosis doctor --only loaded,group[,release]: what the tree declares is what resolution finds, the kit's packages are on one version, and, where geonosis.json declares a release, the release runner has what it needs. The same checks run once before step 2 with the copy installed then; a WARN or FAIL the second run has and the first did not, told by check and subject, is a BY HAND item naming the check and its message (#198)\n 8 geonosis post-update, run by the copy just installed and not by the copy running this: it\n writes .claude/rules/geonosis with the rule files of the version this bump moved to, checks\n them the way the doctor does, and prints that version's group release notes since the one you\n came from, naming the entries marked BY HAND. An updater of 3.3.0 or later hands this to the\n new version, so a step a later release adds reaches the repo; one of 3.2.0 or older ran its\n own steps, and geonosis doctor warns until `geonosis post-update --from ` has run. A\n version with no post-update is asked for `geonosis rules`; one with neither has no step to\n run\n 9 the tier this tree calls `fast` in geonosis.json, so a bump cannot report PASS over a tree\n it has just reddened; a repo that declares none is told so\n 10 when the bump moves the group, and with it @geonosis/oxlint-plugin-biological-architecture\n whether a manifest here names it or a member brings it in: oxlint over each oxlint config\n that loads it (one a lint command names with -c, or a .oxlintrc.json, .oxlintrc.jsonc,\n oxlint.config.ts or oxlint.config.mts), counted before the repin and again after the\n install. Errors the\n new plugin reports that the old one did not FAIL the update and are a BY HAND item naming the\n count and the rules; a repeat run of the same bump keeps the count from the first\n\nStep 6 exists because a repin of one package can prune another's lockfile entries \u2014 fifteen down to\nnine \u2014 and kill a hoist the build depended on, while every install afterwards answers \"already up\nto date\" over an empty directory. `node_modules/.pnpm-workspace-state-v1.json` is the file that\ndecides whether pnpm relinks at all, which is why `--force` and deleting `.modules.yaml` change\nnothing there.\n\nStep 4 runs with the consumer's own lifecycle scripts ON \u2014 that install is the thing under test, so\na repo whose `prepare` refuses the tree it is in fails there with every manifest already rewritten,\nand the step names the script it died in. Step 5 proves the LOCK and nothing else, so it runs with\n`--ignore-scripts`: the scripts already ran once, and a root `prepare` that installs git hooks\nrefuses a git worktree, which is exactly where a bump happens. --install-args= is handed to\nboth of them word for word, and a failed install prints what was left behind, the command to finish\nit by hand, and \u2014 when a moved floor left the lockfile stale \u2014 which entries to rewrite in place.\n\n--to is a claim about the fixed group only. A floor package versions on a line of its own, so\n--floors latest moves each one this tree declares to the newest ITS line published, and\n--floor @ moves one to a version you name; both are resolved with everything else at step 1.\n--to may be left out when --floors or --floor is given: the group stays at the one version every\nmanifest here carries, the floors move, and a group split across versions is refused for --to to settle.\nA floor moved to an older version, and an own-line package left behind its line, are named in the output.\n\nA dependency on a package the kit renamed (the pairs are in the release-renames.json the target\n@geonosis/cli ships) is named as a BY HAND item with the new name and the version the release records\nfor it: the dependency and every import specifier are yours to change. A package moved under a subpath\nof another (@geonosis/-ui into @geonosis/design-kit/-ui) names the package to depend on and\nthe import prefix to rewrite.\n\nUnder a release-age cooldown (pnpm minimumReleaseAge, bun minimumReleaseAge) it stops before writing when\na kit package is younger than the age, and prints the exemption for the manager: pnpm\nminimumReleaseAgeExclude accepts 'geonosis' and '@geonosis/*', bun minimumReleaseAgeExcludes takes exact\nnames only, and npm has no exemption (it is refused above, with the commands). When --install-args\npasses the manager's override, nothing is held back: after the install, each third-party version the\nlockfile gained that is younger than the age is listed as a young line; the versions of one release\n(the same version from the same repository, as the registry names it) are one line naming the family, and --verbose\nlists each package. .geonosis/bump-report.json holds every one under young.\n\nThe design-kit (@geonosis/design-kit, on the kits floor) moves WITHOUT either flag, to the version the\ntarget release records in the release-kits.json its @geonosis/cli was published with \u2014 not to the\nnewest its own line has. A release that records none leaves it where it is, and says so.\n\nThe manager is the one the lockfile names: bun.lock or bun.lockb, pnpm-lock.yaml, or a yarn 1 yarn.lock\n(read with @yarnpkg/lockfile). A package-lock.json or a Yarn 2+ yarn.lock is refused with exit 2 before a\nbyte is written, and the refusal prints the exact commands a consumer of that manager runs instead. A\nyarn.lock holding neither yarn 1's header nor a __metadata: block (an empty one) is refused as that,\nwith `yarn install` as the next step.\n\n--registry \u2014 a directory `pnpm pack` / `geonosis release smoke` produced \u2014 resolves like a\nregistry for every package it holds, read off each tarball's own package.json, and repins it as\nfile:; a declared package the directory does not hold is refused UNLESS --also-npm\nsays to resolve it against the registry too \u2014 an RC adoption must not silently mix a candidate with\nit. --npm-registry is what --also-npm falls back to, in place of the real registry.\n\nA run that stops at a later step (a verify that timed out under load) leaves the earlier ones recorded\ngreen over the tree they left, as geonosis verify records a tier: running the same command again\nresumes after the latest step whose record matches the tree, carrying their lines and the doctor's\nBY HAND items from the last report. --fresh runs every step again. The record needs a git commit.\n\nIt writes .geonosis/bump-report.json and prints a commit body \u2014 including the BY HAND blocks: every\nrule this release judges nothing with until it has an option, and every change the floors this bump\ncrossed name in their own changelogs. Neither is a thing a command can do for you. --prove runs the whole thing over a\nscratch consumer this command builds, on every package manager it can find, with a nested stale copy\nplanted for the purge to remove and a missing version planted for the resolve to refuse. A manager that is not on this machine makes --prove FAIL, because its half of every claim is\nunmeasured; --skip says the caller means to prove without it."; export declare const said: (runtime: Manager, { extra, frozen }: { extra: string[]; frozen: boolean; }) => string; export declare const lifecycleIn: (root: string, output: string) => string | undefined; /** #311: deleting entries re-resolves every dependency (Next, oxlint, better-auth moved in a one-floor bump), so the recipe is surgical. */ export declare const lockRecipe: (runtime: Manager, moved: { from: string; name: string; to: string; }[], output: string) => string | undefined; export declare const splitsIn: (before: string | undefined, after: string | undefined) => SnapshotChange[]; export declare const lockSplitLines: (splits: readonly SnapshotChange[]) => string[]; /** `@geonosis/doctor` is `@geonosis/cli`'s exact-pinned dependency and moves in every group bump (#375). */ export declare const unrepinnedMoves: (before: string | undefined, after: string | undefined, repinned: ReadonlySet, to: string) => string[]; /** `--only loaded` names every rule enabled without a required option, in the middle of step output nobody reads. */ export declare const byHandIn: (output: string) => ByHand[]; export declare const BUILD_TIER = "build"; export declare const BUILD_SKIPPED = "no build tier declared in geonosis.json; the root build script is not run because it may need deploy environment (declare verify.build, a tier like verify.fast, to opt in)"; /** A repin pruned another's entries and killed a hoist; every install afterwards said "already up to date" and the bump reported PASS. `node_modules/.pnpm-workspace-state-v1.json` decides whether pnpm relinks. */ export declare const buildStep: (root: string, runtime: Manager, extras: readonly string[]) => Promise; export declare const bodyOf: (report: BumpReport, root: string) => string; /** Everything that can refuse runs before anything is written, and every write is followed by the check that would have caught it. */ export declare const runUpdate: (input: UpdateInput) => Promise;