Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2e11be5
docs(V2-04): fix ADR-071 status contradiction, requalify CB-T4
Aug 17, 2026
cb9303e
chore: ignore local OpenCode/Obsidian artifacts
Aug 17, 2026
9d46dda
feat(V2-04): derive and test EmergencyHeadroom's byte formula
Aug 17, 2026
bdc3c66
test(V2-04): close GOV-U40/GOV-U41/GOV-S03 for the memory governor
Aug 17, 2026
d2415b7
test(V2-04): GOV-U25/GOV-U26 spurious-wake and lost-wake coverage
Aug 17, 2026
4b98286
test(V2-04): close GOV-U21/22/23 — governor borrowable-protection fai…
Aug 17, 2026
7494f8a
test(V2-04): close CB-T1d and CB-T2 governed-coordinator coverage gaps
Aug 17, 2026
4e94650
test(V2-04): CB-T5 bounded-release-window proof + GOV-RSS01-03 govern…
Aug 17, 2026
a5245ce
merge: CB-T1d + CB-T2 coordinator tests
Aug 17, 2026
fc46d15
merge: GOV-U21/22/23 fairness protection tests
Aug 17, 2026
9f10e23
merge: GOV-U25/26 spurious/lost wake tests
Aug 17, 2026
d1f7c79
merge: GOV-U40/41 + GOV-S03 domain/shutdown tests
Aug 17, 2026
cf2e5fc
merge: CB-T5 + GOV-RSS01-03 window bound and RSS oracle
Aug 17, 2026
58d16a3
docs(V2-04): fix stale RETAIN column in ADR-072 §A outcome table
Aug 17, 2026
69c265d
docs: status.md entry for the P1 governor gate-closure round (2026-08…
Aug 17, 2026
589e17f
fix(V2-04): WriteCoordinator::build no longer panics on a shared Memo…
Aug 17, 2026
041d213
test(V2-04): memtable-rotation-specific RSS/stress oracle (ADR-072 §B)
Aug 17, 2026
bcc6121
fix(V2-04): close the ADR-072 rotation-charge shutdown race
Aug 17, 2026
6464d44
feat(V2-04): EmergencyHeadroom operational activation (GOV-U32)
Aug 18, 2026
566e22b
feat(V2-04): expose memory governor activation as genuinely public API
Aug 18, 2026
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,8 @@ $RECYCLE.BIN/
*.iml
.fleet/
.anthropic/
/obsd\BaseMyAI
obsd\BaseMyAI\.obsidian
obsd\BaseMyAI\BaseMyAI
obsd
opencode.jsonc
19 changes: 19 additions & 0 deletions crates/basemyai-engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ test-util = []
# Témoin négatif D-6 d'ADR-053 : réintroduit volontairement un manifeste
# d'index plat et non borné. Jamais activé par défaut ni par un build produit.
unbounded-index-oracle = ["test-util"]
# Témoin négatif GOV-RSS02 (ADR-071) : réintroduit volontairement, dans le
# harnais de test `gov_rss_oracle` lui-même (jamais dans le governor ou un
# cache réel), une fuite proportionnelle au volume que la comptabilité du
# governor ne peut pas voir (une copie orpheline hors réservation, retenue à
# côté de l'éviction correctement comptée). Jamais activé par défaut ni par
# un build produit.
governor-rss-negative-control-leak = ["test-util"]

[[bin]]
name = "crash_writer"
Expand Down Expand Up @@ -267,5 +274,17 @@ path = "tests/compaction/generation_gc_retry.rs"
name = "generation_pointer_loss_is_rejected_and_gen1_survives"
path = "tests/compaction/generation_pointer_loss_is_rejected_and_gen1_survives.rs"

[[test]]
name = "cb_t5_bounded_release_window"
path = "tests/governor/cb_t5_bounded_release_window.rs"

[[test]]
name = "gov_rss_oracle"
path = "tests/governor/gov_rss_oracle.rs"

[[test]]
name = "gov_rotation_rss_oracle"
path = "tests/governor/gov_rotation_rss_oracle.rs"

[lints]
workspace = true
995 changes: 993 additions & 2 deletions crates/basemyai-engine/src/memory_governor/admission.rs

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion crates/basemyai-engine/src/memory_governor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,20 @@ pub use admission::{AdmissionPermit, MemoryGovernor};
pub use config::GovernorConfig;
pub use governed::{Governed, SharedGoverned};
pub use reservation::MemoryReservation;
pub use types::{AdmissionClass, GovernedMemoryKind, MemoryPlan, estimate_memtable_reservation_bytes};
pub use types::{
AdmissionClass, GovernedMemoryKind, MemoryPlan, estimate_emergency_flush_headroom_bytes,
estimate_memtable_reservation_bytes,
};
// Crate-internal, test-only: lets `store::sst_block::write`'s `#[cfg(test)]`
// tests ground the SstWriter-only half of the EmergencyHeadroom derivation
// against a real writer run (`store::sst_block` is a private module, a
// sibling of this one under the crate root, so it cannot reach `types`
// directly). Gated by `cfg(test)` only, matching that consumer exactly — the
// function itself is used unconditionally by
// `estimate_emergency_flush_headroom_bytes` within `types.rs`, so only this
// cross-module re-export needs gating at all.
#[cfg(test)]
pub(crate) use types::sst_writer_working_set_bytes;

use scheduler::SchedulerQuanta;
use state::GovernorState;
Expand Down
272 changes: 271 additions & 1 deletion crates/basemyai-engine/src/memory_governor/types.rs

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions crates/basemyai-engine/src/store/memtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,18 @@ impl MemtableChargeHandle {
.as_ref()
.map(MemoryReservation::bytes)
}

/// Test-only observability (ADR-072 CB-T5): the number of live strong
/// references to this generation's `Arc<Memtable>` right now — a witness
/// for proving the CB-07 release-window deviation stays bounded, never a
/// decision input (production code must never branch on
/// `Arc::strong_count`, which Rust documents as racy the moment more
/// than one thread can observe it — ADR-071 §"Pinning `Arc`", MG-14).
#[cfg(any(test, feature = "test-util"))]
#[must_use]
pub fn strong_count(&self) -> usize {
Arc::strong_count(&self.0)
}
}

