/**
 * Named project definitions — the layer above the `--project <slug>` convention.
 *
 * `agents run --project <slug>` already resolves a bare name to a working
 * directory by pure convention (`<projectRoot>/<slug>`, see `project-root.ts`).
 * This module adds editable definitions on top: one YAML file per project under
 * `~/.agents/projects/<name>.yaml`, sitting beside the existing `routines/`,
 * `monitors/`, and `teams/` dirs in the user repo.
 *
 * That location makes definitions SYNCABLE, not automatically synced: they ride
 * the user repo only once they are committed to it, via `agents repo push user`
 * (`agents push` was removed). Until then the directory is untracked, and a
 * reconcile that cleans the working tree deletes it — observed twice on one
 * machine, taking four definitions with it each time. The recovery is an
 * orphaned `chore(local): save …-sync drift` commit, which is not a guarantee:
 * unreachable objects are collected. Say "commit them" rather than "for free".
 *
 * A defined project can name itself
 * independently of its folder, bind more than one repo, pin a monorepo subpath,
 * describe context subdirectories an agent should start from, carry a Linear
 * link and external integrations, and set an explicit default path.
 *
 * Portable by construction: `root`/`defaultPath` are stored home-relative
 * (`~/…`) via `toHomeRelative`, so the same definition re-roots on any machine
 * whose home differs — the exact mechanism `project-root.ts` already relies on.
 *
 * Resolution stays additive: an undefined slug still resolves exactly as today
 * (see `resolveProjectRef`), a defined one overrides it.
 */
/** A git repo bound to a project, with an optional monorepo subpath. */
export interface ProjectRepo {
    /** GitHub slug `owner/repo`. */
    slug: string;
    /** Optional path within the repo an agent working this project cares about. */
    subpath?: string;
    /**
     * Optional home-relative local checkout of this repo. The def's `root` only
     * knows the primary repo on disk; `path` opts an additional repo into
     * workspace probing (`projects status`).
     */
    path?: string;
}
/**
 * One checkout target for `projects pull`: a home-relative path plus the
 * expected GitHub slug so the pull step can verify the remote matches before
 * fast-forwarding. `expectedSlug` is absent when a bound dir has no declared
 * slug (the pull still fast-forwards; it just skips the slug check).
 */
export interface ProjectRepoTarget {
    /** Home-relative path — re-roots on each fleet device. */
    path: string;
    /** Expected GitHub slug (`owner/repo`) for the remote; absent = unchecked. */
    expectedSlug?: string;
}
/**
 * A described context anchor: a subdirectory plus what it is. Agents starting on
 * the project read `purpose` to know where to look — an indexed starting point,
 * not just a path. This is the richer form of the single monorepo-focus dir.
 */
export interface ProjectContext {
    /** Path relative to the project root (e.g. `apps/web`). */
    path: string;
    /** One line on how this subtree relates to the project. */
    purpose: string;
}
/**
 * A project goal — the OKR-shaped "why". A project serves one or more goals: a
 * qualitative `objective` ("Ship agents-cli 2.0") and an optional `measure`, the
 * key result that says whether it's landing ("fleet on 2.x", "p95 < 200ms"). The
 * goal is the outcome the work is chasing; milestones (dated checkpoints, pulled
 * from Linear) and live work (agents / PRs / artifacts) are how far along it is.
 */
export interface ProjectGoal {
    /** The outcome, in a line. */
    objective: string;
    /** Optional key result — how success is measured. */
    measure?: string;
}
/** An external context source hung off the project (surfaced in `projects show`). */
export interface ProjectIntegration {
    /** e.g. `gdrive`, `notion`, `figma`, `url`. */
    kind: string;
    url: string;
    label?: string;
}
/** The parsed `~/.agents/projects/<name>.yaml`. */
export interface ProjectDef {
    /** Stable id; matches the filename; what `--project` takes. */
    name: string;
    description?: string;
    /** Repo / monorepo root, home-relative for portability. */
    root?: string;
    /** Where an agent's cwd lands. Defaults to `root` when unset. */
    defaultPath?: string;
    /** Primary GitHub slug (`owner/repo`) — for PR / CI / status roll-up. */
    repo?: string;
    /** All bound repos, each with an optional monorepo subpath. */
    repos?: ProjectRepo[];
    /** Described starting points inside the project. */
    contexts?: ProjectContext[];
    /** The outcomes this project serves (OKR-shaped); a project may have several. */
    goals?: ProjectGoal[];
    /** External context sources (Drive, docs, …). */
    integrations?: ProjectIntegration[];
    /** Linear project link — reuses the existing GraphQL path. */
    linear?: {
        projectId?: string;
        url?: string;
        name?: string;
    };
    /** Free-form doc links surfaced in `projects show`. */
    docs?: string[];
    /**
     * Auto-dispatch settings. When `enabled` is true and `maxAgents > 0` and the
     * project has a `linear.projectId`, the daemon polls Linear for delegated-Todo
     * tickets and dispatches them up to the concurrency cap.
     */
    dispatch?: {
        /** Opt-in: enable auto-dispatch for this project (default: off). */
        enabled?: boolean;
        /** Per-project concurrency cap for auto-dispatched agents. */
        maxAgents?: number;
        /** Optional provider pin: 'rush' | 'codex' | 'factory' | 'host' | … */
        provider?: string;
        /** For provider='host': which machine to dispatch onto (name/device/cap tag). */
        host?: string;
    };
}
/** A project name safe to use as a filename: no separators, `..`, or leading dot. */
export declare function isSafeProjectName(name: string): boolean;
/** Absolute path to a project's YAML definition. Throws on an unsafe name. */
export declare function projectDefPath(name: string): string;
/**
 * Validate a raw parsed object into a `ProjectDef`, throwing an actionable error
 * on the first problem. A malformed document or identity (bad/mismatched name)
 * throws; malformed entries inside the optional lists (`repos`/`contexts`/
 * `integrations`) are dropped so one bad row can't sink an otherwise good def.
 */
