/** * Verification of a module's declared `requires.telo` range — by RUNNING the CLI * at each edge of it. * * This is the half of declared runtime requirements that cannot live in the * analyzer: it spawns a process and reaches the network, while the analyzer is * browser-safe. It is also a *publishing* concern — an author editing a manifest * needs to know whether their runtime can read a module, not whether someone * else's declaration is honest. * * **Why execution rather than a `since:` table.** The obvious design annotates * every vocabulary entry with the version that introduced it and takes the * maximum over what a manifest uses. That re-creates the discipline problem one * level down — every future additive change must remember its `since`, and * forgetting is silent, which is the failure mode this whole mechanism exists to * remove — and it cannot see a *shape* change (an object where a zone annotation * used to take a pointer, a new key on a closed kernel-owned schema) without a * second annotation mechanism. Running the old CLI is not a prediction of the * property; it IS the property, executed. * * **Two edges bound the whole range**, rather than sampling it, because syntax * support is monotonic: a construct added in 0.43 works in 0.44 and later, one * removed in 0.60 works in 0.59 and earlier. Nothing in the middle can fail * while both edges pass. For a range open above the high edge is HEAD, which * normal CI already checks, so an open declaration costs one run. * * **Infrastructure failure warns; evidence of breakage fails.** A CLI that * cannot be installed (offline, a registry outage) leaves the claim unverified, * and blocking a publish on network reachability trades one failure for a worse * one. A CLI that runs and rejects the manifest is evidence, and evidence is * what this gate is for. * * **A FORWARD-DECLARED lower bound is a third state, not an infrastructure * failure.** The normal way new syntax lands is: a module adopts it and declares * the range of the release that will carry it — a version that, until that * release publishes, does not exist. Spawning `npx @telorun/cli@` * can only ETARGET, and reporting *"could not run"* buries a routine, expected, * self-resolving state under npm's install noise, in the same bucket as being * offline. So the registry is asked FIRST and such an edge is reported * `pending`, skipping a run that has no possible outcome. The latest published * version rides along in the report, because that is what makes a TYPO visible: * `pending against 0.790.0 (latest published: 0.78.0)` reads wrong at a glance, * where a bare "could not run" reads the same for a typo and for tomorrow's * release. * * The states are asymmetric between the two callers, and deliberately. At * `telo release check` a pending edge is informational — the release that * publishes the version has not happened yet, which is the entire point of * declaring the bound before it. At **publish** it is fatal, for the reason an * unpublished UPPER bound is: publication runs npm before modules, so by the * time a module is pushed its declared minimum exists — and if it does not, the * release is out of order and every consumer's `telo upgrade` would refuse the * version it is about to receive. */ import { type VersionRange } from "@telorun/analyzer"; export type EdgeOutcome = /** The edge CLI ran and accepted the manifest. */ { edge: string; status: "passed"; } /** The edge CLI ran and rejected it — the declared range is false. */ | { edge: string; status: "failed"; output: string; } /** The edge names a version NEWER than anything published: there is nothing to * install, and the claim becomes verifiable the moment that version ships. */ | { edge: string; status: "pending"; latestPublished: string; } /** The edge CLI could not be run. The claim is unverified, not disproven. */ | { edge: string; status: "unavailable"; reason: string; }; export interface VerifyRequiresResult { /** Absent when the module declares no `requires.telo` — nothing to verify. */ declared?: VersionRange; outcomes: EdgeOutcome[]; /** True when at least one edge produced evidence the declaration is false. */ refuted: boolean; } /** True when the range names an edge no released CLI can satisfy yet. Read by * `publish`, where it is fatal, and by `release check`, where it is not. */ export declare function hasPendingEdge(result: VerifyRequiresResult): boolean; /** * Verify a module manifest against the edges of its own declared range. * * `manifestPath` is checked, not the module directory, so the caller controls * which document is the subject. A module declaring nothing returns immediately: * absent means no requirement, permanently, for everything published before this * mechanism existed. */ export declare function verifyRequires(manifestPath: string, moduleDoc: Record, options: { currentVersion: string; /** Published `@telorun/cli` versions, for telling a forward-declared edge * from an unreachable one. `null` / omitted when the registry could not be * asked, in which case no edge is classified `pending` — a guess about what * exists is worse than the run's own verdict. */ publishedVersions?: string[] | null; }): Promise; /** * The latest published version when `edge` names something NEWER than it — a * forward-declared bound, whose verification is pending that release rather than * failed or unavailable. `undefined` when the edge exists, when it is older than * the latest (a yanked version is deliberately left to the run, whose "could not * run" is honest about it), or when the registry could not be asked. * * Deciding this from the registry rather than from the spawn's failure is the * whole point: `npx @telorun/cli@` has one possible outcome, and * npm's ETARGET arrives wrapped in install noise that reads exactly like being * offline. */ export declare function unreleasedEdge(edge: string, published: string[] | null): string | undefined; export declare function resetPublishedTeloVersionsCache(): void; export declare function publishedTeloVersions(): Promise; /** The declared upper bound when it names a version the registry does not have — * an unverifiable bound, which the grammar exists to forbid. `undefined` when * the range is open above, the bound exists, or the registry was unreachable. */ export declare function unpublishedUpperBound(declared: VersionRange | undefined, published: string[] | null): string | undefined; //# sourceMappingURL=verify-requires.d.ts.map