/** * GC daemon expressed as a supervised daemon subsystem. * * Wraps the GC bootstrap logic (`bootstrapDaemon`, crash recovery, missed-run * recovery, and the node-cron schedule) in the uniform * `start → healthProbe → shutdown` lifecycle from `@cleocode/contracts/daemon` * so the `@cleocode/runtime` `SubsystemRegistry` can drive it identically to * every other long-running concern (Studio supervision, the web server, …). * * Design constraints * ------------------ * `@cleocode/core` CANNOT depend on `@cleocode/runtime` (runtime already * depends on core). To remain dependency-cycle free this module imports only * the pure type contracts from `@cleocode/contracts` and returns a plain * frozen object that satisfies the `Subsystem` interface * without calling `defineSubsystem()` (a runtime-layer factory). A caller that * holds a `SubsystemRegistry` (from `@cleocode/runtime/daemon`) simply calls * `registry.register(createGcSubsystem(cleoDir))` — the frozen shape is * identical to what `defineSubsystem` returns and the registry types accept it. * * Thread-through context * ---------------------- * `start()` returns a {@link GcSubsystemContext} that is threaded into * `shutdown()` by the registry (same pattern as `GatewaySubsystemContext` * in `@cleocode/runtime/gateway`). This lets `shutdown()` cancel the exact * cron task that `start()` scheduled without requiring module-level mutable * state. * * @see packages/core/src/gc/daemon.ts — standalone bootstrap / spawn helpers * @see packages/runtime/src/daemon/define-subsystem.ts — `defineSubsystem` factory * @see packages/runtime/src/gateway/daemon-subsystem.ts — reference implementation * * @packageDocumentation * @module @cleocode/core/gc * * @task T11503 (R5-T1) * @task T11504 (R5-T2) * @epic T11256 * @saga T11243 SG-RUNTIME-UNIFICATION */ import type { Subsystem } from '@cleocode/contracts'; /** * The live context `start()` returns and the registry threads into * `shutdown()`. Carries the scheduled cron task so `shutdown()` can destroy * exactly the task that `start()` created. */ export interface GcSubsystemContext { /** The OS pid of this daemon process (set at subsystem start). */ readonly pid: number; /** The ISO-8601 timestamp when this subsystem started. */ readonly startedAt: string; /** * The scheduled cron task. `ScheduledTask` is the node-cron return value. * Typed as the minimal destroy surface so callers do not need to import * node-cron types. */ readonly cronTask: { destroy: () => void; }; /** Count of GC runs performed since subsystem start. */ runs: number; } /** * Create a GC cron-daemon expressed as a uniform daemon subsystem. * * The returned object is a frozen `Subsystem` that any * `SubsystemRegistry` (from `@cleocode/runtime/daemon`) can `register()`. * * Lifecycle * --------- * - `start(cleoDir)` — reads gc-state.json, performs crash recovery * (resumes `pendingPrune` if non-empty), performs missed-run recovery (runs * GC immediately if elapsed > 24 h), then schedules the daily cron job. * Returns a {@link GcSubsystemContext} for health-probe and shutdown. * - `healthProbe()` — reports a single {@link SubsystemHealth} row keyed on * `child_id: 'gc'`; `running` while the cron task is active, with a `detail` * summarising run count and last-run timestamp. * - `shutdown(context)` — destroys the cron task so the daemon process can * exit cleanly. * * @param cleoDir - Absolute path to the `.cleo/` directory for this project. * @returns A frozen `Subsystem`. * * @example * ```ts * // In the daemon process: * import { SubsystemRegistry } from '@cleocode/runtime/daemon'; * import { createGcSubsystem } from '@cleocode/core/gc/gc-subsystem.js'; * * const registry = new SubsystemRegistry(); * registry.register(createGcSubsystem('/home/user/.local/share/cleo/project/abc/.cleo')); * await registry.startAll(); * ``` */ export declare function createGcSubsystem(cleoDir: string): Subsystem; //# sourceMappingURL=gc-subsystem.d.ts.map