Skip to the content.

Per-song Journal

Journal keeps notes, song information, and observations for each song. Entries can apply to the whole song or mark a playback position; they do not change chords, rhythm, or Lyrics.

On desktop, Journal beside Files opens a compact expandable panel for the loaded song. Click again to close it. Files and Journal share the area: opening either closes the other. Playback continues. Tablet and smartphone layouts have no Journal controls.

+ Add note opens the editor without a position, for a song-wide Note, Info, or Agent entry. + Add at current position snapshots playback seconds once. The optional position field stays editable while typing; leave it empty to make an entry song-wide, or enter seconds to position it (including 0 for the start). Both actions use the same editor.

Song-wide entries appear first, in saved order (editing keeps their place). Positioned entries follow in chronological order. Click a displayed timestamp to seek the loaded media without starting playback. The panel scrolls vertically for many entries or long text. Entries support Edit and Delete (with confirmation). In normal desktop Journal view, visible timestamps briefly invert their colors from their playback time until two playback seconds later. This highlighting stops during Add/Edit, resumes after Save/Cancel, and never scrolls the panel.

Agent is a category only; Journal never invokes an AI agent. Reports are quality signals, not verified labels or ML ground truth. Use the existing chord Edit workflow when you already want to change analysis. Journal does not edit it. Keep resolutions short and human-readable, for example “Fixed: LRC offset corrected by about 3.8 s.” Do not put transcripts, debug logs, commit SHAs, implementation details, or investigation history here.

Storage and developer contract

Journal is optional, user-owned data separate from analysis JSON and same-stem .cho Lyrics sheets. It does not require either file and has an independent lifecycle. FileRepr owns its path: <media directory>/.chordflask/journals/<full media filename>.journal.json, for example .chordflask/journals/song.mp3.journal.json. Including the media extension avoids same-stem recording collisions; the separate directory avoids collisions with analysis for media named song.mp3.journal.mp4. Existing .chordy fallback behavior is the same as other FileRepr paths. No file or storage directory is created on a missing-file read. After the last deletion, a minimal empty schema file stays.

Schema version 1 has schema_version and entries. Entries have stable opaque id strings, timestamp values of null (whole song) or finite non-negative numbers in playback seconds, and category (note, info, agent). Note and Info have text. Agent has kind (general, chord, lyrics, rhythm), question, nullable answer, boolean resolved, and nullable UTC ISO resolved_at. Only Chord reports additionally have nullable expected_chord. Current displayed chord/range capture is deferred. Existing numeric-timestamp journals remain valid without rewriting or migration; the schema version remains 1.

{
    "schema_version": 1,
    "entries": [
        {
            "id": "4bf63740a1544a61b52b17c0b7d82db5",
            "timestamp": 67.2,
            "category": "agent",
            "kind": "lyrics",
            "question": "Lyrics are clearly shifted here.",
            "answer": null,
            "resolved": false,
            "resolved_at": null
        }
    ]
}

POST /journal uses the existing validated dirname/filename media identity. Actions are load (default), add/edit with entry, delete with id, and resolve with id and boolean resolved. Edit also takes id. Dates and new IDs are server-owned. Mutations use the existing per-path process lock and atomic JSON writer (fsync, replace). Malformed or unsupported files produce an error and block writes; they are never silently reset. Switching songs discards the form and ignores responses for the previous song.

Analysis/reanalysis never overwrites Journal. Maintenance storage reports list the journals directory as protected user journals (including lock files). Analysis validation/migration scan only top-level JSON and skip journals, even malformed ones; generic cleanup preserves them. There is no new maintenance subsystem or whole-journal CLI deletion. To remove an entire journal explicitly, delete that exact sidecar yourself when it is not being edited. External tools can scan *.journal.json for category == "agent" and resolved == false.