/** * A derived id for the wire contract this build speaks. * * Reticle is installed as separate pieces — the SDK in the page, the daemon, the MCP server the * agent spawns — upgraded independently and therefore drifting constantly. The question that * matters when they meet is not "are these the same release?" but "do these speak the same * contract?", and package-version equality answers it wrongly in both directions: it fires on two * adjacent patch releases where nothing changed, and it stays silent for two different BUILDS of one * version number, which is exactly what a stale daemon and a cached npx package are. * * So this hashes the vocabulary itself. Both sides compute it from their own copy of core, so equal * hashes mean "we agree" whatever the version strings say, and a hash that moved means a name on the * wire genuinely changed. * * Derived on purpose. A hand-maintained contract number is one somebody eventually forgets to bump, * and a forgotten bump is silent skew — the failure this exists to end. */ /** * FNV-1a, 32-bit. Chosen over a crypto hash because this runs in the PAGE: `crypto.subtle` is async * and unavailable on insecure origins, and a dependency is not worth 40 lines. Collisions do not * matter here — the comparison is equality between two builds of the same project, not a security * boundary. */ export declare function fnv1a(input: string): string; /** * Hash a named vocabulary. Keys and values are sorted, so declaration order — which changes for * cosmetic reasons — never moves the fingerprint, while a renamed, added or removed name always does. */ export declare function fingerprintOf(vocabulary: Record): string; /** * The wire vocabulary two pieces must agree on to work together: the message kinds framing every * exchange, the commands the daemon sends the page, the actions it can ask for, and the event types * the page sends back. Everything else in core is shape, defaults or prose — it can change without * either side misunderstanding the other. */ export declare const CONTRACT_FINGERPRINT: string; /** * The same vocabulary, by NAME rather than by hash — what a peer announces so skew can be decided * structurally. * * A hash answers "same" or "different" and nothing else, so it cannot tell an ADDITIVE change from * a breaking one: adding an `ActionType` an older page never needs to know about moves the hash, * and a peer with a pinned SDK is then told "they speak DIFFERENT wire contracts — tools will * behave in ways neither side reports" about a change that breaks nothing. Every peer MUST announce * this list; `describeSkew` falls back to the hash branch when nothing produces it. * * `messageKinds` is deliberately absent: it frames the envelope rather than naming a capability, so * a peer that did not know a message kind could not have parsed the message carrying this list. */ export declare const CONTRACT_PARTS: { readonly commands: readonly string[]; readonly events: readonly string[]; readonly actions: readonly string[]; };