practice slice 2 — store, paths, self-contained sets

Contract amendment (planning ruling): ProblemSet gains propositions
(nodeId → {name, statement}) and chains (the frozen derivation) — sets
are documents of what WAS selected; grading/dedup/coverage never touch
the live graph. config.ts PATHS.practice → data/practice/. PracticeStore
port (createSet assigns ps_<ts36>_<rand>, getSet, listSets createdAt-desc,
saveSet replace-whole, deleteSet). src/store/practice.ts: one JSON per
set, hand-written isProblemSet read guard (types-only; corrupt/missing →
null/skipped, never thrown; saveSet refuses invalid records). Wired in
src/server/stores.ts. 10-test suite: round-trip, corrupt-tolerance,
missing-dir, validator garbage-reject + optional-tolerate + verdict
union, ps_ id shape.
This commit is contained in:
amosblomqvist
2026-09-29 17:53:36 +03:00
parent 05dcaafc68
commit b7a19609cb
6 changed files with 373 additions and 0 deletions
+4
View File
@@ -26,6 +26,10 @@ export const PATHS = {
/** Chat sessions (AI SDK UIMessage transcripts, one JSON file per chat). */
chats: path.join(DATA_ROOT, "chats"),
graph: path.join(DATA_ROOT, "graph"),
/** Practice problem sets (one JSON document per set — src/store/practice.ts).
* Bounded self-contained snapshots (propositions + chains frozen at
* creation), not append-only ledgers. */
practice: path.join(DATA_ROOT, "practice"),
} as const;
// ─── Models ────────────────────────────────────────────────────────────────