Save Formatting¶
Pure formatting functions for the save system: folder names, Markdown builders for output, baseline, and system prompt files.
app/save_formatting.py¶
Formatted Markdown builders and folder-name generator for the save system.
This module produces the human-readable Markdown files and filesystem-safe
folder names that make up a save package. Each function is a pure formatter:
it takes scalar values and returns a string. No I/O, no network, no
app.* dependencies — only datetime from the standard library.
Exports¶
- save_folder_name(timestamp, input_hash) -> str
Produce a unique folder name for a save operation.
- build_output_md(text, model, temperature, max_tokens, seed, timestamp,
input_hash, *, system_prompt_hash, ipc_id) -> str
Format the generated LLM output as a Markdown document with a provenance header.
- build_baseline_md(text, folder_name) -> str
Format the stored baseline text as a Markdown document.
- build_game_log_md(entries, model, temperature, max_tokens, seed, timestamp) -> str
Format the in-game chat log as a Markdown table with a provenance header. Used by
POST /api/save_chatto writegame_log.md.- build_system_prompt_md(prompt_text, folder_name) -> str
Format the system prompt as a Markdown document with a fenced code block.
Design notes¶
These functions were extracted from main.py so that:
The save route handler can remain a thin orchestrator.
Formatting logic can be unit-tested without the HTTP layer.
build_output_mdaccepts scalar parameters (notSaveRequest) to avoid tight coupling between formatting and the request schema.
- app.save_formatting.save_folder_name(timestamp, input_hash)[source]¶
Produce a unique folder name for a save operation.
Format:
YYYYMMDD_HHMMSS_<8-char-hash-prefix>Example:
20260218_143022_d845cdcfThe 8-character hash prefix provides practical uniqueness even when two saves occur within the same second (different payload → different hash suffix). The format uses only digits, underscores, and lowercase hex characters, making it safe for all major filesystems.
- Parameters:
timestamp (UTC datetime of the save (passed in so the folder name) – stays consistent with the
metadata.jsontimestamp).input_hash (Full 64-char SHA-256 hex digest of the AxisPayload.)
- Returns:
str
- Return type:
Folder name safe for all major filesystems.
- app.save_formatting.build_output_md(text, model, temperature, max_tokens, seed, timestamp, input_hash, *, system_prompt_hash=None, ipc_id=None)[source]¶
Format the generated LLM output as a Markdown document.
Includes an HTML-comment provenance header (model, temperature, seed, hashes) so the file is self-documenting when opened in any Markdown viewer. The IPC hashes are included when available so saved files carry a complete reproducibility record.
- Parameters:
text (The raw LLM-generated text.)
model (Ollama model identifier used for the generation.)
temperature (Sampling temperature used.)
max_tokens (Token budget used.)
seed (RNG seed from the AxisPayload.)
timestamp (UTC datetime of the save (for the provenance header).)
input_hash (SHA-256 of the payload.)
system_prompt_hash (SHA-256 of the normalised system prompt (optional).)
ipc_id (Interpretive Provenance Chain identifier (optional).)
- Returns:
str
- Return type:
Markdown string ready to write to disk.
- app.save_formatting.build_baseline_md(text, folder_name)[source]¶
Format the stored baseline text as a Markdown document.
- Parameters:
text (The baseline text (state.baseline from the frontend).)
folder_name (Save folder name (used in the provenance comment).)
- Returns:
str
- Return type:
Markdown string ready to write to disk.
- app.save_formatting.build_game_log_md(entries, model, temperature, max_tokens, seed, timestamp)[source]¶
Format the in-game chat log as a Markdown document.
Produces a Markdown table with one row per entry and an HTML-comment provenance header recording model and generation settings. Pipe characters inside OOC and IC text are backslash-escaped so they do not break the table structure.
Table columns¶
#— 1-based row index.Char— Character key uppercased (“A” or “B”).OOC— Original out-of-character message (empty cell if absent).Channel— Chat channel (“say”, “yell”, “whisper”).IC Text— Translated in-character dialogue (error detail for failures).Status—okfor success, short failure reason otherwise.Duration— Round-trip time in seconds (e.g.0.8s), blank if unknown.Sent—HH:MM:SSfromsent_at, blank if unknown.Gap— Seconds since previous entry’ssent_at, blank for row 1.- param entries:
ooc_message, ic_text, model, ipc_id, status, error_detail, sent_at, duration_ms).
ooc_messagemay be absent orNonefor legacy entries. Timing/status fields default to success/None for backward compatibility.- type entries:
Serialised
ChatLogEntrydicts (keys: ch, channel,- param model:
- type model:
Ollama model tag used during the session.
- param temperature:
- type temperature:
Sampling temperature used.
- param max_tokens:
- type max_tokens:
Token budget used.
- param seed:
- type seed:
Seed value used.
- param timestamp:
- type timestamp:
UTC datetime of the save (for the provenance header).
- returns:
str
- rtype:
Markdown string ready to write to disk.
- app.save_formatting.build_system_prompt_md(prompt_text, folder_name)[source]¶
Format the system prompt as a Markdown document with a fenced code block.
Wrapping in a fenced code block preserves all whitespace and makes the prompt clearly machine-readable when opened in a Markdown viewer.
- Parameters:
prompt_text (The system prompt string (may be multi-line).)
folder_name (Save folder name (for the provenance comment).)
- Returns:
str
- Return type:
Markdown string ready to write to disk.