/**
 * Session-id resolution for hook binaries + the `.current-session` pointer.
 *
 * ROOT-CAUSE FIX (2026-05-26): the `stop` / `user-prompt-submit` /
 * `pre-tool-use` hooks previously read the session id ONLY from
 * `process.env.CLAUDE_SESSION_ID`, which Claude Code does not reliably set —
 * it delivers `session_id` in the hook's stdin JSON payload (per the CC hook
 * contract). The result: every session collapsed to the literal `'unknown'`
 * bucket, so per-session state (the automation flag, the per-turn tool ledger)
 * never keyed on the real session. `session-end.ts` was the only hook reading
 * stdin correctly. `extractSessionId` centralizes the correct precedence:
 * stdin `session_id` (snake) → `sessionId` (camel) → `CLAUDE_SESSION_ID` env
 * (last-resort) → `'unknown'`.
 *
 * `.current-session` (at `OPENSQUID_HOME()/.current-session`) lets an
 * out-of-band process — notably the `opensquid automation on|off` CLI run from
 * a terminal that never receives the hook stdin — discover the live session id.
 * The `user-prompt-submit` hook records it every turn (best-effort).
 *
 * Imports from: node:fs/promises, node:path, ../paths.js.
 * Imported by: hooks/{stop,user-prompt-submit,pre-tool-use}.ts (resolve +
 *   record); setup/cli/automation.ts (read).
 */
/**
 * Resolve the session id from a hook's raw stdin string. Precedence:
 * stdin `session_id` → stdin `sessionId` → `CLAUDE_SESSION_ID` env → `'unknown'`.
 * Never throws: a malformed/empty payload falls straight through to the env /
 * `'unknown'` fallback so the calling hook stays fail-open.
 */
export declare function extractSessionId(raw: string): string;
/** Absolute path of the live-session pointer file. */
export declare const currentSessionPath: () => string;
/**
 * Record the live session id so out-of-band processes (the automation CLI) can
 * target the session the hooks actually see. Best-effort: never throws, and
 * never records the `'unknown'` sentinel (that would mislead the CLI).
 */
export declare function recordCurrentSession(sessionId: string, cwd?: string): Promise<void>;
/** Read the global live session id, or `null` if absent/unreadable/empty. */
export declare function readCurrentSession(): Promise<string | null>;
/** Read the project-scoped live session id, or `null` if absent/unreadable/empty. */
export declare function readProjectCurrentSession(projectUuid: string): Promise<string | null>;
/**
 * Session resolution for MCP tools (the MCP server is a separate process from
 * the hooks, so it can't read hook stdin).
 *
 * T-RJ-FOLLOWUPS FU.3 (2026-06-01) — CORRECTION to MS.1. MS.1 assumed Claude
 * Code sets `CLAUDE_SESSION_ID` in the MCP server's env; it does NOT — that
 * exact name is never set, so the env step never fired and resolution always
 * fell through to the GLOBAL `.current-session`, which any concurrent session in
 * any project clobbers (last-writer-wins) — silently breaking this session's
 * `log_phase` mid-task.
 *
 * FU.4 correction: CC DOES expose a session-id env var to stdio MCP servers —
 * `CLAUDE_CODE_SESSION_ID` (plus `CLAUDE_PROJECT_DIR`). But it is NOT safe to key
 * on: under `--resume` it holds a NEW id that differs from the persisted /
 * transcript / hook-stdin id the state actually lives under (observed live:
 * env `6c7527de…` while state + transcript were under `1200bc00…`, whose
 * `sessions/<id>/` dir is the real one). So resolving by the env session id
 * would point at an EMPTY session under resume. The project-scoped pointer is
 * correct precisely because the UPS hook writes it with the hook-stdin id — the
 * same id the state uses. (Using `CLAUDE_CODE_SESSION_ID` *guarded by
 * `sessions/<id>/` existence* to also kill the same-project race is FU.7.)
 *
 * Fix: resolve via the PROJECT-SCOPED pointer, keyed by `CLAUDE_PROJECT_DIR`
 * (which CC DOES provide) → `resolveProjectUuid`. A concurrent session in
 * another repo writes a different project's pointer and can't clobber this one.
 *
 * ⚠️ Residual (documented, not solved here): two concurrent CC sessions in the
 * SAME project still share one project pointer and race. Rare; a
 * most-recently-active-task tiebreak is a follow-up.
 *
 * Precedence:
 *   1. `process.env.CLAUDE_SESSION_ID` (kept — harmless if CC ever sets it)
 *   2. `process.env.OPENSQUID_SESSION_ID` (override / test seam)
 *   3. `process.env.CLAUDE_CODE_SESSION_ID` GUARDED by `sessions/<id>/` existence
 *      (FU.7) — CC's per-process id. When its session dir exists it is a real
 *      persisted session, which disambiguates two concurrent sessions in the
 *      SAME repo (distinct per-process ids → distinct dirs). Under `--resume`
 *      the env id is NEW and has no dir → the guard fails → fall through (safe).
 *   4. project-scoped pointer via `CLAUDE_PROJECT_DIR`→`resolveProjectUuid`
 *      (race-free across projects — the real fix)
 *   5. global `.current-session` (back-compat: single-session / no-project cwd)
 */
export declare function resolveMcpSessionId(): Promise<string | null>;
//# sourceMappingURL=session_id.d.ts.map