id: 2977cec2004b4a79aad66805d2e63c79
parent_id: 2043d16d9a9342d3b2cb65f7ccdd0413
item_type: 1
item_id: 0c837f4e6b7e462a997cbc19e47c864a
item_updated_time: 1782287427995
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\" v0.\"],[-1,\"6\"],[1,\"7\"],[0,\".0 (\"],[-1,\"with track mapping addition\"],[1,\"28 endpoint\"],[0,\"s)\\\n\\\n\"]],\"start1\":328,\"start2\":328,\"length1\":40,\"length2\":24},{\"diffs\":[[0,\" session |\\\n\\\n\"],[1,\"### Car Characteristics (v0.7.0)\\\n\\\n| Method | Endpoint | Description |\\\n|--------|----------|-------------|\\\n| GET | `/api/characteristics/cars` | List all cars with aggregated shift-point data (session_count, recommended_shift_rpm) |\\\n| GET | `/api/characteristics/cars/{car}` | Get detailed per-gear shift-point profile for a car |\\\n\\\n\"],[0,\"### Metadata\"]],\"start1\":2219,\"start2\":2219,\"length1\":24,\"length2\":355},{\"diffs\":[[0,\"nts,\"],[-1,\" racing_line, braking_analysis, lap_times, sector_analysis, track_map,\"],[0,\" tra\"]],\"start1\":2706,\"start2\":2706,\"length1\":78,\"length2\":8},{\"diffs\":[[0,\"sessions\"],[1,\" (loaded from persistent storage on startup)\"],[0,\" |\\\n| POS\"]],\"start1\":2981,\"start2\":2981,\"length1\":16,\"length2\":60},{\"diffs\":[[0,\" | null\\\"\"],[-1,\"\\\n}\\\n```\"],[1,\",\\\n  \\\"car_name\\\": \\\"Ferrari 488 GT3 | null\\\"\\\n}\\\n```\\\n\\\n`car_name` field added in v0.7.0 — cached during run finalization from telemetry frames.\"],[0,\"\\\n\\\n### Tr\"]],\"start1\":5465,\"start2\":5465,\"length1\":22,\"length2\":152},{\"diffs\":[[0,\"..],\"],[-1,\"     // normalized (x, z) pairs\"],[0,\"\\\n  \\\"\"]],\"start1\":5771,\"start2\":5771,\"length1\":39,\"length2\":8},{\"diffs\":[[0,\"..],\"],[-1,\"              // meters per point\\\n  \\\"heading\\\": [1.57, ...],                  // radians per point\\\n  \\\"curvature\\\": [0.002, ...],               // 1/radius per point (smoothed)\"],[1,\"\\\n  \\\"heading\\\": [1.57, ...],\\\n  \\\"curvature\\\": [0.002, ...],\"],[0,\"\\\n  \\\"\"]],\"start1\":5882,\"start2\":5882,\"length1\":181,\"length2\":63},{\"diffs\":[[0,\"### \"],[-1,\"Delete Run Response\\\n\\\n```\\\n// DELETE /api/sessions/{id}/runs/{run_id}\\\n// Returns 204 No Content on success\\\n```\\\n\\\n### Reopen Session Response\\\n\\\n```\\\n// POST /api/sessions/{id}/reopen\\\n// Returns updated UseCaseSession (status: \\\"active\\\", analysis cleared)\\\n```\"],[1,\"Car Characteristics List Response\\\n\\\n```json\\\n// GET /api/characteristics/cars\\\n[\\\n  {\\\n    \\\"car_name\\\": \\\"Ferrari 488 GT3\\\",\\\n    \\\"session_count\\\": 3,\\\n    \\\"recommended_shift_rpm\\\": 7500.0\\\n  }\\\n]\\\n```\\\n\\\n### Car Characteristics Detail Response\\\n\\\n```json\\\n// GET /api/characteristics/cars/{car}\\\n{\\\n  \\\"car_name\\\": \\\"Ferrari 488 GT3\\\",\\\n  \\\"gears\\\": [\\\n    {\\\n      \\\"gear\\\": 2,\\\n      \\\"min_rpm\\\": 3200,\\\n      \\\"max_rpm\\\": 8500,\\\n      \\\"min_speed_kmh\\\": 45.0,\\\n      \\\"max_speed_kmh\\\": 120.0\\\n    }\\\n  ],\\\n  \\\"recommended_shift_rpm\\\": 7500.0,\\\n  \\\"session_count\\\": 3\\\n}\\\n```\\\n\\\n### Delete Run Response\\\n\\\n```\\\n// DELETE /api/sessions/{id}/runs/{run_id}\\\n// Returns 204 No Content on success\\\n```\\\n\\\n### Reopen Session Response\\\n\\\n```\\\n// POST /api/sessions/{id}/reopen\\\n// Returns updated UseCaseSession (status: \\\"active\\\", analysis cleared)\\\n```\\\n\\\n---\\\n\\\n## Session Persistence (v0.7.0)\\\n\\\nSessions are persistent — they survive server restart.\\\n\\\n### Storage Layout\\\n\\\n```\\\n./data/sessions/\\\n├── <session_id>.json          # Metadata (runs, analysis results, car_name)\\\n└── <session_id>.frames.json   # Telemetry frames (lazy-loaded on demand)\\\n```\\\n\\\n### Load Behavior\\\n\\\n- **Startup:** `load_all()` reads only metadata JSON files for all sessions — fast, no frame data loaded\\\n- **Lazy load:** `ensure_frames_loaded()` loads frames for a specific session on first access (analysis, frame extraction)\\\n- **Normalization:** On reload, any Recording runs are set to Stopped (ring-buffer markers are stale after restart)\\\n\\\n### Write Behavior\\\n\\\n- **Atomic:** Writes to `<file>.json.tmp`, then renames to final name\\\n- **Compact:** Frames serialized to compact JSON (no pretty-printing)\\\n- **Off-thread:** Frame data cloned under lock, serialization + disk write offloaded to `std::thread::spawn` to avoid blocking API responses\"],[0,\"\\\n\\\n--\"]],\"start1\":6607,\"start2\":6607,\"length1\":259,\"length2\":1745},{\"diffs\":[[0,\"istory\\\n\\\n\"],[1,\"### v0.7.0 (2026-06-24) — Session Persistence + Car Characteristics\\\n- **Persistent sessions** — sessions, runs, and analysis survive server restart\\\n  - Metadata at `data/sessions/<id>.json`, frames at `<id>.frames.json` (split, lazy-loaded)\\\n  - Atomic writes (temp + rename), off-thread frame serialization\\\n  - Metadata-only `load_all` on startup; `ensure_frames_loaded` lazy-loads on demand\\\n  - Recording runs normalized to Stopped on reload\\\n  - `car_name: Option<String>` cached on `UseCaseSession`\\\n- **Car characteristics** — `GET /api/characteristics/cars`, `GET /api/characteristics/cars/{car}`\\\n  - New module: `characteristics.rs` — aggregates shift-point data across sessions\\\n  - Typed `Deserialize` view structs (`ShiftPointAnalysisView`, `GearCurveView`)\\\n- **Removed** obsolete `track_map` use case (superseded by `track_mapping`)\\\n- `Deserialize` added to `TelemetryFrame` and `FeedSource` (for session frame round-trip)\\\n- 33 unit tests (unchanged from v0.6.0)\\\n\\\n\"],[0,\"### Post\"]],\"start1\":10474,\"start2\":10474,\"length1\":16,\"length2\":987},{\"diffs\":[[0,\"-06-\"],[-1,\"08 — Track mapping: TrackModel persistence, track API endpoints, PCARS V1 position, dual position mode, corner detection\"],[1,\"24 — v0.7.0: session persistence (split metadata/frames, lazy load, atomic writes), car characteristics DB (2 endpoints), removed track_map use case, 28 total endpoints\"],[0,\"*\"]],\"start1\":13821,\"start2\":13821,\"length1\":125,\"length2\":173}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-06-24T07:57:22.570Z
created_time: 2026-06-24T07:57:22.570Z
type_: 13