/** * Trajectory Store — correction sample primitives for SDK use. * * Extracts listCorrectionSamples and reviewCorrectionSample from TrajectoryDatabase * as pure functions that can be used without openclaw-plugin dependency. * * Reads the canonical workspace trajectory database * (`{workspaceDir}/.state/trajectory.db`) written by openclaw-plugin * TrajectoryDatabase — the path pin below (`resolveTrajectoryDbPath`) is the * shared path contract: core must not import from openclaw-plugin, so the * relative path is pinned here, and the plugin-to-core round-trip test * (openclaw-plugin tests/core/trajectory-store-round-trip.test.ts) fails if * either side moves the file. * * @example * import { listCorrectionSamples, reviewCorrectionSample } from '@principles/core/trajectory-store'; */ import Database from 'better-sqlite3'; import type { CorrectionSampleReviewStatus, CorrectionSampleRecord } from './trajectory-types.js'; export type { CorrectionSampleReviewStatus, CorrectionExportMode, CorrectionSampleRecord, } from './trajectory-types.js'; /** * Canonical trajectory.db location shared by every SDK reader. * * The production writer is openclaw-plugin `TrajectoryDatabase`, whose path * authority is openclaw-plugin `core/paths.ts` * (`PD_FILES.TRAJECTORY_DB = .state/trajectory.db`). principles-core must not * import from openclaw-plugin, so the relative path is pinned here; the * plugin-to-core round-trip test * (openclaw-plugin/tests/core/trajectory-store-round-trip.test.ts) writes * through TrajectoryDatabase and reads through this module — if either side * moves the file, that test fails. * * A missing database is NOT the same as an empty database: readers open the * file through `openTrajectoryDbReadonly`, which throws * `TrajectoryDbUnavailableError` (carrying the path and reason) instead of * silently returning no rows (rc-3 fail-loud-missing, rc-9 no-silent-fallback). */ export declare function resolveTrajectoryDbPath(workspaceDir: string): string; /** * The trajectory database cannot be read at its canonical location. * * Distinct from "the database exists and has no rows": callers (CLI commands) * must surface this as an operator-visible failure with a next action, never * as an empty result. */ export declare class TrajectoryDbUnavailableError extends Error { readonly dbPath: string; constructor(dbPath: string, reason: string); } /** * Open the workspace trajectory database read-only or throw. * * Read-only on purpose: these primitives never create or migrate the file — * the writer (openclaw-plugin TrajectoryDatabase / `pd runtime init`) owns * creation, so a missing file is reported, not papered over. */ export declare function openTrajectoryDbReadonly(workspaceDir: string): Database.Database; /** * Translate unexpected query/DDL failures into the same typed unavailability * the CLI layer knows how to present (PRI-753 review: malformed or * schema-less databases must not escape as raw stack traces). The underlying * SQLite message is preserved in the reason. Domain errors (sample not * found) and existing unavailability errors pass through unchanged. */ export declare function rethrowAsQueryFailed(dbPath: string, err: unknown): never; /** * PRI-904: the next session-local user-turn ordinal — the deterministic * round fact the prompt principle fair rotation advances on. * * Reads the ALREADY-PERSISTED `user_turns.turn_index` counter for one * session (written by openclaw-plugin `TrajectoryDatabase.recordUserTurn`). * It is the same fact the correction pipeline anchors on * (`nextUserTurnIndex` in the prompt hook), so no new column, table, file or * cursor is introduced: this is a read of production state through the * registered trajectory-store seam. * * Determinism contract (SPEC INV-F02): for one session the value is * `max(turn_index) + 1`, so consecutive recorded user turns yield consecutive * ordinals. Modulo the eligible-ring size N, N consecutive turns therefore * cover every ring position exactly once — a bounded, provable opportunity * window, unlike hashing an opaque run identity. * * @param workspaceDir - The workspace directory (DB path: {workspaceDir}/.state/trajectory.db) * @param sessionId - Session whose next user-turn ordinal is requested * @returns The next ordinal (>= 1); 1 when the session has no recorded turn yet * @throws TrajectoryDbUnavailableError if the database does not exist or * cannot be opened — callers must degrade observably, never assume 0 */ export declare function nextSessionTurnOrdinal(workspaceDir: string, sessionId: string): number; /** * List correction samples by review status. * * @param workspaceDir - The workspace directory (DB path: {workspaceDir}/.state/trajectory.db) * @param status - Filter by review status (default: 'pending') * @returns Array of CorrectionSampleRecord; empty array means the database * exists and has no matching rows * @throws TrajectoryDbUnavailableError if the database does not exist or * cannot be opened — never silently treated as "no samples" */ export declare function listCorrectionSamples(workspaceDir: string, status?: CorrectionSampleReviewStatus): CorrectionSampleRecord[]; /** * Review a correction sample (approve or reject). * * @param sampleId - The sample ID to review * @param decision - 'approved' or 'rejected' * @param note - Optional review note * @param workspaceDir - The workspace directory (DB path: {workspaceDir}/.state/trajectory.db) * @returns The updated CorrectionSampleRecord * @throws TrajectoryDbUnavailableError if the database does not exist, * cannot be opened, or the schema/query fails * @throws Error if the sample is not found */ export declare function reviewCorrectionSample(sampleId: string, decision: 'approved' | 'rejected', note: string | undefined, workspaceDir: string): CorrectionSampleRecord; //# sourceMappingURL=trajectory-store.d.ts.map