/** The minimal Linear project shape the link flow needs (id + name + url). */
export interface LinearProjectLite {
    id: string;
    name: string;
    /** Project URL, when the `linear` CLI JSON carries one. Never fabricated. */
    url?: string;
}
/**
 * Collapse a Linear name / repo slug / folder path to one comparison key:
 * lowercase, keep only the last path segment, strip separators.
 *   "Agents CLI"            -> "agentscli"
 *   "phnx-labs/agents-cli"  -> "agentscli"
 *   "~/src/.../agents-cli"  -> "agentscli"
 */
export declare function normalizeProjectKey(s: string): string;
/**
 * Find the Linear project that best matches a repo slug or folder name.
 * Exact normalized match first, then a containment fallback (either direction),
 * so "agents-cli-web" still suggests "Agents CLI" when no exact peer exists.
 *
 * Kept for parity with the Factory original — the `link` command uses
 * {@link pickLinearProject} instead: this one returns the FIRST match (silent
 * on duplicate names), which is fine for a UI suggestion but never for a write
 * path.
 */
export declare function matchLinearProject(slugOrName: string, projects: LinearProjectLite[]): LinearProjectLite | undefined;
/**
 * Find the local checkout directory a Linear project name refers to, on EXACT
 * key equality only — never containment. `matchLinearProject`'s containment
 * fallback is right for suggesting a link a human then confirms; this backs
 * `projects import --from-linear`, which writes `root`/`repo` with nobody
 * looking, and "Agents CLI" must not silently bind `agents-cli-web`.
 *
 * Returns `undefined` when nothing matches, and also when SEVERAL dirs key to
 * the same value (`agents-cli` and `agents_cli`) — an ambiguous match is not a
 * match.
 */
export declare function matchLocalCheckoutExact(name: string, dirNames: string[]): string | undefined;
/** The outcome of picking one Linear project out of the workspace list. */
export type LinearPick = {
    kind: 'match';
    project: LinearProjectLite;
} | {
    kind: 'candidates';
    projects: LinearProjectLite[];
} | {
    kind: 'none';
};
/**
 * Pick the Linear project a query refers to. An exact id or exact normalized
 * name match is confident enough to write; anything weaker (several exact-name
 * peers, or only containment matches) comes back as a candidate LIST for the
 * user to disambiguate — the link command never guesses on a weak signal.
 */
export declare function pickLinearProject(query: string, projects: LinearProjectLite[]): LinearPick;
/**
 * List the workspace's Linear projects via the `linear` CLI on PATH. Throws a
 * clear error when the binary is missing, errors, or returns a shape we can't
 * use — this backs an explicit user command, so a silent empty list would send
 * the user down a wrong "no matches" path.
 */
export declare function listLinearProjects(): LinearProjectLite[];
/**
 * The `linear` block a def should carry after binding it to `project`.
 *
 * Pure so the write rule is testable without a `linear` CLI or a filesystem —
 * `agents projects link` is the only caller and does nothing else to the field.
 *
 * Two rules, both learned from real drift:
 *
 * - `name` is REFRESHED, never merely preserved. It used to be written by
 *   spreading `prior`, so a project renamed on the board kept its old label in
 *   the YAML forever — and that label is what the status card, the AGI EXT
 *   Fleet panel (`linearProjectName`), and agents naming the work all read.
 * - `url` is dropped when the projectId CHANGES and the incoming row has none.
 *   Carrying it over would leave a def pointing at the previous project's page
 *   beside the new project's name, and the status card prefers `url` over the
 *   id — so the one field a reader clicks would go to the wrong project.
 *   Re-linking the SAME id keeps a previously stored url, since the CLI's list
 *   row omitting `url` says nothing about whether the project has one.
 */
export declare function nextLinearLink(prior: {
    projectId?: string;
    url?: string;
    name?: string;
} | undefined, project: LinearProjectLite): {
    projectId: string;
    url?: string;
    name: string;
};
