import { EffectiveTree } from './effective-tree'; import { BlockedResult } from './types'; /** * L1: the directory this command would run in DOES NOT EXIST. * * THE INCIDENT (reproduced from a transcript, 0.4.603). A subagent was launched with its cwd inside * `/.claude/worktrees/agent-a5931637c5bff6d6d`. Mid-session another agent's cleanup REAPED that * worktree. The shell's cwd still named a path that was now gone. * * `classify()` asked git for the toplevel, got `null` — and `null` meant two completely different * things: "this is not a git directory" and "this directory does not exist". Conflating them classified * the dead path as the PRIMARY clone, so force-to-root fired and printed: * * ❌ Run git/gh commands from the repo root, not a subdirectory. * Command runs in: /.claude/worktrees/agent-a5931637c5bff6d6d * Judged against: * cd '' && cd /.claude/worktrees/agent-… && git fetch … * * Three things wrong at once: the diagnosis (it is not a subdirectory, it is GONE), the tone (it reads * as a scolding for a mistake nobody made), and the remedy (it ends inside the deleted directory, so it * cannot satisfy the check — the retry re-fires with the prefix doubled, then tripled). Three rounds * were burned before `git worktree list` made the real state visible. * * So the fix is a DISTINCT tree kind with its own message. Naming the state is most of the cure: an * agent that is told the directory is gone stops trying to `cd` into it. The remedy deliberately routes * through the governed root and drops the command's own leading `cd`, so it can never point back at the * dead path — the same convergence property `remedyAtRoot` gives force-to-root. * * The lost-work line is not padding. A reaped worktree takes uncommitted changes with it, and an agent * that silently retries at the root will otherwise report success on work that no longer exists. */ export declare class MissingDirectoryGuard { private readonly resolver; /** The deny report, or null to allow. */ block(command: string, tree: EffectiveTree): string | null; private report; } export declare function missingDirectoryBlock(command: string, tree: EffectiveTree): BlockedResult | null;