/** * FF-only git merge utility for the Tier-3 merge ritual. * * Enforces the linear-history contract: merges MUST be fast-forward only. * If the experiment branch has diverged from the target (i.e. cannot be * fast-forwarded), the merge is aborted immediately. The codebase NEVER * auto-rebases — the caller must resolve divergence manually and retry. * * Kill-switch checks are performed at `pre-merge` and `post-merge` step * boundaries via {@link checkKillSwitch}. A kill between the merge commit * landing and the post-merge check cannot be auto-reverted by this utility; * the caller is responsible for manual cleanup in that case. * * Algorithm: * 1. `checkKillSwitch('pre-merge')` — abort before touching git * 2. `git -C merge --ff-only ` * 3. Non-zero exit → `git merge --abort` (safety net), return * `{ merged: false, reason: 'ff-failed-abort' }` * 4. `checkKillSwitch('post-merge')` — warn but cannot auto-revert * 5. Return `{ merged: true, headSha }` * * Subprocess safety: * - All git arguments are passed as separate array elements to * `child_process.spawn`. No shell interpolation of user-supplied strings. * - `shell: false` (Node default) ensures paths with spaces or special * characters cannot escape into shell metacharacter injection. * * @see ADR-054 — Sentient Loop Tier-3 (sandbox auto-merge) * @task T1028 */ /** Result returned by {@link gitFfMerge}. */ export interface MergeResult { /** Whether the fast-forward merge succeeded and was committed. */ merged: boolean; /** * HEAD SHA of the target branch after the operation. * * - When `merged: true` — the new HEAD after the ff-merge. * - When `merged: false` — the unchanged HEAD (merge was aborted). * - Empty string on unexpected git failure. */ headSha: string; /** * Reason for a non-merged outcome. * * - `'ff-failed-abort'` — `git merge --ff-only` exited non-zero; histories * have diverged. The caller MUST resolve divergence manually. * - `'kill-switch-activated'` — kill switch fired at `pre-merge`; merge was * never attempted. * - `'verify-failed'` — git subprocess could not be spawned or an unexpected * error occurred during the merge operation. */ reason?: 'ff-failed-abort' | 'kill-switch-activated' | 'verify-failed'; } /** Options for {@link gitFfMerge}. */ export interface GitFfMergeOptions { /** * Absolute path to the experiment worktree (the directory that contains the * experiment branch's work tree). Used to derive the experiment ref. */ experimentWorktree: string; /** * Name of the target branch (e.g. `'main'`). The merge is performed inside * the working directory of the target branch — callers must ensure `cwd` * resolves to a worktree that has `targetBranch` checked out. * * The merge command run is: * ``` * git -C merge --ff-only * ``` * where `` is resolved from `experimentWorktree` via * the `cwd` option below, or defaults to `process.cwd()`. */ targetBranch: string; /** * Working directory for git commands. Should be a worktree that has * `targetBranch` checked out. * * Defaults to `process.cwd()`. */ cwd?: string; /** * Override for the git binary path. Defaults to `'git'` (from PATH). * Useful for testing with a fake git script. */ gitBin?: string; } /** * Perform a fast-forward-only git merge of an experiment worktree into the * target branch. * * The merge is the final gating action of the Tier-3 ritual. This function * enforces two invariants: * * 1. **Linear history only** — if `git merge --ff-only` exits non-zero, the * merge is immediately aborted (`git merge --abort`) and * `{ merged: false, reason: 'ff-failed-abort' }` is returned. The caller * MUST resolve the divergence manually before retrying. * * 2. **Kill-switch gates** — the kill switch is checked at `pre-merge` before * any git command is issued, and at `post-merge` after a successful merge. * A `post-merge` kill-switch activation cannot be auto-reverted; the caller * receives `{ merged: true, headSha }` and must handle cleanup. * * @param options - See {@link GitFfMergeOptions}. * @returns {@link MergeResult} describing the outcome. */ export declare function gitFfMerge(options: GitFfMergeOptions): Promise; //# sourceMappingURL=merge.d.ts.map