export declare function validateProjectDef(raw: unknown, sourceName?: string): ProjectDef;
/**
 * Load a single project definition by name. Returns undefined when the file is
 * absent (the common "not a defined project, fall back to convention" case) but
 * throws when a file EXISTS and is malformed — a broken definition is loud.
 */
export declare function loadProjectDef(name: string): ProjectDef | undefined;
/**
 * List every defined project, sorted by name. A missing projects directory is
 * the empty state; malformed definitions and filesystem failures stay loud so
 * CLI callers (including Factory) can show the actual error.
 */
export declare function listProjectDefs(): ProjectDef[];
/**
 * Persist a project definition, normalizing `root`/`defaultPath` to home-relative
 * so it stays portable across machines. Creates the projects dir on first write.
 * Writes via temp+rename so readers never see a partial file.
 */
export declare function writeProjectDef(def: ProjectDef): string;
/** Delete a project definition. Returns true if a file was removed. Never touches the repo. */
export declare function removeProjectDef(name: string): boolean;
/**
 * The cwd an agent lands in for a defined project: `defaultPath` when set, else
 * `root`. Home-relative when `forRemote` (the remote shell expands `~`), else
 * expanded against the local home. Returns undefined when neither is set.
 */
export declare function projectBasePath(def: ProjectDef, forRemote: boolean): string | undefined;
/**
 * All checkout targets for a project definition, each tagged with its expected
 * GitHub slug. The primary root carries `def.repo`; each `repos[i].path`
 * carries `repos[i].slug`. Paths are home-relative (re-root per fleet device)
 * and include missing checkouts so a remote peer can answer `missing` for them.
 *
 * This is the single authoritative expansion for both `projects status` (via
 * {@link projectProbeTargets}) and `projects pull`, so the two commands always
 * operate on exactly the same set of directories.
 */
export declare function projectRepoTargetsForDef(def: ProjectDef): ProjectRepoTarget[];
/**
 * The directories `projects status` probes across the fleet: the repo root plus
 * every bound checkout, home-relative so each host re-roots them, and including
 * directories absent here so a peer can still answer `✗ missing` for them.
 */
export declare function projectProbeTargets(def: ProjectDef): string[];
/**
 * The directories an agent spawned on this project should reach: the cwd first
 * (`resolveDefinedProjectPath`, so cwd behavior is unchanged), then every other
 * bound repo. `forRemote` keeps them `~/…` so the remote shell re-roots them at
 * its own `$HOME`; locally they are absolute and filtered to what exists.
 *
 * Callers pass the resolved primary so a `--project slug@worktree` run grants
 * the sibling repos alongside the worktree it actually landed in.
 */
export declare function projectDirsAbs(def: ProjectDef, opts: {
    forRemote: boolean;
    primary?: string;
}): string[];
/**
 * Which defined project a session belongs to, derived from its working
 * directory. A session whose `cwd` sits inside a project's repo root (or a
 * worktree under it) is a member; the LONGEST matching root wins so a nested
 * project beats its parent. Returns undefined when no definition contains the
 * path.
 *
 * The comparison is against the LOCAL home: roots and the cwd are both expanded
 * with `expandLocalHome` and resolved, so this matches sessions whose cwd shares
 * this machine's home layout. A session recorded on a different-home machine
 * (`/Users/x/…` vs `/home/x/…`) will not match until the fleet-wide,
 * home-relative variant lands (see docs/concepts.md).
 */
export declare function projectNameForCwd(cwd: string | undefined, defs: ProjectDef[]): string | undefined;
/**
 * The canonical project label for a cwd, for every surface that buckets work by
 * project (the activity timeline, feed posts, the sessions overview): the
 * DEFINED project whose root contains the cwd (longest root wins, so a
 * multi-repo project reads as one bucket), else the repository-level key from
 * {@link resolveProjectKey}. `defs` comes from {@link listProjectDefs}, which is
 * fail-open — with no definitions this degrades to exactly today's behavior.
 */
export declare function resolveProjectNameForCwd(cwd: string | undefined | null, defs: ProjectDef[]): string | undefined;
/**
 * Resolve a defined project's ref to a working directory, mirroring
 * `buildProjectPath`'s `forRemote` contract (a home-relative `~/…` for the
 * remote shell to expand, an absolute local path otherwise). A `@worktree`
 * lands under the repo ROOT's `.agents/worktrees/`, not the `defaultPath`
 * subdir — worktrees are per-repo, not per-focus. Returns undefined when the
 * definition carries no `root`/`defaultPath` (caller falls back to convention).
 */
export declare function resolveDefinedProjectPath(def: ProjectDef, worktree: string | undefined, forRemote: boolean): string | undefined;
