/**
 * githubBugReporter — file a bug report, with the run attached, into GitHub.
 *
 *   import { exportBugReport, githubBugReporter } from 'agentfootprint/observe';
 *
 *   const reporter = githubBugReporter({
 *     issueRepo: 'acme/checkout-agent',      // where the ISSUE goes
 *     evidenceRepo: 'acme/agent-evidence',   // where the ZIP goes (default: issueRepo)
 *   });                                      // token: GITHUB_TOKEN, or `token`
 *
 *   const { issueUrl, zipUrl } = await reporter.file(report);
 *
 * Two HTTP calls and no SDK: `PUT /repos/{evidenceRepo}/contents/{path}` commits
 * the zip, `POST /repos/{issueRepo}/issues` files the issue with a manifest
 * table and a link to the committed bundle. Plain `fetch`, zero dependencies,
 * `apiBase` for GitHub Enterprise Server — so this works unchanged on a network
 * that never reaches github.com.
 *
 * ## TWIN TARGETS: the issue and the evidence may live in different repos
 *
 * The case this exists for: a field tester finds a bug in a LIBRARY. The issue
 * belongs in the library's public repo, where the maintainers and the next
 * person to hit it will find it. The evidence — a real run, with real prompts,
 * real tool arguments and real retrieved documents — does not. So the zip goes
 * into a PRIVATE repo the maintainers can read, and the issue links it and says
 * plainly that the evidence is private.
 *
 * ```ts
 * githubBugReporter({
 *   issueRepo: 'footprintjs/agentfootprint',   // public — the conversation
 *   evidenceRepo: 'acme/af-bug-evidence',      // private — the run
 * });
 * ```
 *
 * ## DEFAULT-TARGET DOCTRINE
 *
 * **File into the application's OWN repo.** That is the default (`evidenceRepo`
 * defaults to `issueRepo`) and it is the right default: the run belongs to the
 * organisation that produced it. Sending a run's evidence across an
 * organisational boundary — to a vendor, to an upstream library, to anyone
 * whose access your company did not grant — is a HUMAN act with consequences a
 * library cannot weigh. This adapter will do it, because a field tester filing
 * upstream is a real and valuable thing; it will not do it quietly. The
 * consent manifest (`describeBugReport`) exists so a person sees exactly what
 * would leave before it does, and this reporter refuses to commit evidence to a
 * PUBLIC repo unless the caller says `acknowledgePublicEvidence: true` out loud.
 *
 * ## Provisioning the token: fine-grained, and scoped to two repos
 *
 * Use a **fine-grained personal access token** (GitHub → Settings → Developer
 * settings → Fine-grained tokens), scoped to ONLY `issueRepo` and
 * `evidenceRepo`, with exactly two permissions — **Contents: read and write**
 * (to commit the zip) and **Issues: read and write** (to file the issue) — and
 * an expiry date. Put it in the server's environment as `GITHUB_TOKEN`, or pass
 * it as `token`.
 *
 * The contrast matters: a CLASSIC PAT's `repo` scope is coarse — it grants
 * read/write across every repository the account can reach, so a leaked
 * bug-report token is a leaked key to the whole account. With a fine-grained
 * token scoped as above, the blast radius of a leak is filing bug reports and
 * committing files to one evidence repo, and nothing else. GitHub App
 * installation tokens (short-lived, org-installed, revocable centrally) are the
 * next rung for an organisation that wants one; this adapter does not mint
 * them — hand it the token your app already obtained.
 *
 * ## Secrecy (the two-clause law)
 *
 * The token appears in no message, no error and no log this adapter can
 * produce, and neither does the bundle's content. A failed request is reported
 * as **the status and GitHub's own `message` field** — never the request, never
 * the headers, never the body that carried the token, never a byte of
 * evidence. Transport failures are re-wrapped rather than rethrown, because a
 * `fetch` implementation is free to put the request (headers included) into the
 * error it throws. Nothing here writes to a console. Pinned by a suite that
 * forces every failure path and greps the message, the stack and the JSON
 * projection for the token.
 *
 * @example  A server route (the app's own repo, the default target)
 * ```ts
 * const reporter = githubBugReporter({ issueRepo: 'acme/checkout-agent' });
 * app.post('/bug-report', async (req, res) => {
 *   const report = exportBugReport(recordings.get(req.body.runId), req.body.fields);
 *   res.json(await reporter.file(report));
 * });
 * ```
 */
import type { BugReport } from '../../bug-report/index.js';
export interface GithubBugReporterOptions {
    /** `owner/name` of the repo the ISSUE is filed in. Required. */
    readonly issueRepo: string;
    /**
     * `owner/name` of the repo the evidence ZIP is committed to. Defaults to
     * {@link issueRepo}. Point it at a PRIVATE repo when the issue itself is
     * public — see the twin-target section above.
     */
    readonly evidenceRepo?: string;
    /**
     * The GitHub token. Falls back to the `GITHUB_TOKEN` environment variable.
     * It needs **Contents: read/write on `evidenceRepo`** and **Issues:
     * read/write on `issueRepo`**; filing an issue on a public repo needs only a
     * valid account token. This is a secret: it is sent as an `Authorization`
     * header and appears in no message this adapter can throw.
     */
    readonly token?: string;
    /** Directory inside `evidenceRepo` for the bundles. Default `'bug-reports'`. */
    readonly dir?: string;
    /** Labels applied to the issue. Default: none. */
    readonly labels?: readonly string[];
    /** Branch to commit the evidence to. Default: the repo's default branch. */
    readonly branch?: string;
    /** API root. Default `https://api.github.com`; for GitHub Enterprise Server
     *  it is `https://github.your-company.com/api/v3`. */
    readonly apiBase?: string;
    /**
     * Commit evidence to a PUBLIC repo deliberately.
     *
     * Off by default: a bundle carries a real run — prompts, tool arguments,
     * retrieved documents — and a public repo publishes it to the internet
     * permanently. Set this only when the evidence is synthetic, or when a human
     * has read the manifest and decided.
     */
    readonly acknowledgePublicEvidence?: boolean;
    /** Refuse a zip larger than this before uploading. Default 24 MB. */
    readonly maxZipBytes?: number;
    /** Test seam — inject `fetch`. Bypasses the network entirely. */
    readonly _fetch?: typeof fetch;
}
/** What a filed report leaves behind. */
export interface FiledBugReport {
    /** The issue, on `issueRepo`. */
    readonly issueUrl: string;
    /** The committed bundle's blob page, on `evidenceRepo`. */
    readonly zipUrl: string;
    /** Path inside `evidenceRepo`. */
    readonly zipPath: string;
    /** `owner/name` the evidence went to. */
    readonly evidenceRepo: string;
    /**
     * Whether the evidence repo's visibility was actually READ before committing.
     *
     * `false` means the metadata call failed — usually a token that can write
     * contents but not read repository metadata. The commit proceeds (a
     * permissions quirk must not block a bug report) and this field says the
     * guard did not run, so nobody mistakes an unchecked upload for a checked one.
     */
    readonly checkedVisibility: boolean;
    /** The answer, when the check ran. */
    readonly evidenceRepoPrivate?: boolean;
}
/** Files a finished {@link BugReport}. */
export interface BugReporter {
    file(report: BugReport): Promise<FiledBugReport>;
}
export declare function githubBugReporter(options: GithubBugReporterOptions): BugReporter;
