Operating system(s)
What happened?
Branch name assignments (threads.branch_name) are stored only in SQLite (desktop.sqlite). Pi session files (.jsonl) contain no branch information. As a result, syncShellIndex — which scans session files on every startup — cannot reconstruct branch assignments if the database is lost, reset, or a different database instance is used (e.g. dev vs. prod, new machine, corrupted DB).
Any scenario that produces a fresh or empty desktop.sqlite permanently moves all sessions to "Unassigned" with no automatic recovery path.
Steps to reproduce
- Assign sessions to git branches by sending messages through the Howcode Composer.
- Delete or replace ~/Library/Application Support/howcode/state/desktop.sqlite (or switch to a DB instance that lacks the assignments).
- Restart Howcode — all sessions appear under "Unassigned" despite the Pi .jsonl files being intact.
syncShellIndex completes without errors but branch_name stays NULL for all threads because mapSessionSummaryToRecord returns no branchName and the UPSERT resolves to COALESCE(threads.branch_name, NULL).
Agent implementation prompt
assignThreadBranch() in desktop/thread-state-db/thread-writes.ts writes branch names only to threads.branch_name in SQLite. mapSessionSummaryToRecord in desktop/pi-threads/session-index.ts does not read or return a branchName field. syncSessionSummaries in desktop/thread-state-db/session-writes.ts upserts with COALESCE(threads.branch_name, excluded.branch_name) which preserves existing values but cannot populate them from session files.
Investigate and implement durable branch assignment storage. Options to consider:
- Write branch name into the Pi session JSONL as a session_info-style entry when assignThreadBranch is called; extend applySessionFileEntry and SessionSummary to read it back; populate branchName in mapSessionSummaryToRecord so syncShellIndex can reconstruct assignments from files alone.
- During syncShellIndex, for sessions with branch_name IS NULL, use git log --format="%H %D" --before=<session_startedAt> against the project's repo to infer which branch was active when the session started. The session start timestamp is available in .meta.json (startedAt) alongside each .jsonl.
Relevant files:
- desktop/pi-threads/session-index.ts (readSessionSummary,
- mapSessionSummaryToRecord),
- desktop/thread-state-db/session-writes.ts (syncSessionSummaries),
- desktop/thread-state-db/thread-writes.ts (assignThreadBranch),
- desktop/pi-threads/composer-actions.ts (call site for assignThreadBranch).
App version or commit
0.1.66-dev
Operating system(s)
What happened?
Branch name assignments (threads.branch_name) are stored only in SQLite (desktop.sqlite). Pi session files (.jsonl) contain no branch information. As a result, syncShellIndex — which scans session files on every startup — cannot reconstruct branch assignments if the database is lost, reset, or a different database instance is used (e.g. dev vs. prod, new machine, corrupted DB).
Any scenario that produces a fresh or empty desktop.sqlite permanently moves all sessions to "Unassigned" with no automatic recovery path.
Steps to reproduce
syncShellIndex completes without errors but branch_name stays NULL for all threads because mapSessionSummaryToRecord returns no branchName and the UPSERT resolves to COALESCE(threads.branch_name, NULL).
Agent implementation prompt
assignThreadBranch() in desktop/thread-state-db/thread-writes.ts writes branch names only to threads.branch_name in SQLite. mapSessionSummaryToRecord in desktop/pi-threads/session-index.ts does not read or return a branchName field. syncSessionSummaries in desktop/thread-state-db/session-writes.ts upserts with COALESCE(threads.branch_name, excluded.branch_name) which preserves existing values but cannot populate them from session files.
Investigate and implement durable branch assignment storage. Options to consider:
Relevant files:
App version or commit
0.1.66-dev