impl Memtable {
Expand Down
61 changes: 61 additions & 0 deletions crates/basemyai-engine/src/store/sst_block/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,67 @@ mod tests {
assert_eq!(loaded.entries().expect("entries"), data);
}

// ADR-071 §"Headroom de progrès background" / ADR-072 CB-08: grounds
// `memory_governor::sst_writer_working_set_bytes`'s steady-state terms
// (staged block, Bloom partition, leaf index, internal levels — every
// component `SstWriter::resident_bytes` can observe from outside)
// against a real writer run, not just arithmetic that agrees with
// itself. Same fixture shape as `partitioned_writer_builds_a_
// hierarchical_index` above (already proven to force multiple leaves
// *and* an internal index root), so every term the estimate computes is
// actually exercised here, not vacuously zero.
//
// `resident_bytes()` cannot see the transient `plain`/sealed/ciphertext
// copies `write_staged_block`/`seal_section` allocate and free within a
// single call (by design — its own doc comment defers that closure
// oracle to `r6_allocator_peak`), so this test validates the
// *steady-state* portion of the estimate exhaustively and leaves the
// transient-buffer portion to the direct code-reading recorded in that
// function's own doc comment.
#[test]
fn sst_writer_term_bounds_a_real_writers_steady_state_across_many_blocks_and_leaves() {
let dir = tempfile::tempdir().expect("tempdir");
let data = entries(200, 40);
let cache = Arc::new(MetadataCache::new(8 * 1024 * 1024));
let block_size: u32 = 128;
let max_key_bytes: usize = 32;
let mut writer = SstWriter::create(dir.path(), 0, block_size, None, max_key_bytes, 0, Arc::clone(&cache))
.expect("create writer");

let bound = crate::memory_governor::sst_writer_working_set_bytes(block_size, max_key_bytes, false)
.expect("no overflow");
let mut peak_resident_bytes = 0usize;
for (index, (key, value)) in data.iter().enumerate() {
let kind = if value.is_some() {
ValueKind::Value
} else {
ValueKind::Tombstone
};
writer
.push(InternalKey::new(key.clone(), 1, kind), value.clone())
.expect("push");
peak_resident_bytes = peak_resident_bytes.max(writer.resident_bytes());
assert!(
writer.resident_bytes() <= bound,
"writer.resident_bytes()={} exceeded the derived steady-state bound={bound} after {index} pushes",
writer.resident_bytes()
);
}
let written = writer.finish().expect("finish");
assert!(
written.footer.bloom_partition_count > 1,
"fixture must force multiple leaves — otherwise the leaf-index/Bloom terms are untested"
);
assert!(
written.footer.index_levels > 1,
"fixture must force an internal index root — otherwise the internal-levels term is untested"
);
assert!(
peak_resident_bytes > 0,
"the writer must have actually held something resident at some point"
);
}

#[test]
fn versioned_roundtrip_preserves_versions_and_snapshot_visibility() {
let dir = tempfile::tempdir().expect("tempdir");
Expand Down
Loading
Loading