/** * Worktree completion SDK — auto-invoke `worktree-complete` post-success (T9548). * * Exposes {@link completeWorktreeForTask}, the high-level SDK entry point used * by {@link orchestrateSpawnExecute} to integrate a worker's worktree back to * the project default branch after a successful spawn returns. Also used by * the `cleo orchestrate worktree-complete ` CLI command. * * Idempotent semantics: * * - Re-invoking on a completed worktree is a **no-op**. The function inspects * `.cleo/audit/worktree-lifecycle.jsonl` for the most-recent `complete` * entry for the task; if found, a `complete-skip` audit row is appended * and an explanatory envelope is returned. * - Branch / worktree absence is also treated as already-complete (cleanup * already happened or the worker did not produce any commits). * * Merge-conflict semantics (ADR-062): * * - On merge / rebase failure, the worktree is **preserved** (NOT pruned). * The function returns an error envelope describing the recovery path, * and writes a `complete-conflict` audit row. Operators resolve manually * by entering the worktree, fixing conflicts, then re-running with * `--resolve manual` to mark the worktree as handled. * * Manual resolve mode: * * - `opts.resolve === 'manual'` skips the merge attempt entirely. The * function writes a `complete-manual` audit row and returns success. * Use this AFTER you have manually merged / cherry-picked the worktree * contents back to the target branch. * * All git operations follow ADR-062: `git merge --no-ff` is the only * canonical integration strategy. Cherry-pick is forbidden — it destroys * commit SHAs and breaks `git log --grep ""` traceability. * * @task T9548 * @epic T9515 — worktree-lifecycle bug-fix epic (4 of 5) * @adr ADR-062 */ import type { WorktreeLifecycleState } from '@cleocode/contracts'; import { type WorktreeIntegrationResult } from '../spawn/branch-integration.js'; import { WORKTREE_LIFECYCLE_AUDIT_FILE } from '../worktree/audit.js'; /** * Conflict-recovery strategy passed to {@link completeWorktreeForTask}. * * - `'auto'` (default) — attempt the canonical `git merge --no-ff` flow. On * conflict the worktree is preserved and an error envelope is returned. * - `'manual'` — skip the merge attempt entirely. The caller asserts they * have already resolved the integration manually. A `complete-manual` * audit row is written and the function returns success. * * @task T9548 */ export type WorktreeCompleteResolveMode = 'auto' | 'manual'; /** * Options for {@link completeWorktreeForTask}. * * Mirrors the {@link completeAgentWorktreeIntegration} options surface plus * the T9548-specific `resolve` + audit-path overrides. * * @task T9548 */ export interface CompleteWorktreeForTaskOpts { /** Override the resolved default branch (test fixtures + integration calls). */ targetBranch?: string; /** Task title to embed in the merge commit subject. */ taskTitle?: string; /** Skip the `git fetch origin` step (test fixtures, offline runs). */ skipFetch?: boolean; /** Conflict-recovery strategy. Default `'auto'`. */ resolve?: WorktreeCompleteResolveMode; /** * Override the `worktree-integration.jsonl` path (testing). When omitted * `.cleo/audit/worktree-integration.jsonl` under `projectRoot` is used. */ integrationAuditPath?: string; /** * Override the `worktree-lifecycle.jsonl` path (testing). When omitted * `.cleo/audit/worktree-lifecycle.jsonl` under `projectRoot` is used. */ lifecycleAuditPath?: string; } /** * Envelope returned by {@link completeWorktreeForTask}. * * Mirrors the {@link WorktreeIntegrationResult} fields plus a discriminating * `outcome` tag and a `recovery` block surfaced when a merge conflict * preserved the worktree. * * @task T9548 */ export interface CompleteWorktreeForTaskResult { /** Task ID the call targeted. */ taskId: string; /** * What happened: * * - `merged` — auto-merge succeeded; worktree pruned. * - `noop` — idempotent skip (worktree was already integrated, or no * commits to merge). * - `manual` — `resolve: 'manual'` was set; audit row written, no merge. * - `conflict` — auto-merge failed; worktree preserved for manual recovery. */ outcome: 'merged' | 'noop' | 'manual' | 'conflict'; /** Underlying integration result when an auto-merge was attempted. */ integration: WorktreeIntegrationResult | null; /** The task's worktree as completion saw it before acting (T10871). */ state: WorktreeLifecycleState; /** Human-readable reason — surfaced in CLI envelopes and audit rows. */ reason: string; /** * Recovery instructions populated when `outcome === 'conflict'`. Used by * the CLI to render an actionable error message to the operator. */ recovery?: { /** The worktree path that was preserved. */ worktreePath: string; /** Task branch that needs manual resolution. */ branch: string; /** Ordered list of recovery steps. */ steps: readonly string[]; }; } /** * Complete the worktree integration lifecycle for a task. * * Called automatically by {@link orchestrateSpawnExecute} after a worker * spawn returns a success result. Also invokable directly via * `cleo orchestrate worktree-complete `. * * Behaviour: * * 1. **Manual resolve** — when `opts.resolve === 'manual'`, write a * `complete-manual` audit row and return success without touching git. * 2. **Idempotent check** — if a prior `complete` audit row exists for * the task, return `outcome: 'noop'` and append `complete-skip` to the * lifecycle audit log. * 3. **Auto merge** — delegate to {@link completeAgentWorktreeIntegration} * (ADR-062 `git merge --no-ff`). On success write `complete` audit row. * 4. **Conflict** — when the merge fails, the worktree is **preserved** * (no prune attempt). A `complete-conflict` audit row is written and * the envelope's `recovery` block describes the manual recovery path. * * @param taskId - Task ID whose worktree should be integrated. * @param projectRoot - Absolute path to the project root. * @param opts - Optional behaviour overrides. * @returns Envelope describing what happened. * * @task T9548 * @adr ADR-062 */ export declare function completeWorktreeForTask(taskId: string, projectRoot: string, opts?: CompleteWorktreeForTaskOpts): CompleteWorktreeForTaskResult; /** * Audit log file (relative to project root) used by completeWorktreeForTask. * * Re-exported for tests + downstream consumers that need to assert on the * canonical path. * * @task T9548 */ export { WORKTREE_LIFECYCLE_AUDIT_FILE }; /** * Environment variable that, when set to a truthy value (`'1'`, `'true'`, * any non-empty string other than `'0'` / `'false'`), switches off the worktree * integration `cleo complete` runs, like `--no-integrate` (T14053). * * Use this for manual flows where the operator wants to inspect the worktree * before integration, or for CI smoke tests that exercise `cleo complete` * without touching the agent worktree tree. * * @task T9548 */ export declare const AUTO_WORKTREE_COMPLETE_ENV = "CLEO_NO_AUTO_WORKTREE_COMPLETE"; /** * Read the env-var skip toggle. Treats `'0'`, `'false'`, `''`, and an absent * env-var as opt-in (auto-complete ENABLED). Any other non-empty value is * treated as opt-out (auto-complete DISABLED). * * Centralising the parse here lets callers and tests share one truth-table. * * @task T9548 */ export declare function isAutoWorktreeCompleteDisabled(env?: NodeJS.ProcessEnv): boolean; /** * Why completion leaves the task's worktree branch alone, or `undefined` when * it integrates: `--no-integrate` first, then {@link AUTO_WORKTREE_COMPLETE_ENV}. * `cleo complete` and `cleo done --plan` share it, so both say the same (T14053). * * @param noIntegrate - Whether `--no-integrate` was passed. * @param env - Environment to read (defaults to `process.env`). * @returns The skip reason, or `undefined`. * * @example * ```ts * integrationDisabledReason(true); // '--no-integrate was passed; …' * ``` * @task T14053 */ export declare function integrationDisabledReason(noIntegrate: boolean | undefined, env?: NodeJS.ProcessEnv): string | undefined; /** * Audit a spawn auto-complete skipped by {@link AUTO_WORKTREE_COMPLETE_ENV}: * a `complete-skip` row with `reason: 'env-override'` in the lifecycle audit * log (worktree-lifecycle MUST-19). The worktree and branch are untouched. * * @param taskId - Task whose auto-complete was skipped. * @param projectRoot - Absolute path to the project root. * @param lifecycleAuditPath - Override for the lifecycle audit log (tests). * @task T14057 */ export declare function recordAutoCompleteEnvSkip(taskId: string, projectRoot: string, lifecycleAuditPath?: string): void; //# sourceMappingURL=worktree-complete.d.ts.map