/** * Loading hooks-core from a runtime that may have been deleted underneath us. * * WHY THIS IS NOT JUST `import(path)`. The wiki tools are the only place in the * server that resolves a path at CALL time; everything else imports eagerly at * startup and is therefore already in memory. That difference is invisible * until the directory the server is running from disappears -- and it does * disappear: `plugin/launch.mjs` used to prune every runtime version except the * newest, including the one a live session was executing from. Observed * 2026-08-28, a session that outlived one six-hour refresh got * `Cannot find module .../versions/6.0.0/.../hooks-core/wiki.mjs` from every * wiki call for the rest of its life, while all ~65 other tools worked * perfectly. Knowledge capture was silently dead and nothing else looked wrong. * * The prune is fixed. This exists because a bare `import()` failure is still * the wrong shape of answer: * * - it names an internal path and an ESM error code, which reads as a broken * package rather than a missing runtime -- that misreading cost real time, * including a confident and wrong "hooks-core is missing from the published * tarball" (it is not, and never was); * - and it gives up while a perfectly good copy of hooks-core usually sits * next door, under the runtime version the launcher now points at. * * So: try the bundled copy, fall back to the pointed-at runtime when that is * safe, and only then fail -- with a message that says what happened and what * to do about it. */ /** * Whether a runtime copy may stand in for the bundled one. * * SEPARATE AND EXPORTED SO IT CAN BE TESTED FROM BOTH SIDES. Folded into * `fallbackDir` this was unreachable: any fixture that makes the running * version unknown also makes the candidate unreadable, so the candidate check * fired first and a mutation flipping this guard to fail-open survived every * test. * * FAILS CLOSED on an unknown version, either side. If this server's own version * cannot be established there is no way to know whether the candidate is * compatible, and "load it anyway" is the answer that corrupts a shared store. * Refusing costs a restart. That is not hypothetical: the first version of this * skipped the comparison when the running version was null, which is exactly * what a PRUNED runtime produces -- so the guard was disabled in the only * situation the fallback exists for. */ export declare function fallbackIsCompatible(runningVersion: string | null, candidateVersion: string | null): boolean; export declare class HooksCoreUnavailableError extends Error { constructor(moduleName: string, cause: unknown); } /** * Import a hooks-core module by file name, e.g. `wiki.mjs`. * * ONE AT A TIME, AND ONCE EACH. `wikiQuery` asks for seven modules in a single * `Promise.all`, and twenty-four of the twenty-five hooks-core modules import * `staleness.mjs`, so those seven dynamic imports are seven overlapping linkings * of one shared subgraph. Node's own loader tolerates that; a VM-module loader * does not have to, and jest's does not -- it hands the second graph the module * instance the first is still linking, and the import fails with * `request for 'node:fs' can not be resolved on module .../staleness.mjs that is * not linked`. That surfaced as a wiki_query suite that passed alone and failed * in the full run, where the extra load changes the interleaving. * * Serialising costs nothing worth measuring: these are local files, the first * load populates the cache below, and every later call is a resolved promise. * It also removes the duplicated work of re-entering `import()` -- and, with it, * the `existsSync` probes on the failure path -- on every single wiki call. * * A FAILED LOAD IS NOT CACHED. The fallback directory can appear after a refresh * finishes, so a module that was unavailable a minute ago may load now; caching * the rejection would make one badly-timed call permanent for the session. * * Throws `HooksCoreUnavailableError` only when neither the bundled copy nor a * compatible runtime copy can be loaded. */ export declare function loadHooksCore(moduleName: string): Promise; //# sourceMappingURL=hooks-core-loader.d.ts.map