Skip to content
Closed
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
12 changes: 11 additions & 1 deletion crates/tracedecay-agent-hosts/src/agents/codex/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,17 @@ fn prepare_stages_the_source_and_returns_ready_for_cli_activation() {
let outcome = CodexIntegration
.prepare_non_interactive_install(&install_ctx(home.path()))
.unwrap();
assert!(matches!(outcome, NonInteractiveInstallOutcome::Ready));
// Activation is the host CLI's job. CI and other machines without `codex`
// must stop after staging, with the same command the operator runs.
match outcome {
NonInteractiveInstallOutcome::Ready => {}
NonInteractiveInstallOutcome::DeferredUserAction(deferred) => {
assert_eq!(
deferred.remediation,
"Codex activates plugins through its native cache. Run `codex plugin add tracedecay@personal` after TraceDecay stages the source package."
);
}
}
assert!(codex_plugin_manifest_path(home.path()).is_file());
assert!(codex_personal_marketplace_path(home.path()).is_file());
assert_eq!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ pub fn try_acquire_code_generation_store_read_lock(
) -> Result<Option<CodeGenerationStoreLockV1>, CodeGenerationRetentionErrorV1> {
let store_root = canonical_store_root(store_root)?;
let lock = open_lock_file(&store_root.join(STORE_LOCK_FILE))?;
match lock
.try_lock_shared()
.map_err(std::io::Error::from)
{
match lock.try_lock_shared().map_err(std::io::Error::from) {
Ok(()) => Ok(Some(CodeGenerationStoreLockV1 {
file: lock,
store_root,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,16 @@ pub(super) fn text_artifact_admitted_build_budget(
.saturating_sub(watermark_headroom);
let admitted_bytes = preferred_bytes.min(available_for_growth);
if admitted_bytes < minimum_bytes {
// Reservations that fill the ledger are releasable pressure. The
// measured process being over the watermark is not. Collapsing them
// makes a transient competing reservation look like a dead authority
// and the successor never retries when that reservation drops.
let host_capacity = limit_bytes
.saturating_sub(unmodeled_live_bytes)
.saturating_sub(watermark_headroom);
if used_bytes > 0 && host_capacity >= minimum_bytes {
return Err(RetrievalPortError::BudgetExceeded);
}
return Err(RetrievalPortError::AuthorityUnavailable(format!(
"text-artifact build needs at least {minimum_bytes} bytes; \
{available_for_growth} bytes are available below the resident-memory watermark"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -933,14 +933,27 @@ async fn dashboard_freshness_does_not_join_a_clone_backfill_slice() {
latest.advance_text_serving(1).expect("advance text build");
}

let held_slot = latest.text_projection_build.lock_slot();
// Hold the backfill slot on another thread. A std mutex must not cross
// this task's await, and freshness must still answer without taking it.
let build = Arc::clone(&latest.text_projection_build);
let (acquired_tx, acquired_rx) = std::sync::mpsc::sync_channel(1);
let (release_tx, release_rx) = std::sync::mpsc::sync_channel(1);
let holder = thread::spawn(move || {
let held_slot = build.lock_slot();
acquired_tx.send(()).expect("notify slot hold");
let _release = release_rx.recv();
drop(held_slot);
});
acquired_rx.recv().expect("clone backfill slot is held");
let freshness = tokio::time::timeout(
Duration::from_millis(100),
registry.dashboard_freshness(fixture.path()),
)
.await
.expect("dashboard freshness must not wait for the clone backfill slice")
.expect("mounted dashboard freshness");
let _ = release_tx.send(());
holder.join().expect("slot holder");
assert!(matches!(
freshness.clone_index,
Some(
Expand All @@ -950,7 +963,6 @@ async fn dashboard_freshness_does_not_join_a_clone_backfill_slice() {
) if reason == "clone-index status is being updated"
));

drop(held_slot);
registry.shutdown().await;
}

Expand Down Expand Up @@ -986,6 +998,14 @@ async fn query_admission_serves_v14_while_clone_successor_is_pending() {
let worktree = mounted
.get(&fixture.path().canonicalize().expect("canonical root"))
.expect("mounted worktree");
// The text owner and the serving seat must be the same seal. A
// second mount mints a different invalidation fingerprint, so
// grafting only the text handle leaves the query on the other
// generation and the pending clone is never the one that was queried.
*worktree
.serving_generation
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner) = Some(latest.clone());
*worktree
.text_generation
.write()
Expand Down Expand Up @@ -1060,6 +1080,10 @@ async fn expired_source_proof_reschedules_pending_clone_backfill() {
let worktree = mounted
.get(&fixture.path().canonicalize().expect("canonical root"))
.expect("mounted worktree");
*worktree
.serving_generation
.write()
.unwrap_or_else(std::sync::PoisonError::into_inner) = Some(latest.clone());
*worktree
.text_generation
.write()
Expand Down Expand Up @@ -2432,6 +2456,20 @@ fn text_build_budget_shrinks_to_available_headroom_without_dropping_below_its_fl
),
"less than the builder's supported floor must remain a typed capacity refusal"
);

let held = limit - watermark_headroom - 64 * MIB;
assert_eq!(
super::super::text_artifact_admitted_build_budget(
minimum,
minimum,
limit,
held,
held,
watermark_headroom,
),
Err(RetrievalPortError::BudgetExceeded),
"a reservation that leaves the host able to admit the floor is releasable pressure, not a dead authority"
);
}

/// The artifact build and reader ceilings must reserve through the process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3244,22 +3244,22 @@ fn partitioned_codec_fixture() -> (
}

const PARTITIONED_FORMAT_STATE_DIGEST: &str =
"sha256:28f30287a415e81bf589922385146f921a539734ec0a3600bd39578ad3c8dcd3";
"sha256:8d84348830efc4452a078cfac1cc78e0ed44112a37f1025bd6f4f4bc152fe196";
const PARTITIONED_FORMAT_SEGMENTS: &[(&str, u64)] = &[
(
"sha256:924c1f0b7b171b7bf5433a6eb04767eb244e7c9decc1f2343b06a657908f3a7b",
11_070,
"sha256:e50d2733b5f594d79fdccc3e44b5d30d5efb66d14805b5fe0c67d5ceb0a1d66f",
11_071,
),
(
"sha256:1a6e240c8fcc1084d82cee42cbaa889bb479ff1df7a76432dcec2d51d66e1d1a",
5_170,
"sha256:1095d61bb8bbbf6637f85ca957a510d221aaba7923af8e60b0f3eef07042e6ff",
5_171,
),
(
"sha256:4461a4ce08e5f59299030959a2773bd48b2c2d48056c188e06867db99609847a",
6_278,
"sha256:9921ca7da5c489307887ab570a5e8d5a7cebf192b9b6664c487e9a327943e396",
6_279,
),
(
"sha256:4c54bba48f3fcf2fd0085ab5aecd8b35451a8cfc56381fa99605327165afbb15",
"sha256:52b5707b5312bcb1e29849372b0dbb882205b3289b345643620a35c1d260c246",
6_837,
),
];
Expand Down
2 changes: 1 addition & 1 deletion crates/tracedecay-dashboard-api/src/delivery_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2474,7 +2474,7 @@ mod tests {
panic!("a gated mount must project as typed unavailable");
};
assert!(
reason.contains("configure a token"),
reason.contains("Configure a token"),
"the credential gate must tell the reader what to do: {reason}"
);

Expand Down
6 changes: 3 additions & 3 deletions crates/tracedecay-privacy/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,10 +654,10 @@ fn compile_regex(
/// so it is *both* a different match and vastly larger to compile: three
/// upstream rules that repeat `\w` over a wide bound
/// (`pypi-...[\w-]{50,1000}`) blow past the compiler's 10 MB program limit.
/// Expanding `\w` to its RE2 meaning fixes the semantics and the size at once
/// , every rule in the catalogue then compiles under the default limit, with
/// Expanding `\w` to its RE2 meaning fixes the semantics and the size at once,
/// so every rule in the catalogue then compiles under the default limit, with
/// no memory headroom bought and no rule dropped.
////// * **`\b` / `\B`.** RE2's word boundary is ASCII. Rust's is Unicode-aware,
/// * **`\b` / `\B`.** RE2's word boundary is ASCII. Rust's is Unicode-aware,
/// and a Unicode boundary is the one construct the lazy DFA gives up on the
/// moment the haystack holds a non-ASCII byte: every file with an em-dash or
/// an emoji in a comment was then scanned by the PikeVM, the slowest engine,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@
}
],
"expected_query_fallback_digests": {
"train": "sha256:d020b61b1658145487d4d1ea9622ad6075293c329e202bb351c49290bc398067",
"validation": "sha256:934459d069cc368f06ce81d950116d4c823965a95c8f752eef9d41b45a0c01cb"
"train": "sha256:5750d4a588f7a7e14c381ec3a4285400a29e164babbf88e677ce7441aaf8e9b2",
"validation": "sha256:e7a459efb1655bb71e30fd302690cd5ac7937197add94a3ac1cab5812a1f5a48"
},
"profile_matrix": [
{
Expand Down
2 changes: 1 addition & 1 deletion crates/tracedecay-query/src/search_quality/packaged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::candidate_output::{
use super::evaluate::SearchEvalError;

const WORKLOAD_PATH: &str = "tests/fixtures/search_quality/query-lexical-graph-workload-v1.json";
const WORKLOAD_SHA256: &str = "20322067510f57f5fa75f68674b18290a65d0535af7da363b6b6f29384042ca4";
const WORKLOAD_SHA256: &str = "267e2bd2e9b90d258cbeed829920ab735f6af0ebc2a6e870d59eeef29b1cdb93";

const FILES: &[(&str, &[u8])] = &[
(
Expand Down
15 changes: 3 additions & 12 deletions crates/tracedecay-runtime-core/src/lifecycle_lease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,7 @@ pub fn acquire_shared_or_inherited(operation: &str) -> Result<LifecycleLease> {

fn acquire_shared_or_inherited_at(path: &Path, operation: &str) -> Result<LifecycleLease> {
let mut file = open_lock_file(path)?;
match file
.try_lock_shared()
.map_err(std::io::Error::from)
{
match file.try_lock_shared().map_err(std::io::Error::from) {
Ok(()) => Ok(LifecycleLease {
hold: LeaseHold::File(file),
token: None,
Expand Down Expand Up @@ -384,10 +381,7 @@ fn acquire_exclusive_at_with_timeout(
#[hotpath::measure(label = "runtime_core.lifecycle.acquire_shared")]
fn acquire_shared_at(path: &Path, operation: &str) -> Result<LifecycleLease> {
let mut file = open_lock_file(path)?;
match file
.try_lock_shared()
.map_err(std::io::Error::from)
{
match file.try_lock_shared().map_err(std::io::Error::from) {
Ok(()) => Ok(LifecycleLease {
hold: LeaseHold::File(file),
token: None,
Expand All @@ -404,10 +398,7 @@ fn acquire_shared_at(path: &Path, operation: &str) -> Result<LifecycleLease> {

fn try_acquire_shared_at(path: &Path, operation: &str) -> Result<SharedLeaseAttempt> {
let file = open_lock_file(path)?;
match file
.try_lock_shared()
.map_err(std::io::Error::from)
{
match file.try_lock_shared().map_err(std::io::Error::from) {
Ok(()) => Ok(SharedLeaseAttempt::Acquired(LifecycleLease {
hold: LeaseHold::File(file),
token: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ mod tests {
assert_eq!(summary.status, DirectEvaluationStatusV1::Pass);
assert_eq!(
summary.workload_digest,
"sha256:c7c97a6ab08da36ba02a89ca0d705dee0cc62d3a12d6bd3698f6c2185dd2d708"
"sha256:8657aa486a4c58e17c9969c7aa5d143a4d30e88dca7d26f13e61c7d3effab091"
);
assert_eq!(summary.profile_count, 1);
assert_eq!(summary.query_count, 67);
Expand Down
3 changes: 3 additions & 0 deletions crates/tracedecay/src/daemon/production_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,9 @@ mod generation_retention_test;
#[cfg(test)]
mod configuration_idempotency_journey_test;

#[cfg(test)]
mod configuration_protected_preview_journey_test;

#[cfg(test)]
mod read_only_project_open_journey_test;

Expand Down
Loading
Loading