/** * How a command reports that it cannot proceed (GUIDELINES §3: errors are actionable, the * most important line last). Two shapes, picked by WHAT went wrong, never by habit: * * usage — the builder typed the command wrong (unknown flag, missing NAME). The error line, * then the usage block: they need the syntax. * failure — the command was typed fine and something else stopped it. The error line with * its catalog code in brackets, then (agent origin only) the agent's own trace and * an origin line, then the hint. Never the usage block — it buried the one line * that mattered under twenty it did not (2026-08-22 report). * * The hint is an explicit field of the domain's `CliFailure`, never derived from the message * text: a hint line is the line a builder acts on, so only text we wrote may be one (PR #157 * review, M3). Every command's `fail` goes through here so the shapes cannot drift per file. */ import { type CliFailure } from "../hosting/cli-failure"; import { jsonRequested } from "../telemetry"; export { jsonRequested }; /** * The exit-code taxonomy (design 2026-08-24 §7½.2; exit 4 added 2026-09-06 — most builders * drive this CLI with their own AI agents, and an agent deciding "retry" vs "fix my input" * vs "fix my code" from exit code alone beats one parsing prose). Documented in * `clustly --help` and /docs/cli; STABLE — additive only. The exit is DERIVED from the * failure's catalog code (error-catalog.ts EXIT_BY_ORIGIN), never chosen per call site. * * 0 success — including an ACCEPTED PENDING state (a review-queued deploy is not a failure) * 1 platform/server/network fault — the input was fine; retrying may succeed * 2 usage — the command itself was typed wrong; fix the invocation (sh convention) * 3 state — typed fine, but the world is not ready (signed out, not deployed, no release); * the hint line names the command that changes the state * 4 agent — YOUR agent's code failed a job (threw, wrong contract, timed out, install * failed); not retryable; the trace names where. Clustly's side was fine. * * 130 (Ctrl-C) is the shell's, set where SIGINT is caught (io.ts). */ export declare const EXIT_CODES: { readonly OK: 0; readonly PLATFORM: 1; readonly USAGE: 2; readonly STATE: 3; readonly AGENT: 4; readonly INTERRUPTED: 130; }; export declare function usageFailureLines(command: string, message: string, usage: string): string[]; /** * The one failure shape: `clustly : [CODE] what`, then — agent origin only — the agent's * trace verbatim and an origin line that says whose fault it is, then the hint. The origin line * is printed ONLY for agent failures: for every other origin the exit code already says it and * the line would be noise. */ export declare function failureLines(command: string, failure: CliFailure): string[]; /** The road-sign an agent follows next: a command to run or a URL to fetch, and why. */ export interface NextStep { cmd?: string; url?: string; why: string; } /** * The one `--json` envelope every surface emits (design 2026-08-24 §7½.1): what happened * (`ok`/`state`), the human sentence (`message`), and `next` — the road-sign array of what an * agent should run or fetch next, so recovery never requires parsing prose. Data rides beside * the envelope, additive-only. One JSON object, stdout, nothing else on stdout. */ export declare function emitJson(payload: { ok: boolean; state: string; message: string; next: NextStep[]; [key: string]: unknown; }): void; /** The --json twin of failureLines: the envelope plus code / origin / exit, and the trace when * there is one. `explain` is always the first road-sign — the definition is the fix's context. */ export declare function failureEnvelope(failure: CliFailure, message: string, next: NextStep[]): { ok: false; state: "failed"; message: string; next: NextStep[]; [key: string]: unknown; }; /** Argument-parse failure: error + usage, exit 2 (the sh convention an agent can key on). * With --json anywhere on the line, the same USAGE failure as one envelope on stdout. */ export declare function exitWithUsageError(command: string, message: string, usage: string, escapeStep?: NextStep): never; /** * THE way a command ends in failure once it has parsed its arguments: the catalog line (or the * --json envelope), the exit derived from the code. Every command's catch goes through here. * * Exists because four commands (status, logs, agents, unlist) each hand-rolled a raw * `console.error(...)` + a bare exit(1) in their catch — so a rejected API key, a 404, and a * genuine outage all came out as exit 1, "your input was fine; retrying may succeed", with no * code, no origin and no envelope, while the same 401 on `test` exited 3 (audit 2026-09-08). * The catalog is only a contract if nothing can bypass it. */ export declare function failCommand(command: string, failure: CliFailure, json: boolean, next?: NextStep[]): never; /** * Every other failure: rendered from the catalog, the exit derived from the code's origin. * * Honours --json HERE, at the funnel, not per call site. The state failures raised before a * command's body — signed out, not deployed, no release — reached this function directly, and * an agent that ran `clustly status --json` while signed out got exit 3 and prose with no * envelope, while the same agent one step later would have got JSON (audit 2026-09-08). One * funnel, one rule: --json anywhere on the line means one envelope on stdout, whatever failed. */ export declare function exitWithFailure(command: string, failure: CliFailure, escapeStep?: NextStep): never; /** `clustly :` — or just `clustly:` for the dispatcher itself, never `clustly :`. */ export declare function commandPrefix(command: string): string; /** @deprecated Use exitWithFailure — kept for the call sites the 2026-09-06 change did not touch. */ export declare function exitWithPlatformError(command: string, failure: CliFailure): never; /** @deprecated Use exitWithFailure — kept for the call sites the 2026-09-06 change did not touch. */ export declare function exitWithStateError(command: string, failure: CliFailure): never;