app/puzzle_history.h

the board-local log of completed tactics puzzles.

A sibling of GameStore for the puzzle screen. Every finished puzzle attempt (solved or not) is appended here so the Review screen can list them and open each one on the board — the position replayed from its solving FEN through the puzzle’s solution line, scrubbed exactly like a game (review-docs/PLAN.md §7).

WHY THIS IS NOT A GameRecord (game_store.h). A puzzle is not a game: it starts from an arbitrary mid-game FEN (so its pieces are anonymous — never physically followed), it carries a rating and themes a game does not, and it is scored as solved/failed rather than a chess result. Above all, GameStore feeds the server upload pipeline (pendingUpload, POST /api/games); a puzzle solve is reported to Lichess by an entirely different road (PuzzleBridge → LichessClient) and must never enter that queue. Puzzles therefore get their own store and their own tiny record, mirroring GameStore’s one-JSON-file-per-entry, directory-as-index design (records are ~1 KB, so thousands cost nothing and there is no index to desync).

THE TRUTH IS fen + solution (UCI), exactly as a game’s truth is startFen + moves: the SAN and per-ply FENs a reviewer sees are replayed from those two.

namespace kirin
struct PuzzleHistoryEntry
#include <puzzle_history.h>

Public Functions

inline int plyCount() const

Public Members

std::string recordId
std::string puzzleId
std::string fen
std::string lastMove
std::vector<std::string> solution
int rating = 0
std::vector<std::string> themes
bool solverIsWhite = true
bool win = false
bool rated = true
std::string endedAt
class PuzzleHistoryStore
#include <puzzle_history.h>

Public Functions

explicit PuzzleHistoryStore(std::string dir = "")
inline const std::string &dir() const
bool save(const PuzzleHistoryEntry &entry)
bool load(const std::string &recordId, PuzzleHistoryEntry &out) const
bool remove(const std::string &recordId)
std::vector<PuzzleHistoryEntry> list() const

Public Static Functions

static std::string defaultDir()

Private Functions

std::string pathFor(const std::string &recordId) const

Private Members

std::string dir_