import { type GitRunner } from './project.js';
import { DATA_BRANCH } from './branch-names.js';
export { DATA_BRANCH };
/** The data branch's checkout under a project: `<repo>/.the-framework/branches/tf-data`. */
export declare function dataWorktreePath(cwd: string): string;
/** Injectable seams; production takes the defaults. */
export interface DataBranchDeps {
    git?: GitRunner;
    /** Write one file, creating parents (default `node:fs/promises`). */
    write?: (path: string, content: string) => Promise<void>;
    /** Whether anything (file, dir, or dangling link) sits at `path` (default `fs.lstat`). */
    lexists?: (path: string) => Promise<boolean>;
    /** Create a symlink at `path` to `target` (default `node:fs/promises`). */
    symlink?: (target: string, path: string) => Promise<void>;
    log?: (message: string) => void;
}
/**
 * Make sure the data branch and its checkout exist, the queue file is seeded, and the root
 * `tickets` symlink points into the checkout. Idempotent and cheap when everything is in place
 * (one `git rev-parse` against the checkout); never throws — a project this cannot be set up in
 * reports why and is left alone.
 */
export declare function ensureDataWorktree(cwd: string, deps?: DataBranchDeps): Promise<{
    ok: boolean;
    error?: string;
}>;
/**
 * What one funneled write did. `changed: false` is the clean no-op (the op wrote nothing new).
 * A failure says whether the change still landed as a local commit (`committed` — the push is
 * what failed, and the next cycle carries it out) or nothing survived at all.
 */
export type DataWriteResult = {
    ok: true;
    changed: boolean;
    pushed: boolean;
} | {
    ok: false;
    committed: boolean;
    error: string;
};
/**
 * Apply one change to the data branch: sync with origin, run `op` against the checkout, commit
 * whatever it changed, push. The single funnel every local data write goes through (#1582).
 *
 * `op` must be re-runnable: when the push loses a race with another machine, the cycle re-syncs
 * and runs it again against the fresher state rather than force-fitting a stale commit — the op
 * *is* the intent, the commit is just its serialization. Two attempts; a push that still fails
 * (the network, most likely) keeps the commit local and reports the error — the next cycle's sync
 * rebases it onto whatever origin has by then, and the next push carries it.
 *
 * Never throws: callers run on background ticks with nothing to catch it.
 */
export declare function withDataBranch(cwd: string, message: string | (() => string), op: (dataDir: string) => Promise<void>, deps?: DataBranchDeps): Promise<DataWriteResult>;
/** How a sync went: converged with origin, or why it could not. */
export type DataSyncResult = {
    ok: true;
} | {
    ok: false;
    error: string;
};
/**
 * The eager pull (#1582): sync the checkout with origin so this machine reads what other machines
 * and cloud sessions committed, without waiting for the next local write — and push anything a
 * failed cycle left stranded locally, via the same owed-push rule as the writer. Ensures the
 * checkout exists, so a fresh clone converges on its first tick. Never throws.
 *
 * Reports why it could not converge (#1599): a push origin rejects, or no origin to converge with
 * at all. The writer treats a remote-less repo as fine — the commit is safe locally — but a sync's
 * whole job is to meet the other machines, and a repo nothing can reach is an error state the user
 * has to fix, not a mode the framework supports (#1595). The daemon records the answer as the
 * project's error state, so it reaches the dashboard rather than only the daemon's stdout.
 */
export declare function pullDataBranch(cwd: string, deps?: DataBranchDeps): Promise<DataSyncResult>;
/**
 * The project root `cwd` belongs to: the directory holding the repo's real `.git`. From the main
 * checkout that is `cwd` itself; from an agent's worktree it is the repo the worktree was made
 * from — where the data checkout lives, and the address every data write funnels to. `undefined`
 * outside any repo.
 */
export declare function dataProjectRoot(cwd: string, git?: GitRunner): Promise<string | undefined>;
/**
 * Read one file off the data branch, from anywhere in the repo: the checkout when this `cwd` has
 * one, else `git show` against the local branch (worktrees share the repo's refs, so an agent's
 * checkout reads the same data without holding any of it), else against `origin/…` (a fresh
 * clone that fetched but never branched — the cloud case). `undefined` when the file exists in
 * none of them. Never throws.
 *
 * `fresh: true` fetches first and prefers origin's copy — for a reader about to act on the queue
 * from a long-lived agent process, where the local ref may trail what other writers pushed.
 */
export declare function readDataFile(cwd: string, rel: string, opts?: {
    fresh?: boolean;
}, deps?: DataBranchDeps): Promise<string | undefined>;
//# sourceMappingURL=data-branch.d.ts.map