Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.d/copilot-log-reader-resilience.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed
- Copilot Chat no longer stays unavailable after its log's timestamps change without new content,
and an Ovis started after a Copilot's log rotated reads its earlier copies when none was pruned.
23 changes: 22 additions & 1 deletion docs/copilot-chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,28 @@ mtime and ctime were at least three seconds old at that check and the wall clock
moved behind it; younger timestamps or a clock rollback trigger rehashing
because a same-size rewrite may share their filesystem tick. Changed logs
revalidate the entire consumed prefix in 64 KiB chunks, including bytes outside the catch-up
window; logs over 64 MiB use Terminal without reading or hashing them.
window; logs over 64 MiB use Terminal without reading or hashing them. Rehashed bytes that match
keep a session the log already registered even when only the timestamps moved; a held marker's
fallback still needs an untouched initial log.
Copilot 1.0 rotates its log at about 10 MiB: it renames the copies up (`.1.log` to `.2.log`,
keeping four), writes the new `.1.log` beside them as `.1.log.rotation-staging` and renames it
into place, then empties the open log. While it copies, it holds the log open twice; both
descriptors are the one log.
A reader that first meets a Copilot whose log has already rotated replays its `.N.log` copies,
oldest first, when the oldest begins within five seconds of the start time in the log's name
(no copy was pruned), every copy belongs to the open log's owner and none changed while they
were read; with the open log they count against the 64 MiB limit. An older copy that ends
inside a line, a link or a copy that cannot be opened is not replayed; a newest copy that ends
inside a line is read again on the next lookup, as are copies changed while being read. Without
such a chain the open log stands alone, as before.
A newest copy other than the one last seen (by inode, size and timestamps, since a deleted
copy's inode can come back) means the open log rotated, even into the same bytes: a binding the
copies alone made is read again from the whole chain, any other carries on from the copy that
continues the bytes read. No newest copy at all, the moment inside a rotation before the new
one is in place, counts as a rotation too: a lookup that lands there leaves Chat unavailable
until Copilot registers a session again, rather than risk showing one the copies left behind.
Copies of another user are never replayed. A log that shrinks below the size
last seen, even by a partial line, is read again from its complete lines.
This assumes filesystem timestamps trail this machine's clock by no more than that margin.
A filesystem with greater timestamp lag, such as a skewed network mount, can retain a stale
binding until the next append.
Expand Down
Loading
Loading