/**
 * exportBugReport / describeBugReport — a bug report IS the evidence.
 *
 * The usual bug report is a person's memory of a run: "it said the wrong
 * thing, I think it called the search tool twice". The run itself — the
 * timeline, the state, the chart, the narrative — is sitting right there in
 * the process and never leaves it. This turns that around: the report is the
 * run, packaged, with the prose attached.
 *
 * ## Two calls, because consent needs two
 *
 *   1. {@link describeBugReport} — "here is what would be sent." A manifest of
 *      SELECTABLE UNITS: each conversation with its event and turn counts and
 *      its size, each derived file, the redacted keys by name, the total, and
 *      a loud warning with trim hints if it is too big.
 *   2. {@link exportBugReport} — "send exactly these." The reporter's ticked
 *      unit ids come back as `include`, and the bundle carries only those.
 *
 * One call does work for a server-side reporter that has no human in front of
 * it; the two-call shape is what makes a browser consent dialog possible at
 * all, because a dialog cannot ask about a blob it has not measured.
 *
 * ## What is in the bundle (layout 2 — `manifest.manifestVersion`)
 *
 * | file | what it is |
 * |---|---|
 * | `manifest.json` | this manifest — always present, never a selectable unit |
 * | `envelope.json` | the run as a `RecordingEnvelope`: the archive contract, with the canon `{ snapshot, events, structure }` under `recording` |
 * | `recording.json` | the bare recording — ONLY when the envelope's run facts were not available, with the manifest naming the missing one |
 * | `conversations/<id>.json` | one file per conversation, when there is more than one run |
 * | `conversation.json` | the readable transcript, derived from the events |
 * | `narrative.txt` | the narrative recorder's lines, when one was attached |
 * | `environment.json` | the HOST that ran it + the reporter's prose |
 *
 * The evidence file is named for what it is, and there is never more than one
 * of it: a bundle carrying both an envelope and a copy of the recording it
 * already contains would double the biggest file in the archive — and the
 * archive is store-only, so doubling is real bytes, against a ceiling a
 * reporter has to fit under.
 *
 * `environment.json` is the host and NOTHING that identifies a machine: Node
 * version, platform, architecture. **No username, no hostname, no working
 * directory, no environment variables, no file paths.** A bug report should not
 * be the way an internal directory layout leaves a company. The producer
 * versions it used to repeat now live where the archive contract stamps them,
 * in `envelope.json`'s `producer` — one fact, one place. (The manifest's own
 * `environment` block still prints both for the human reading the issue; it is
 * a summary, not a second archive.)
 *
 * ## Redaction is already done, and the manifest proves it
 *
 * The recording arrives ALREADY redacted when its run had a policy (an
 * agent's `Agent.create({ redact })`): footprintjs scrubs state at commit
 * time, the snapshot a recording carries is the redacted view
 * (`getLastSnapshot()`), and every event was served under the same rule
 * before anything recorded it — so a redacted value was never in what this
 * reads. Nothing here scrubs anything — it would be too late to matter and a
 * second policy could only disagree with the first. What this
 * does do is LIST the redacted keys by name, derived from the placeholders
 * actually present in the evidence, so a human consenting to the bundle can
 * see which secrets were protected. A key that is not on that list was not
 * redacted, and the honest reading of an empty list is "no policy was set" —
 * which the manifest says in a note.
 *
 * @example  The consent flow
 * ```ts
 * const manifest = describeBugReport(recording);
 * // …show manifest.units to the human; they tick some…
 * const report = exportBugReport(recording, {
 *   include: ['conv-1', 'file-narrative', 'file-environment'],
 *   title: 'Agent answered with a stale price',
 *   stepsToReproduce: '1. ask for the price\n2. update it\n3. ask again',
 *   expected: 'the new price',
 *   actual: 'the old one',
 * });
 * fs.writeFileSync(report.filename, report.zip);
 * ```
 */
import type { BugReport, BugReportInput, BugReportManifest, DescribeBugReportOptions, ExportBugReportOptions } from './types.js';
/**
 * A size a human reads. KB under a megabyte, MB above it — a ceiling reported
 * as "0.0 MB" teaches nothing, and these strings are the whole content of a
 * refusal.
 */
export declare function formatBytes(bytes: number): string;
/**
 * Measure a bug report before anything leaves — the consent step.
 *
 * Every unit is "selected" in the manifest this returns, because nothing has
 * been chosen yet: it is the offer, with sizes and counts attached, for a human
 * (or a policy) to narrow. Show `units` to the reporter; pass the ids they keep
 * to {@link exportBugReport} as `include`.
 *
 * Cheap enough to call on every dialog open: it serializes the files to measure
 * them, and throws them away.
 *
 * @param input   a recording, a `recordRun` handle, a runner, or an array.
 * @param options size ceiling and a fixed timestamp.
 */
export declare function describeBugReport(input: BugReportInput, options?: DescribeBugReportOptions): BugReportManifest;
/**
 * Build the bundle: the manifest, the named files, and a real zip of them.
 *
 * @param input   a recording, a `recordRun` handle, a runner, or an array.
 * @param options the reporter's prose, plus `include` — the ids from
 *                {@link describeBugReport} that the reporter consented to.
 *
 * @throws TypeError naming the unknown id when `include` names a unit that
 *         does not exist, and naming the available conversations when the
 *         selection would carry no evidence at all.
 */
export declare function exportBugReport(input: BugReportInput, options: ExportBugReportOptions): BugReport;
/** `2026-08-11-agent-answered-with-a-stale-price.zip`. */
export declare function bundleFilename(title: string, createdAt: Date): string;
/** Lower-case, ASCII, hyphenated, bounded — a filename, not a sentence. */
export declare function slugify(title: string): string;
//# sourceMappingURL=build.d.ts.map