export type Logger = (line: string) => void; export interface SkillRecord { /** Skill directory basename (the `` in .../skills//SKILL.md). */ skillName: string; isPremium: boolean; /** For premium records, the enabledPlugins key that owns the skill; null for * platform records (which every session can invoke). */ subName: string | null; mtimeMs: number; } /** One record per `//skills//SKILL.md`. Platform * skills are install-wide: every live session can invoke them, so subName is * null. A missing root or unreadable subdir yields no records for it. */ export declare function collectPlatformSkillMtimes(pluginsRoot: string): SkillRecord[]; /** One record per premium SKILL.md, tagged with the sub-plugin name that is its * enabledPlugins key. Mirrors buildSubToMarketplace's descent: a nested sub at * `/plugins//PLUGIN.md` owns `/plugins//skills/*` * with subName=; a standalone bundle at `/PLUGIN.md` (no * `plugins/` subdir) owns `/skills/*` with subName=. */ export declare function collectPremiumSkillMtimes(premiumRoot: string): SkillRecord[]; /** Epoch-ms process start time from `/proc//stat` + `/proc/stat`. * starttime is field 22 of the pid stat line (ticks since boot); the comm * field (2) can contain spaces and ')', so fields are counted after the final * ')'. Returns null when either input lacks its field. hz defaults to 100 * (Linux USER_HZ). Linux-only, which is where detached survivors exist. */ export declare function parseProcStartMs(procPidStat: string, procStatBlob: string, hz?: number): number | null; /** The greatest-mtime SKILL.md the session can invoke: every platform record, * plus premium records whose subName is in the session's enabledPlugins. * Null when that set is empty (a session with no invokable skills at all). */ export declare function selectBeatingSkill(records: readonly SkillRecord[], enabledPlugins: ReadonlySet): SkillRecord | null; export declare function formatStaleSession(f: { sessionId: string; sessionClass: 'owned' | 'survivor'; spawnedAtMs: number; skill: SkillRecord; }): string; export interface LiveSessionRef { sessionId: string; sessionClass: 'owned' | 'survivor'; /** Process start time (ms): trackerRegisteredAtMs for owned, parseProcStartMs * for survivors. */ spawnedAtMs: number; enabledPlugins: ReadonlySet; } export interface SkillStalenessAuditDeps { intervalMs: number; logger: Logger; /** All platform + premium SKILL.md records this tick. */ collectRecords: () => SkillRecord[]; /** Every live session with a resolved spawn time and enabledPlugins. */ listSessions: () => LiveSessionRef[]; } export interface SkillStalenessAudit { start(): void; stop(): void; tickOnce(): void; } export declare function createSkillStalenessAudit(deps: SkillStalenessAuditDeps): SkillStalenessAudit; /** enabledPlugins for a resolved account, as a set; empty for a null/unknown * account (the platform layer still applies to that session). */ export declare function resolveEnabledPlugins(accountId: string | null, accountsRoot: string): ReadonlySet; export interface SessionEnumIo { ownedSessions: Array<{ sessionId: string; pid: number; }>; ownedSpawnMs: (sessionId: string) => number | undefined; survivorRows: Array<{ sessionId: string; pid: number; }>; survivorSpawnMs: (pid: number) => number | undefined; enabledPluginsFor: (sessionId: string) => ReadonlySet; } /** Union owned PTYs (spawn time from the tracker clock) and detached-survivor * rows (spawn time from /proc), skipping any whose spawn time is unresolved. * An owned session shadows a survivor row with the same id (a session cannot * be both; owned is authoritative). */ export declare function buildLiveSessionRefs(io: SessionEnumIo): LiveSessionRef[]; //# sourceMappingURL=skill-staleness-audit.d.ts.map