/** * Revert Executor — squashed git revert + revert event write. * * Executes `git revert --no-edit --no-commit ` over the commit list * collected by {@link collectMergeCommits}, commits the result as a single * squashed revert commit, writes a `kind:'revert'` sentient event, and sets * the global pause flag via {@link pauseAllTiers}. * * ## Human-commit guard * * Before executing the revert, `detectHumanCommits` inspects each commit in * the range using `git log --format="%H %ae"`. Any commit whose author email * does NOT match the daemon's sentient identity pubkey prefix is flagged as * a human commit. When human commits are detected and `includeHuman = false` * (the default), the executor aborts with a descriptive error. * * ## Safety * * - `receiptId` and commit SHAs are passed as separate arguments to * `child_process.spawn` — never shell-interpolated. * - The revert commit message is constructed in process; no user input is * passed through to shell. * * @see DESIGN.md §8 T1012-S2 * @task T1038 */ import type { AgentIdentity } from 'llmtxt/identity'; import type { MergeEvent } from './events.js'; /** Human commit detected in revert range when `includeHuman = false`. */ export declare const E_HUMAN_COMMIT_IN_RANGE = "E_HUMAN_COMMIT_IN_RANGE"; /** The revert git operation itself failed (non-zero exit). */ export declare const E_REVERT_FAILED = "E_REVERT_FAILED"; /** The sentient agent email used in commit authorship. */ export declare const SENTIENT_AUTHOR_EMAIL = "sentient@cleocode"; /** * Options for {@link executeSquashedRevert}. */ export interface ExecuteSquashedRevertOptions { /** Absolute path to the project / git repository root. */ cleoRoot: string; /** Commit SHAs to revert, oldest first (from {@link collectMergeCommits}). */ commits: string[]; /** The merge events corresponding to the commit list. */ mergeEvents: MergeEvent[]; /** The receiptId of the starting event (used in the commit message). */ fromReceiptId: string; /** Signing identity for the revert sentient event. */ identity: AgentIdentity; /** * When `true`, allows reverting a range that contains commits not authored * by the sentient agent. When `false` (default), aborts if any human commit * is detected. */ includeHuman?: boolean; } /** * Result returned by {@link executeSquashedRevert}. */ export interface ExecuteSquashedRevertResult { /** The new squashed-revert commit SHA (HEAD after the revert commit). */ revertCommitSha: string; /** The commit SHAs that were reverted. */ revertedRange: string[]; /** Whether any human commit was present (and was allowed via includeHuman). */ humanCommitPresent: boolean; /** The receiptId of the `kind:'revert'` event written to the audit log. */ revertEventReceiptId: string; } /** * Execute a squashed git revert over the given commit list. * * Steps: * 1. Validate the commit list is non-empty. * 2. Check for human commits in the range; abort if found and `!includeHuman`. * 3. Run `git revert --no-edit --no-commit ^..`. * 4. Run `git commit` with the canonical revert message. * 5. Capture the new HEAD SHA. * 6. Write a `kind:'revert'` sentient event. * 7. Set `pausedByRevert = true` via {@link pauseAllTiers}. * * @param opts - Revert options. * @returns The result including the new revert commit SHA. * @throws `E_HUMAN_COMMIT_IN_RANGE` if human commits are present and `!includeHuman`. * @throws `E_REVERT_FAILED` if the git revert or commit operation fails. * * @example * ```ts * const result = await executeSquashedRevert({ * cleoRoot: '/home/user/project', * commits: ['sha1', 'sha2', 'sha3'], * mergeEvents: [...], * fromReceiptId: 'ABC123receiptId', * identity, * }); * console.log('Reverted to:', result.revertCommitSha); * ``` */ export declare function executeSquashedRevert(opts: ExecuteSquashedRevertOptions): Promise; //# sourceMappingURL=revert-executor.d.ts.map