fix(engine): close the Windows ledger and sidecar save gaps

- FleetLedger caches only the durable length, not an open ledger handle,
  so a live appender no longer blocks compaction's replace on Windows.
- hash_session_record treats a Windows path-not-found under a
  non-directory parent as NotADirectory, matching Unix, so a blocked
  checkpoint inspection cannot silently clear save health.
- The focused Windows workflow now carries RUST_BACKTRACE for Phase B.

Local: persistence_actor 1/1, ledger compaction 1/1, fleet_setup 1/1;
scripts/preflight.sh --check OK.
This commit is contained in:
CodeWhale Bot committed 2026-11-08 22:46:10 -08:00
1 parent ba92bff261
commit 13858fa8d0
3 files changed
+20 -10

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ jobs:
CARGO_INCREMENTAL: 0
RUSTFLAGS: -Dwarnings
RUST_MIN_STACK: 8388608
RUST_BACKTRACE: full
FILTER: ${{ inputs.filter }}
steps:
- uses: actions/checkout@v7
+4 -9
View File
@@ -342,7 +342,7 @@ pub struct FleetLedger {
ledger_file: WorkspaceFile,
lock_file: WorkspaceFile,
original_lock: std::fs::File,
durable_barrier: parking_lot::Mutex<Option<(std::fs::File, u64)>>,
durable_barrier: parking_lot::Mutex<Option<u64>>,
/// Stable advisory-lock inode shared by every manager for this workspace.
///
/// The ledger itself is replaced during compaction, so locking
@@ -549,7 +549,7 @@ impl FleetLedger {
file.sync_data()
.with_context(|| format!("syncing fleet ledger {}", self.ledger_path.display()))?;
let length = file.metadata()?.len();
*self.durable_barrier.lock() = Some((file, length));
*self.durable_barrier.lock() = Some(length);
// Wake SSE subscribers after the bytes are durable (#6211 R7b). Every
// record kind funnels through here, so a wake only promises "something
// changed" — subscribers re-poll with their cursor.
@@ -1186,17 +1186,12 @@ impl FleetLedger {
let file = self.ledger_file.open_update(false, false)?;
let length = file.metadata()?.len();
let mut cached = self.durable_barrier.lock();
if let Some((previous, durable_length)) = cached.take()
&& durable_length == length
&& same_file(&previous, &file)?
{
*cached = Some((previous, durable_length));
if *cached == Some(length) {
return Ok(());
}
file.sync_data()
.context("acknowledging Fleet ledger durability")?;
let length = file.metadata()?.len();
*cached = Some((file, length));
*cached = Some(file.metadata()?.len());
Ok(())
}
+15 -1
View File
@@ -3962,7 +3962,21 @@ impl SessionManager {
use std::io::Read;
let mut file = match open_private_read_file(path) {
Ok(file) => file,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(None),
Err(error) if error.kind() == io::ErrorKind::NotFound => {
if path
.parent()
.is_some_and(|parent| parent.exists() && !parent.is_dir())
{
return Err(io::Error::new(
io::ErrorKind::NotADirectory,
format!(
"private sidecar parent {} is not a directory",
path.parent().unwrap_or(path).display()
),
));
}
return Ok(None);
}
Err(error) => return Err(error),
};
let mut digest = Sha256::new();