export declare const DEV_DIR = ".helix"; export declare const DEV_STATE_FILENAME = "dev-state.json"; export declare const DEV_PRODUCTS_FILENAME = "dev-products.json"; export declare const DEV_ACHIEVEMENTS_FILENAME = "dev-achievements.json"; export declare const DEV_STATE_FILE_VERSION = 1; /** Opaque to the CLI: the shape is the SDK's DevShellState. Only `userId` is ever read here. */ export type DevStateBlob = { userId?: string; } & Record; /** The simulated player. `dev-user-1` is the SDK's own default, so a first run matches its docs. */ export type DevIdentity = { id: string; username: string; displayName: string | null; }; export type DevWorldStates = { activeUserId: string; players: Record; }; export type DevStateFile = { v: number; worlds: Record; }; /** The catalog seed, shaped like the SDK's DevShellProductsSeed (and the future helix.registry.json). */ export type DevProductsSeed = { products: unknown[]; listings?: unknown[]; }; export declare function devStatePath(worldDir: string): string; export declare function devProductsPath(worldDir: string): string; export declare function devAchievementsPath(worldDir: string): string; export declare function emptyDevStateFile(): DevStateFile; export declare const DEFAULT_DEV_IDENTITY: DevIdentity; /** dev-user-1 is the SDK's default identity, so identity 1 must spell exactly what the SDK would. */ export declare function devIdentity(index: number): DevIdentity; /** Never throws: a hand-edited or truncated file starts the run empty rather than killing the command. */ export declare function readDevStateFile(worldDir: string): DevStateFile; export declare function writeDevStateFile(worldDir: string, file: DevStateFile): string; export type DevStateSelection = { file: DevStateFile; identity: DevIdentity; /** The state to hand the shell, or null to let it mint an empty player. */ state: DevStateBlob | null; /** True when the file changed here (a reset or a new identity) and must be written back before boot. */ mutated: boolean; }; /** * Pick which simulated player this run drives. `--reset` drops the whole world's stored state; `--fresh` * mints the next identity and leaves every other player's state alone. */ export declare function selectDevState(file: DevStateFile, slug: string, options?: { reset?: boolean; fresh?: boolean; }): DevStateSelection; /** Fold one onStateChange payload back into the file. Last write wins — the shell is the only writer. */ export declare function recordDevState(file: DevStateFile, slug: string, state: DevStateBlob): DevStateFile; export type IgnoreOutcome = 'present' | 'appended' | 'created'; /** * Keep the simulated player out of version control. Appends with the file's OWN line ending — flipping * a creator's .gitignore to LF would show up as a whole-file diff on their next commit. */ export declare function ensureDevDirIgnored(worldDir: string): IgnoreOutcome; export type DevProductsSeedResult = { path: string; seed: DevProductsSeed; count: number; } | null; /** Read `.helix/dev-products.json` if the creator wrote one. A bare array is accepted as `{ products }`. */ export declare function readDevProductsSeed(worldDir: string): DevProductsSeedResult; /** One validated seed row, shaped for the SDK's DevShellAchievement (registry side). */ export type DevAchievementRow = Record; export type DevAchievementsSeedResult = { path: string; achievements: DevAchievementRow[]; count: number; criteriaCount: number; } | null; /** * Read `.helix/dev-achievements.json` — registration-shaped rows, validated with the SAME rules * `helix achievement register` applies (closed criteria vocabulary, key templates, dot-path field, * unlockMode coherence). A seed that passes here is the same JSON that registers for real; a row the * registration would refuse must fail the boot, not silently never unlock. */ export declare function readDevAchievementsSeed(worldDir: string): DevAchievementsSeedResult;