import type { VendoStore } from "./store.js"; /** * Build contract §1.3 — `turn.state`, made durable. * * The runtime ships a process-lifetime reference implementation, which is * honest for a disposable session id and useless for a session-OWNING harness: * `claudeCode()` reads its native session on the turn AFTER the one that wrote * it, so a restart (or a second replica) meant a re-seed on every turn. * * The state lives on the THREAD ROW — `vendo_threads.harness_state` (v12) — and * that is the whole design. It rode `vendo_state` under a synthetic `app_id` * before, which bought "no new table" at the price of a slot no table cascade * covered: thread deletion swept it by hand in two places, a retention sweep * needed a fence to keep the app-state door from seeing it, and the erase * cascade reached it only through a second selector. On the thread row, every * one of those is simply the row going away. * * ONE slot per thread carrying its owner's name, exactly as the interface says: * a foreign harness DESTROYS the row rather than shadowing it, so swapping back * cannot resurrect a session the conversation has outgrown. * * Typed structurally rather than against `HarnessStateStore` because the store * sits BELOW `@vendoai/harnesses` in the layering (contract §2) — the shape is * the contract, as it is for `threadMessageStore`. */ /** The slot's stored payload. Spelled ONCE because three writers land it: both * backends' `set`, and a batched turn commit, which carries the row itself * rather than calling `set` — a second spelling would be a slot one writer * could no longer read. */ export declare const harnessStateRow: (harnessName: string, value: string) => { harness: string; value: string; }; export interface HarnessStateStore { /** `owner` is the thread row's own `subject`, passed when the caller has * ALREADY read the row this verb would otherwise re-fetch to learn it (the * ops backend's `ownerOf` is one wire round-trip per verb). It is a * shortcut, never an assertion: a wrong owner reads as a missing slot, so * callers pass only what a thread read actually returned. */ get(threadId: string, harnessName: string, owner?: string): Promise; /** `get` for a caller that ALREADY holds the slot's stored value — the turn * envelope reads it in the same call as the thread. Same rules as `get`, * because it is `get`'s second half: a slot belonging to another harness is * still destroyed rather than shadowed (§1.3). `stored` is the raw row * payload `harness.get` answers; `undefined` is a missing slot. */ resume(threadId: string, harnessName: string, stored: unknown, owner?: string): Promise; set(threadId: string, harnessName: string, value: string | undefined, owner?: string): Promise; clear(threadId: string, owner?: string): Promise; } export declare function harnessStateStore(store: VendoStore): HarnessStateStore; //# sourceMappingURL=harness-state.d.ts.map