/** * The single subprocess boundary between this feature and the `gh` CLI. * * Every `gh` invocation in the projection goes through `GhRunner.run(args)`, and * `args` is an array. That is structural rather than habitual on purpose: item titles * and config values come from tracked files, so in a cloned repo they are the repo * author's strings, not the user's. With one seam there is no call site for somebody * in a hurry to add a template string or `shell: true` to, and the fake runner used in * tests records every argv — which is what lets the token-secrecy property be checked * by *value* (set `GH_TOKEN` to a sentinel, assert it appears in no recorded argv) * rather than by grepping the source for a variable name. This project has broken * prose-scoped greps six separate times. * * Nothing here reads `GH_TOKEN` or `GITHUB_TOKEN`. `gh` owns the credential; this * module owns the argv. * * One function here is **not** a subprocess and is the exception that proves the rule: * {@link resolveGhOnPath} answers "is `gh` installed?" with a filesystem lookup, because * `aidlc doctor` needs that answer on its default path and may not spawn to get it. It * lives here rather than in a second file so all `gh` knowledge stays in one place. * * Requirements: roadmap-issue-projection/AC-30, roadmap-issue-projection/AC-50, * issue-tracker-in-init/AC-29 * * @module */ export type GhResult = { ok: true; stdout: string; } | { ok: false; error: string; exitCode: number | null; }; export interface GhRunner { run(args: readonly string[]): GhResult; } /** * 256 MiB. * * `execFileSync` defaults to 1 MiB, and discovery asks for every projected issue's * body so the marker can be read. Measured: the default throws `ENOBUFS` at roughly * 2 MiB of output, which a few hundred issues with ordinary bodies will exceed — two * orders of magnitude below the 1000-issue map this feature otherwise supports. The * failure is a thrown error rather than a truncated read, so it would be loud; it * would also be entirely avoidable, which is why the limit is stated. */ export declare const GH_MAX_BUFFER: number; /** The real runner. Argument array, no shell, explicit buffer. */ export declare function realGhRunner(): GhRunner; /** * Check that `gh` is present and authenticated. * * **Authentication only.** `gh auth status` cannot tell whether the token may write * issues on the target repository, so a token that is authenticated but not authorized * passes here and fails on the first write — where `applyPlan` names the item and * prints `gh`'s own message. Claiming otherwise would put the check in the wrong * place and make the first-run failure less legible, not more. */ export declare function ghPreflight(gh: GhRunner): { ok: true; } | { ok: false; error: string; }; /** * Where `gh` resolves on `PATH`, or null. * * **Presence only, and deliberately not a `run()` call.** This is the one probe that runs * on `aidlc doctor`'s default path, and `check` is documented there as pure state * inspection shared verbatim by dry-run and real runs (`doctor/types.ts:1-10`). * `gh auth status` can reach the network, so an offline run would report a problem that is * not there; even `gh --version` spawns a process on every doctor run in every project that * opted in. A `PATH` walk with an execute-permission test is a handful of `stat` calls, * offline and deterministic. Authentication stays with {@link ghPreflight}, which has the * better message for it. * * `env` is a parameter, not a read of `process.env`, so both branches are testable without * mutating the ambient environment (issue-tracker-in-init/AC-29, AC-30). * * `PATH` entries are untrusted path fragments: they are joined and permission-tested, * never interpolated into a command. */ export declare function resolveGhOnPath(env?: NodeJS.ProcessEnv): string | null; /** First non-empty line of a `gh` message, for one-line error reporting. */ export declare function firstLine(text: string): string; /** `['--repo', repo]` when a coordinate was resolved, else `[]`. */ export declare function repoArgs(repo: string | null): readonly string[]; /** * Ask `gh` which repository the current directory belongs to. * * Only needed when `roadmap.sync.repo` is unset, and only so bodies can carry permalinks. * A failure is **not** fatal: it yields null, and the projection continues with unlinked * paths. Refusing to sync because a hyperlink could not be built would trade the feature's * whole purpose for one of its conveniences, and the plan header already names the target, * so a wrong repository stays visible either way. */ export declare function resolveNameWithOwner(gh: GhRunner): string | null; //# sourceMappingURL=gh.d.ts.map