import { type Output } from '../output.js'; import type { AgentsMdOutcome } from '../scaffold/agents-md.js'; import { type DependencyMismatch } from '../scaffold/dependency-diff.js'; import { type UpdateTag } from '../update/notice.js'; export interface GitStatus { dirty: boolean; } /** * The boundary that makes `upgrade` safe to run at all: the whole value of the command is that a * creator can read what it changed as a git diff. Overwriting vendored files on top of already * -uncommitted work mixes the two together and makes that diff unreadable, so a dirty tree is * refused unless the creator opts in with --force. Kept as a pure function, separate from the * git call that produces `status`, so it is reachable from a test with no real repo involved. */ export declare function assertCleanTree(status: GitStatus, force: boolean): void; /** * The other half of "package.json is never rewritten": upgradeProject leaves it untouched even * when the vendored engine now needs a dependency it doesn't have (e.g. vite-plugin-singlefile, * which every pre-Task-3 project's package.json predates) — silently doing nothing here would * mean `upgrade` reports success while `bitmagic build` still fails later with an opaque * module-resolution error. Prints the exact install command instead; never writes the file. * * The command names the project's OWN package manager (`detectPackageManager`), not a hardcoded * npm: a creator on pnpm who runs the printed `npm install` gets a tree npm linked and a second, * far less obvious failure on the next build. * * Exported for its test — the detection helpers can be unit-tested on their own, but only * calling this proves the printed line actually uses them. */ export declare function printDependencyReport(output: Output, root: string): DependencyMismatch[]; /** * Say what became of AGENTS.md, and — when it was kept — what the current template has that it * does not. * * Only `kept` is worth more than a line. `current` says nothing at all: reporting "unchanged" on * every upgrade of every project is the kind of output people stop reading, which costs the * messages that do matter. */ export declare function reportAgentsMd(output: Output, outcome: AgentsMdOutcome): void; /** * Tell a project scaffolded before GAME-DESIGN.md existed that it is missing one, and return * whether it was. * * The same shape as the dependency report above, and for the same reason: `upgrade` deliberately * never writes a creator-owned file, so where an upgrade leaves a project unable to use something * the CLI can now do, it has to say so rather than let the gap sit there silently. Cover art is * exactly that case — the command reached every project the moment the CLI updated, but its input * only reaches projects scaffolded since. * * Conditioned on the file genuinely being absent, never on a version number. A "what's new in this * release" banner would be printed to projects that already have the thing, and would rot into a * lie the release after next; this cannot, because it is reporting a fact about the disk. * * It stays a nudge: writing the design document for someone would be putting our words in their * game's mouth, and the file is theirs. */ export declare function reportMissingDesignDoc(output: Output, root: string): boolean; /** What the post-upgrade CLI check found, for the `--json` result. */ export interface CliUpdateStatus { /** The CLI that ran this upgrade. '' when its own package.json could not be read. */ current: string; /** The newest version npm reports, or null if the registry could not be reached. */ latest: string | null; /** True only for a confirmed newer release — an unreachable registry is not evidence. */ updateAvailable: boolean; } /** * Ask npm, right now, whether this CLI is behind — but only when the engine actually moved. * * The startup nudge in bin.ts already reports a newer CLI on every command, so this exists for the * one thing that nudge structurally cannot do: it reads a cache refreshed at most once a day, so on * the run where a creator vendors an engine published minutes ago it is silent about the CLI that * shipped alongside it. That is the moment the gap matters most — an engine can need build config or * a command only the newer CLI has, and the creator finds out as an opaque `bitmagic build` failure * rather than as a version mismatch. * * Gated on the engine version having changed, not run on every `upgrade`: with no bump there is * nothing newly vendored to be out of step with, and the daily cached nudge is enough. The gate is * inside this function rather than at the call site so the no-bump path provably makes no request. * * Live rather than cached, and so on the network — but `upgrade` has already downloaded a tarball by * the time it runs, and `fetchLatestVersion` carries its own short timeout and swallows every * failure into null. A sulking registry costs a hint, never the upgrade. */ export declare function reportCliUpdate(output: Output, engineChanged: boolean, version?: string, tag?: UpdateTag, fetchLatest?: () => Promise): Promise; export declare const upgradeCommand: import("citty").CommandDef<{ readonly engine: { readonly type: "string"; readonly description: "Engine version to upgrade to (must be the currently published one)."; }; readonly force: { readonly type: "boolean"; readonly description: "Upgrade even with uncommitted changes in the working tree."; }; readonly agent: { readonly type: "string"; readonly description: string; }; readonly json: { readonly type: "boolean"; readonly description: "Print the result as JSON on stdout; all progress goes to stderr."; }; }>;