export declare function getGitBranch(cwd: string): string;
export declare function getGitStatus(cwd: string): string;
export declare function getGitDiff(mode: 'staged' | 'all', cwd: string): string;
export declare function getGitDiffStat(cwd: string): string;
/**
* Detect the default branch of the remote (e.g. main, master).
* Falls back to 'main' if detection fails.
*/
export declare function getDefaultBranch(cwd: string): string;
/**
* The branch-vs-base diff PLUS the ref that actually produced it (mmnto-ai/totem#2106
* rev-5 item 3). `getGitBranchDiff` returns only the diff text, so a caller that also
* needs to know WHICH ref was diffed (for scope/lineage metadata) previously re-probed
* ref existence separately — but `origin/` can EXIST yet its `...HEAD` diff FAIL
* (unrelated histories / no merge base), in which case the payload is local-based while
* a separate existence probe would mislabel it `origin/`. Returning `resolvedBase`
* from the diff operation itself couples the recorded ref to the diff that actually ran.
*/
export interface GitBranchDiffResult {
/** The unified diff text of `...HEAD`. */
diff: string;
/** The ref that PRODUCED the diff — `origin/` when its diff succeeded, else the local ``. */
resolvedBase: string;
}
export declare function getGitBranchDiffResult(cwd: string, base?: string): GitBranchDiffResult;
/**
* Branch-vs-base diff text only. Thin wrapper over {@link getGitBranchDiffResult} that
* discards `resolvedBase` — retained at its original `string` return so the many
* existing callers keep compiling (mmnto-ai/totem#2106 rev-5 item 3, additive change).
*/
export declare function getGitBranchDiff(cwd: string, base?: string): string;
/**
* Run `git diff ` for an explicitly supplied ref range (e.g.
* `HEAD^..HEAD`, `main...feature`). Used by `totem review --diff` to
* bypass the implicit working-tree → staged → branch-vs-base fallback chain.
*
* Rejects ranges starting with `-` to defuse git-flag injection (e.g.
* `--diff --no-index`); `safeExec`'s arg-array form already prevents shell
* metacharacter expansion on the range itself.
*/
export declare function getGitDiffRange(cwd: string, range: string): string;
/**
* Get the author date of a tag in YYYY-MM-DD format.
* Returns null if tag doesn't exist or lookup fails.
*/
export declare function getTagDate(cwd: string, tag: string): string | null;
/**
* Get the most recent semver tag (e.g., "v0.14.0").
* Returns null if no tags exist.
*/
export declare function getLatestTag(cwd: string): string | null;
/**
* Get git log since a ref (tag or commit), or last N commits as fallback.
* Returns one-line-per-commit format: "hash subject".
*/
export declare function getGitLogSince(cwd: string, since?: string, maxCommits?: number): string;
/**
* Check if a specific file has uncommitted changes (staged or unstaged).
*
* Fails loud: throws `TotemGitError` when git is absent or errors, so callers
* cannot mistake "git broke" for "file is clean" (mmnto/totem#1440). The one
* documented silent-false case is "not a git repository" — a legitimate state
* for a working directory that happens to sit outside version control.
* Callers that truly want silent fallback for OTHER git failures must opt in
* explicitly with their own try/catch + `// totem-context:` annotation.
*/
export declare function isFileDirty(cwd: string, filePath: string): boolean;
/**
* List git-tracked files under `dirAbs`, returned as `dirAbs`-relative
* forward-slash paths. Returns `null` (NOT an empty set) when the directory is
* outside a git repo OR git is unavailable/errors — the documented signal for
* callers to fall back to a filesystem walk rather than treat "git unavailable"
* as "nothing tracked." An empty set means the opposite: we ARE in a repo and
* genuinely nothing under `dirAbs` is tracked.
*
* Used by {@link generateInputHash} to exclude untracked working-tree lessons
* from the compile-manifest input hash — an untracked MCP scratch lesson must
* not diverge the hash and block an unrelated push (mmnto-ai/totem#2051 /
* mmnto-ai/totem#2055 working-tree-scope class). Fail-soft to `null` is
* deliberate: a git hiccup degrades to the legacy fs-walk (prior behavior),
* never a crash.
*
* Reads git's NUL-delimited output so paths with spaces or unicode parse
* exactly; the delimiter is built via `String.fromCharCode(0)` to keep this
* source free of a literal control byte.
*/
export declare function listTrackedFilesUnder(repoCwd: string, dirAbs: string): Set | null;
/**
* Resolve the git repository root via a JS-side walk-up looking for `.git/`,
* rather than shelling out to `git rev-parse --show-toplevel`. Sibling to
* {@link resolveGitRoot}; prefer this variant when the caller will combine
* the returned root with paths derived from `process.cwd()` — git's output
* normalizes case + may resolve Windows 8.3 short names (`RUNNER~1`) to long
* names (`runneradmin`), and the divergence breaks `path.relative` even when
* both paths point at the same directory. A JS-side walk returns a path in
* cwd's own form, so downstream `path.relative` works portably.
*
* Returns `null` when `start` is not inside a git repository (or any parent
* is not). Never throws — best-effort by contract. No subprocess overhead.
*/
export declare function findRepoRootSync(start: string): string | null;
/**
* Walk up from `start` to the nearest ancestor that is a Totem repo root: a
* directory containing a `.totem/` marker OR a `.git` entry (a directory in a
* normal clone, a FILE in a linked worktree — `existsSync` matches both).
* Returns that ancestor's absolute path, or `null` when neither marker appears
* up to the filesystem root. Never throws — best-effort, pure fs, no git spawn.
*
* Sibling to {@link findRepoRootSync} (which keys on `.git` alone); this
* variant also stops at `.totem/` so a consumer invoked from a SUBDIRECTORY of
* a repo — e.g. `.totem/orchestration//processed/` — resolves the true
* root instead of the subdir. Without it, a cwd-fragile derivation
* (`process.cwd()` + `path.dirname`) reads the wrong workspace and can render a
* false-clean verdict (mmnto-ai/totem#2312). The `.totem` marker is checked
* first so an orchestration-only tree still anchors even where `.git` is a
* worktree file the caller might not expect.
*/
export declare function findTotemRepoRootSync(start: string): string | null;
/**
* Resolve the effective Totem repo root for a command invoked with an optional
* `repoRoot` override: treat `repoRoot ?? cwd` as the WALK START and derive
* the root via {@link findTotemRepoRootSync}; a marker-less start (bare test
* fixture) is used as-is. Single home for the walk-start-not-definitive-root
* contract shared by `pollMail`, `eclGc`, and `eclCompact`
* (mmnto-ai/totem#2312).
*/
export declare function resolveTotemRepoRootSync(repoRootOpt: string | undefined, cwd: string): string;
/**
* A copy of `env` with {@link GIT_LOCATION_ENV_VARS} removed and everything
* else — PATH included — carried through unchanged. Exported for direct
* testing; callers pass the result as the child's `env`.
*/
export declare function envWithoutGitLocation(env?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
/**
* The REPOSITORY NAME of a checkout's `origin` remote — `totem` for
* `https://github.com/mmnto-ai/totem.git`, `git@github.com:mmnto-ai/totem.git`,
* and either form without the `.git` suffix or with trailing slashes. The
* owner and the host are deliberately dropped: this answers "which repository
* is this checkout of", which is a property of the path's last segment, and a
* mirror or a fork at the same repo name answers the same (the same
* host-blindness the doctor's cohort-id derivation already has).
*
* Returns `null` when there is no origin, when git is unavailable or fails for
* ANY reason, or when the URL yields no `owner/repo` pair. Never throws: every
* caller's fallback is "we do not know", and a git failure is exactly that.
*
* Costs one synchronous `git config` spawn, so call it only where the answer
* cannot be had from the filesystem (mmnto-ai/totem#2801: the cohort map's key,
* where a per-agent worktree's DIRECTORY basename names the worktree rather
* than the repository).
*
* The answer is a function of `cwd` ALONE, and two guards make it so.
*
* `--local` scope: a bare `git config --get` searches local, then GLOBAL, then
* system, and answers outside a repository at all — so a machine carrying a
* global `remote.origin.url` would hand a repo-shaped answer to a directory
* that is not a repo. `--local` errors outside a repository, which lands on the
* documented `null`. In a linked worktree it reads the shared common-dir
* config, where remotes live.
*
* A scrubbed env: git's repository-location variables are read from the
* environment before `cwd` is consulted, and git EXPORTS them into every hook
* process it spawns. Inheriting them made this read answer for whatever
* repository the ambient `GIT_DIR` named — a non-repo directory resolved as
* that repo, which is the identity-adoption class the caller exists to
* prevent, and it turned the resolver's own suite red under an exported
* `GIT_DIR`. {@link GIT_LOCATION_ENV_VARS} are therefore deleted from the
* child's env; everything else (PATH above all) is inherited unchanged.
*/
export declare function getOriginRepoName(cwd: string): string | null;
/**
* Extract the repository name from an ssh (`git@host:owner/repo.git`) or https
* (`https://host/owner/repo.git`) remote URL, tolerating a trailing `.git` and
* trailing slashes in either order. Returns `null` when no `owner/repo` pair
* resolves. Pure — exported for direct testing of the parse.
*/
export declare function repoNameFromRemoteUrl(remoteUrl: string | undefined): string | null;
export declare function resolveGitRoot(cwd: string): string | null;
/**
* Filter a unified diff to exclude files matching ignore patterns.
* Splits on `diff --git` boundaries and removes sections for ignored files.
* Uses matchesGlob from core for consistent glob behavior.
*/
export declare function filterDiffByPatterns(diff: string, patterns: string[]): string;
export declare function extractChangedFiles(diff: string): string[];
/**
* Infer a scope glob suggestion from a list of changed file paths.
* Returns glob patterns based on the common directory prefix,
* with default test file exclusions.
*/
export declare function inferScopeFromFiles(files: string[]): string[];
//# sourceMappingURL=git.d.ts.map