import type { AgentId } from './types.js';
export interface ProjectResourceSyncResult {
    synced: string[];
    skipped: string[];
}
export declare function projectAgentRoot(projectRoot: string, agent: AgentId): string;
export declare function syncProjectResourcesToAgent(agent: AgentId, version: string, projectAgentsDir: string): ProjectResourceSyncResult;
/**
 * Turn the manifest's managed paths (relative to agentRoot) into anchored,
 * POSIX, `referenceRoot`-relative ignore entries. `referenceRoot` is the
 * directory the anchored `/…` patterns resolve against — the git worktree root
 * for a `.git/info/exclude` block, since git anchors info/exclude patterns at
 * the top of the working tree (not at the harness dir). Two guards keep it
 * honest:
 *   - drop any path that escapes the harness config dir (e.g. grok writes
 *     commands back into the tracked `.agents/` tree via a `../` subdir —
 *     ignoring that would hide tracked source; separate bug, PHNX-3718);
 *   - the manifest only ever holds paths the sync itself generated (pre-existing
 *     user/committed files are skipped and never recorded), so ignoring exactly
 *     these never masks a hand-authored or committed file (e.g. a repo that
 *     commits its own `.claude/CLAUDE.md` keeps it — it is not in the manifest).
 */
export declare function managedGitignoreEntries(agentRoot: string, referenceRoot: string, managed: string[]): string[];
/**
 * Stop git tracking `relPath` in the DotAgents clone at `repoDir` and keep it
 * locally ignored — the PHNX-3718 pattern, applied to a shared config file the
 * user repo should no longer carry (e.g. the duplicated CHANGELOG.md; the
 * canonical copy ships in `.system/`).
 *
 * The ignore entry goes in `.git/info/exclude`, NOT `.gitignore`: a tracked
 * `.gitignore` block would itself show as `M .gitignore` on every clone and
 * reintroduce the exact dirty-tree-blocks-pull failure this whole effort exists
 * to kill. info/exclude is per-clone and never committed, so the working tree
 * stays clean at rest.
 *
 * Idempotent and convergent: when the path is still tracked it is removed from
 * the index (the working file is kept) AND that removal is committed — a bare
 * `git rm --cached` would leave a staged deletion, which is itself a dirty tree
 * that re-arms the very pull trip this exists to prevent. The single removal
 * commit also propagates the de-track fleet-wide: peers pull it and converge,
 * their next run finding nothing to untrack. The exclude block is rewritten in
 * place, unioning `relPath` with any entries already there, so a second run is a
 * no-op. Fails open outside a git repo. Returns whether the path was untracked
 * by this call (a signal for the caller's one-time log).
 */
export declare function detrackViaGitExclude(repoDir: string, relPath: string): boolean;
/**
 * One human line for the files a project sync left alone because you already
 * wrote them. This is the normal steady state — every sync of a project whose
 * `.claude/commands/` you hand-authored hits it — so it is a single grouped
 * line, not one wrapped warning per file, and it says "yours" rather than the
 * internal "user-owned". Returns null when nothing was skipped.
 */
export declare function formatKeptProjectResources(skipped: string[]): string | null;
