/** * Project-ref resolution — the ONE door (P4-lite W3). * * A project ref can name a project on ANY pod the user can see, resolved via * the Control Plane directory (`GET /projects/resolve?ref=`). Every command * that accepts a project ref parses + resolves it HERE — no second ref parser * anywhere. * * Ref forms (ratified): * - uuid → local: today's behavior, pinned against the active pod * - `/` → canonical cross-pod form (e.g. perso/synap) * - bare `` → resolved when unique across visible pods; 300-ambiguous otherwise * * The directory is an ACCELERATOR, not a dependency: CP unreachable, not * logged in, or 404 all degrade to a graceful message — the uuid path never * touches the CP and keeps working. */ export type ParsedProjectRef = { kind: "uuid"; id: string; } | { kind: "fq"; pod: string; slug: string; } | { kind: "slug"; slug: string; } | { kind: "invalid"; reason: string; }; export declare function parseProjectRef(raw: string): ParsedProjectRef; /** One resolved project, as the CP directory returns it (200). */ export interface CpProjectResolution { projectId: string; /** Nullable in the CP mirror (pre-slug rows); render with a fallback. */ slug: string | null; name: string; podId: string; podUrl: string; grant?: unknown; } /** A 300-ambiguous candidate — same shape, rendered as `pod/slug` hints. */ export type CpProjectCandidate = Partial; export type ProjectRefResolution = /** uuid ref — no CP involved; caller keeps today's active-pod behavior. */ { kind: "local"; projectId: string; } | { kind: "resolved"; project: CpProjectResolution; refPod?: string; } | { kind: "ambiguous"; candidates: CpProjectCandidate[]; } | { kind: "not-found"; ref: string; } | { kind: "not-active"; ref: string; status: string; } | { kind: "not-logged-in"; } | { kind: "cp-error"; message: string; } | { kind: "invalid"; reason: string; }; /** Injectable seams for tests — production callers pass nothing. */ export interface ResolveDeps { fetchImpl?: typeof fetch; getToken?: () => { token: string; } | null; cpUrl?: string; } /** * Resolve a project ref. uuid short-circuits to `local` (today's behavior); * everything else goes through the CP directory with the CLI's CP credentials. */ export declare function resolveProjectRef(raw: string, deps?: ResolveDeps): Promise; /** True when two pod URLs name the same origin (scheme+host+port). */ export declare function samePodOrigin(a: string | undefined, b: string | undefined): boolean; /** * Session-lens guard: the per-Claude-session lens has NO pod field, so a * `--session` pin can only target a project on the ACTIVE pod. Returns the * refusal message for a cross-pod ref, or null when the pin is allowed. */ export declare function sessionScopeRefusal(project: CpProjectResolution, activePodUrl: string | undefined): string | null; /** `pod/slug` label for a candidate row, degrading to whatever fields exist. */ export declare function candidateLabel(c: CpProjectCandidate): string;