// Task 278 — derive `effectivePermissionMode` from the Claude Code binary's
// `--debug=auto-mode --debug-file=<path>` per-session capture. The 2.1.150
// binary writes one line per `[auto-mode] verifyAutoModeGateAccess` call:
//
//   <timestamp> [DEBUG] [auto-mode] verifyAutoModeGateAccess:
//     enabledState=<opt-in|enabled|disabled|...>
//     disabledBySettings=<bool>
//     model=<id> modelSupported=<bool>
//     disableFastModeBreakerFires=<bool>
//     carouselAvailable=<bool> canEnterAuto=<bool>
//
// `enabledState` is the runtime ground truth. On auto-mode spawns the
// binary may write `enabledState=opt-in` despite the `--permission-mode
// auto` flag (the silent-downgrade case Task 278 was filed for); the
// JSONL `permission-mode` record continues to carry the REQUESTED mode
// regardless. So the JSONL is not a usable signal; this file is.
//
// Mapping (effective mode given requested + enabledState):
//   requested=auto, enabledState=enabled         -> effective=auto       (matches)
//   requested=auto, enabledState=anything else   -> effective=default    (downgrade)
//   requested != auto                            -> effective=requested  (no debug line written)
//
// Stateless on purpose. The file is at most a few hundred bytes for an
// active session (one line per gate-check; shift-tab transitions add
// more). We read the whole file on every modify event and look at the
// LAST gate-check line. Comparing against the sidecar lets the http-
// server skip a sidecar write when the effective mode hasn't changed
// from what's already persisted.
import { existsSync, readFileSync } from 'node:fs';
const AUTO_MODE_LINE = /\[auto-mode\] verifyAutoModeGateAccess: enabledState=(\S+)/;
/** Pure: derive effective mode from log content + spawn-time requested mode.
 *  Returns null when the file has no parseable gate-access line yet (race
 *  between spawn and first read). For non-auto spawns this returns the
 *  requested mode verbatim since no debug capture exists. */
export function deriveEffectiveMode(logContent, requestedMode) {
    if (requestedMode !== 'auto')
        return requestedMode;
    // Walk lines in reverse so the LAST gate-check wins; shift-tab inside
    // the PTY appends a fresh line that supersedes the spawn-time check.
    const lines = logContent.split('\n');
    for (let i = lines.length - 1; i >= 0; i -= 1) {
        const m = AUTO_MODE_LINE.exec(lines[i]);
        if (m === null)
            continue;
        const enabledState = m[1];
        return enabledState === 'enabled' ? 'auto' : 'default';
    }
    return null;
}
export function createPermissionModeTail(deps) {
    return {
        deriveFromFile(sessionId, logPath, requestedMode) {
            if (!existsSync(logPath))
                return null;
            let raw;
            try {
                raw = readFileSync(logPath, 'utf8');
            }
            catch (err) {
                deps.logger(`[permission-mode-tail] read-failed sessionId=${sessionId.slice(0, 8)} path=${logPath} err=${err instanceof Error ? err.message : String(err)}`);
                return null;
            }
            const effective = deriveEffectiveMode(raw, requestedMode);
            if (effective !== null) {
                deps.logger(`[permission-mode-tail] derived sessionId=${sessionId.slice(0, 8)} requested=${requestedMode} effective=${effective}`);
            }
            return effective;
        },
    };
}
//# sourceMappingURL=permission-mode-tail.js.map