import { detectCi, TOOL_LABELS, TOOL_ORDER, type CiDetection, type DetectOptions, type MigrationTool, type ToolMatch } from "./detect.js"; /** * Write the workflow that runs this check on every pull request. * * `GOAL.md` says the thing that decides whether this becomes infrastructure is * whether it is a default rather than a decision, and that retention lives in * CI: a test that passes silently forever gets deleted, one that blocks a bad * merge stays. Today adopting the Action means hand-writing a service * container, a migration step, a permissions block and the step itself. That is * thirty minutes of YAML nobody enjoys, and it is where adoption stops. * * `action.yml` refuses to guess the migration step *at runtime*, and that * refusal is right: guessing wrong there means silently testing a schema the * developer did not write, and reporting on it behind their back. Guessing at * scaffold time is a different act entirely — the guess lands in a file they * read before it ever runs, and a wrong one is a line they fix in the diff. * * So this guesses, loudly, and says what it guessed from. Where it cannot tell, * it leaves the step present and commented rather than absent, because a * missing step is an empty database, and an empty database is a run that comes * back inconclusive rather than a run that passes over nothing. */ /** * The published action, as `README.md` and `docs/example-usage.yml` name it. * * Kept next to those two on purpose: `test/ci-scaffold.test.ts` asserts this * string appears in `docs/example-usage.yml`, so moving the repository breaks * the suite rather than shipping a workflow pointing at nothing. */ export declare const ACTION_REF = "jdora09769-bot/crossline@v1"; /** Where the file goes, and the name tried when the first one is taken. */ export declare const WORKFLOW_DIR = ".github/workflows"; export declare const WORKFLOW_NAMES: readonly ["crossline.yml", "crossline-access-control.yml"]; /** The complete file, ready to write. */ export declare function renderWorkflow(d: CiDetection): string; export type CiStatus = /** Nothing here runs Crossline yet; `path` is free. */ "write" /** A workflow in this repository already does; nothing to do. */ | "already-configured" /** Every candidate name is taken by somebody else's workflow. */ | "no-free-name"; export interface CiPlan { detection: CiDetection; /** The whole file, whether or not it is going to be written. */ workflow: string; /** Relative path we would write, or null when we refuse to. */ path: string | null; status: CiStatus; /** The workflow that already runs Crossline, when that is why we stopped. */ existing: string | null; /** Candidate names found already taken by unrelated workflows. */ taken: string[]; } /** * Work out what would change, without changing anything. * * The rule this enforces is the one that decides whether the command is safe to * run twice: nothing that exists is ever rewritten. Not the workflow somebody * hand-tuned six months ago, and not one of ours either — a file a developer * edited is theirs, and silently replacing it with a fresh guess is exactly the * behaviour that gets a tool removed. */ export declare function planCi(cwd: string, opts?: DetectOptions): CiPlan; /** Write the plan. Returns the path written, or null when nothing was. */ export declare function applyCi(cwd: string, plan: CiPlan): string | null; /** What was detected and why, for a reader who has not opened the file yet. */ export declare function describeDetection(d: CiDetection, color?: boolean): string; export interface OfferCiOptions { cwd: string; migrations?: MigrationTool | "none"; /** True when `--yes` was passed: no prompt, just write. */ assumeYes: boolean; /** Whether there is a human on the other end of stdin. */ interactive: boolean; out: (text: string) => void; ask: (question: string) => Promise; /** Injected so the prompt is drivable from a test. */ saysYes: (answer: string) => boolean; } /** * The whole interaction, from detection to the sentence naming what changed. * * Split out of the CLI for the same reason the agent hook is: so the decision * table is one readable thing and a test can drive it without a pseudo-terminal. */ export declare function offerCi(opts: OfferCiOptions): Promise; export { detectCi, TOOL_LABELS, TOOL_ORDER }; export type { CiDetection, MigrationTool, ToolMatch };