/** * active-skill-resolver — utility for hook enforcers. * * Resolves the active peak skill name for the current session, so hook * enforcers (e.g. code-ban) can decide whether to fire. * * Slice 4.0.8 (D1 + D4a): prefer the canonical * `readPresenceLease` projection from `presence-lease-service.ts`. * The 4.0.7 legacy `active-skill-.json` walk is preserved * as a 1-minor-release back-compat fallback, gated on the * `legacyPresence: true` opt-in. By default the canonical projection * is the only source of truth — the read returns `{ skill, callerId, * sessionId, source: 'canonical' | 'legacy' | 'none' }`. * * Per `src/services/session/caller-id-types.ts`: the active-skill file is * at `.peaks/_runtime//active-skill-.json` * (legacy) or `.peaks/_runtime//presence-index/.json` * (canonical index → lease file). * * Resolution order (graceful degradation — never throws): * 1. PEAKS_ACTIVE_SKILL env var (explicit override, used by tests) * 2. Canonical lease projection (presence-lease-service.readPresenceLease) * 3. Legacy `.peaks/_runtime//active-skill-*.json` walk, when * `legacyPresence === true` is passed by the caller * 4. null (caller did not set a skill; enforcers can decide to skip) */ export interface ActiveSkillResolution { readonly skill: string | null; readonly callerId: string | null; readonly sessionId: string | null; /** * Mode token recorded on the canonical lease (e.g. `full-auto`, * `assisted`, `strict`, `24h`). Normalized on read: a legacy * on-disk `'swarm'` surfaces as `'full-auto'` (slice * `canonical` (the legacy `active-skill-*.json` files do not * surface a mode field, and the `env` / `none` cases are test * statusline can render the orchestrator's mode alongside the * active leaf role. */ readonly mode: string | null; /** `canonical` = presence-lease-service; `legacy` = per-caller active-skill file; `env` = test override; `none` = nothing wired. */ readonly source: 'env' | 'file' | 'canonical' | 'none'; } /** * Resolve the active peak skill for the current hook invocation. * * Reads PEAKS_ACTIVE_SKILL first (test override), then the canonical * lease projection (RD §4 / §6 — the lease + index is the source of * truth in 4.0.8), then — only when the caller explicitly opts in via * `legacyPresence: true` — the legacy `.peaks/_runtime//active-skill-*.json` * walk. Returns the first match. */ export declare function resolveActiveSkillForCaller(projectRoot: string, opts?: { legacyPresence?: boolean; callerId?: string | null; }): ActiveSkillResolution; /** * Whether any in-flight lease in this session carries a `peaks-*` skill. * * Independent of `resolveActiveSkillForCaller` on purpose: that function is * the one under suspicion when the identity cannot be resolved, so asking it * whether peaks is present would be circular. Fails open — a bug in peaks * must not brick the harness. */ export declare function hasPeaksLeaseInSession(projectRoot: string): boolean; /** * Whether this caller owns at least one in-flight lease in the session. * * `resolveActiveSkillForCaller` cannot answer this: it returns * `{ skill: null, source: 'none' }` both when a caller has no lease and when * the id handed over is not the lease's key. Those two need different * decisions, so the call site asks directly. */ export declare function hasLeaseForCaller(projectRoot: string, callerId: string): boolean;