/** * On-disk artifact constants: the project history, flow files, replay/drift status, the recorder * lifecycle, heal outcomes, and the structured-annotation vocabulary. */ /** * Schema version stamped into project.json so a reader can reject/upgrade old files. */ export declare const PROJECT_FILE_VERSION = 1; /** * Structured outcome when reading project.json fails (never thrown to the agent). * Mirrors ContractReadError. NOTE: recordRun self-heals a MALFORMED file (starts fresh) so a * corrupt history never wedges the agent; only the READ path (reticle_project) surfaces MALFORMED. */ export declare const ProjectReadError: { readonly MISSING: "project-missing"; readonly MALFORMED: "project-malformed"; /** * Readable, and written by a version of Reticle this one does not know. * * Kept apart from MALFORMED because the two need opposite handling. A malformed file has nothing * left to lose, so recording a run repairs it. A file from another version is intact, and * repairing it would overwrite history a later release could still read. */ readonly WRONG_VERSION: "project-wrong-version"; }; export type ProjectReadError = (typeof ProjectReadError)[keyof typeof ProjectReadError]; /** How a run record was produced. */ export declare const RunKind: { readonly FLOW_REPLAY: "flow_replay"; readonly MANUAL: "manual"; }; export type RunKind = (typeof RunKind)[keyof typeof RunKind]; /** * The persisted outcome of a run. Distinct from ReplayStatus (a wire/replay * concept of ok|drift|error): RunStatus is the history concept and adds pass/fail. The replay * site maps ReplayStatus.OK→PASS, DRIFT→DRIFT, ERROR→ERROR. */ export declare const RunStatus: { readonly PASS: "pass"; readonly DRIFT: "drift"; readonly ERROR: "error"; readonly FAIL: "fail"; }; export type RunStatus = (typeof RunStatus)[keyof typeof RunStatus]; /** * Bounds on project.json so the file stays small + diffable. recordRun keeps the * last PER_NAME runs of any single name, then caps the whole list to TOTAL most-recent overall. */ export declare const PROJECT_RUN_CAP: { readonly PER_NAME: 50; readonly TOTAL: 200; }; /** Maximum distinct route identities retained in project.json. */ export declare const PROJECT_ROUTE_CAP = 200; /** Schema version stamped onto on-disk flow files (.reticle/flows/.json). */ export declare const FLOW_FILE_VERSION = 1; /** How a flow step is anchored to the live DOM at replay time (semantic, never a volatile ref). */ export declare const AnchorKind: { readonly TESTID: "testid"; readonly ROLE: "role"; readonly SIGNAL: "signal"; readonly COMPONENT: "component"; }; export type AnchorKind = (typeof AnchorKind)[keyof typeof AnchorKind]; /** * The role marker for a DEGRADED step — one recorded with no resolvable * testid. It is kept (never dropped) but a volatile eXX ref is NEVER persisted in its place; * the step carries this placeholder ROLE anchor + degraded:true, a legible "add a data-testid * here" marker that a human/self-healing pass re-binds. Satisfies the anchor min(1). */ export declare const DEGRADED_ANCHOR_ROLE = "unresolved"; /** Structured failure codes for flow disk ops (returned, never thrown as free strings). */ export declare const FlowErrorCode: { readonly INVALID_NAME: "flow_invalid_name"; readonly NOT_FOUND: "flow_not_found"; readonly PARSE_FAILED: "flow_parse_failed"; readonly NO_RECORDING: "flow_no_recording"; }; export type FlowErrorCode = (typeof FlowErrorCode)[keyof typeof FlowErrorCode]; /** A flow name must be a single safe path segment (no '/', '\\', '..', leading dot). */ /** * ONE safe path segment: the guard for anything that becomes a single directory or file name. * * Session ids and run ids are this. They are joined into `.reticle/sessions//` and written to, * and a session LABEL is supplied by the tab — so a separator here is a tab choosing where on disk * Reticle writes. Flow names were this too until they became namespaced, and the two guards shared * one pattern; widening the flow pattern silently widened these, which a test caught immediately. * They answer different questions and now have different patterns: a flow name may be a path, a * session id may never be one. */ export declare const SAFE_SEGMENT_PATTERN: RegExp; /** * A flow name: one or more `/`-separated segments. * * Namespaced because the replay grammar addresses documents by path — `onboarding/signup` is how a * composite names the sub-journey it invokes, and the protocol's `FlowNameSchema` has said so since * grammar v2. This pattern is the PERSISTENCE half, and while it stayed single-segment * `reticle_flow_save` refused every name the language is built on. Found by driving a composite: * recording worked, closing the boundary worked, saving it was refused. * * Traversal is impossible by CONSTRUCTION rather than by a filter. No segment may contain a dot at * all, so `..` cannot be spelled; every segment must START with a letter or digit, so a leading, * trailing or doubled separator cannot either. That is stronger than checking for `..`, because * there is no encoding of it left to miss. */ export declare const FLOW_NAME_PATTERN: RegExp; /** * The outcome of replaying an on-disk flow by re-resolving its * semantic anchors against the live DOM. `drift` (an anchor missed → contract changed) is * cleanly separated from `error` (the flow could not load or an action failed) and `ok`. */ export declare const ReplayStatus: { readonly OK: "ok"; readonly DRIFT: "drift"; readonly ERROR: "error"; }; export type ReplayStatus = (typeof ReplayStatus)[keyof typeof ReplayStatus]; /** * Why an anchor failed to resolve at replay time (the "whose fault is * it" reason kind). Drives the human `reason` sentence and whether a nearest-match is offered. */ export declare const DriftReason: { readonly TESTID_NOT_FOUND: "testid_not_found"; readonly SIGNAL_NOT_OBSERVED: "signal_not_observed"; readonly COMPONENT_NOT_FOUND: "component_not_found"; readonly STATE_MISMATCH: "state_mismatch"; /** * The step carries DEGRADED_ANCHOR_ROLE — no anchor was ever resolvable, so nothing was queried. * Distinct from TESTID_NOT_FOUND deliberately: "your element disappeared" and "this step never had * an element bound to it" need different fixes, and reporting the second as the first sent heal * hunting for the nearest testid to the literal word "unresolved". */ readonly ANCHOR_DEGRADED: "anchor_degraded"; /** * The step's anchor resolved and its action ran; the testid its `expect.element` names was absent * afterwards. Distinct from TESTID_NOT_FOUND for the same reason ANCHOR_DEGRADED is: "the element * you clicked is gone" and "the thing you asserted afterwards never appeared" need different * fixes, and reporting the second as the first sends the caller looking for a renamed anchor on a * step whose anchor was fine. */ readonly EXPECT_ELEMENT_NOT_FOUND: "expect_element_not_found"; }; export type DriftReason = (typeof DriftReason)[keyof typeof DriftReason]; /** * Did the step's anchor resolve and its action RUN, leaving only the declared consequence unmet? * * The three reasons below all mean the same thing about the app's state: the element was found, the * action was dispatched, and the page is where the step left it. Only the assertion failed. The * other reasons mean the anchor itself was never resolved, so the page is somewhere the flow never * described and every later step would run against a state nobody predicted. * * That difference is what lets a replay CONTINUE past a failure without turning one wrong result * into several — see the sweep option on replayFlow. Halting on both was correct while there was no * way to tell them apart; it stopped a 6-step bug sweep at its first defect and reported the other * five as `notAttempted`. */ export declare function isConsequenceDrift(reason: DriftReason): boolean; /** Default timeout (ms) a signal anchor waits to be observed at replay. */ export declare const FLOW_SIGNAL_TIMEOUT_MS = 4000; /** * The structured annotation kinds a human can attach while recording. * FIRST CUT: only these four structured kinds compile to flow fields (via a toolbar menu + * a signal