Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
27193b1
fix(tests): prevent retained-history cancellation lost wakeups
ScriptedAlchemy Oct 4, 2026
92094ed
fix(contracts): carry freshness across served graph results
ScriptedAlchemy Oct 4, 2026
cdb2aeb
test(sdk): complete physical restart retained journeys
ScriptedAlchemy Oct 4, 2026
ab3ab23
fix(tests): isolate concurrent SDK journey builds
ScriptedAlchemy Oct 4, 2026
b6a39cf
Merge remote-tracking branch 'origin/master'
ScriptedAlchemy Oct 4, 2026
38de0fb
fix(service): remove obsolete runner profile arguments
ScriptedAlchemy Oct 4, 2026
c2f767d
fix(contracts): type freshness on distribution reports
ScriptedAlchemy Oct 4, 2026
6f5d97c
Merge remote-tracking branch 'origin/master'
ScriptedAlchemy Oct 4, 2026
e15a711
fix(git): preserve history changes under session upserts
ScriptedAlchemy Oct 4, 2026
612c0b3
fix(daemon): await native graph without duplicate decoding
ScriptedAlchemy Oct 4, 2026
b3f4d3c
fix(observability): retain production graph row counts
ScriptedAlchemy Oct 4, 2026
b0dc6b9
fix(bench): clear warnings without changing query coverage
ScriptedAlchemy Oct 4, 2026
bdb3ad1
fix(retention): recognize lexical initialization sidecars
ScriptedAlchemy Oct 4, 2026
108278b
fix(feedback): admit test attribution on advisory demand
ScriptedAlchemy Oct 4, 2026
6400b04
test(sessions): assert journal frontiers and current schema
ScriptedAlchemy Oct 4, 2026
51c1cb0
fix(hooks): replay acknowledged delivery receipts durably
ScriptedAlchemy Oct 4, 2026
d2184c2
test(sessions): compare drain reads at the same WAL phase
ScriptedAlchemy Oct 4, 2026
c92586a
fix(index): decline graph waits when activation is disabled
ScriptedAlchemy Oct 4, 2026
03b3c6e
fix(worktrees): separate inspection tag from Git operation
ScriptedAlchemy Oct 4, 2026
899d45d
test(index): await the settled restart graph authority
ScriptedAlchemy Oct 4, 2026
8edb18a
test(transport): settle refresh before cancel receipt assertions
ScriptedAlchemy Oct 4, 2026
c0b6a44
style(transport): format settled refresh assertions
ScriptedAlchemy Oct 4, 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
34 changes: 27 additions & 7 deletions crates/tracedecay-agent-hosts/src/native_integration/worktree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ impl DaemonNativeWorktreeAuthority {
locked: WorktreeObservationV1::Unknown,
holder: WorktreeObservationV1::Unknown,
unique_data: WorktreeObservationV1::Unknown,
operation: None,
operation_state: None,
observed_at,
inspection_digest: zero_digest()?,
});
Expand Down Expand Up @@ -431,7 +431,7 @@ impl DaemonNativeWorktreeAuthority {
},
holder,
unique_data,
operation,
operation_state: operation,
observed_at,
inspection_digest: zero_digest()?,
})
Expand All @@ -455,7 +455,7 @@ impl DaemonNativeWorktreeAuthority {
locked: WorktreeObservationV1::Unknown,
holder: WorktreeObservationV1::Unknown,
unique_data: WorktreeObservationV1::Unknown,
operation: None,
operation_state: None,
observed_at,
inspection_digest: zero_digest()?,
})
Expand Down Expand Up @@ -513,7 +513,7 @@ impl DaemonNativeWorktreeAuthority {
locked: inspection.locked,
holder: inspection.holder,
unique_data: inspection.unique_data,
operation: inspection.operation,
operation: inspection.operation_state,
observed_at,
evidence_digest: zero_digest()?,
})
Expand Down Expand Up @@ -740,9 +740,10 @@ mod tests {
use std::process::Command;

use tracedecay_contracts::git::{
NativeWorktreeTargetV1, WorktreeInspectionV1, WorktreeKindV1, WorktreeObservationV1,
WorktreePresenceV1,
NativeWorktreeSurfaceResultV1, NativeWorktreeTargetV1, WorktreeInspectionOutcomeV1,
WorktreeInspectionV1, WorktreeKindV1, WorktreeObservationV1, WorktreePresenceV1,
};
use tracedecay_domain::git::GitOperationStateV1;
use tracedecay_domain::{ProjectId, RepositoryId, UtcMicros, WorktreeId};
use tracedecay_runtime_core::git::try_git_program;
use tracedecay_runtime_core::git_repository::GitRepositoryAuthority;
Expand Down Expand Up @@ -786,12 +787,31 @@ mod tests {
locked: WorktreeObservationV1::No,
holder: WorktreeObservationV1::No,
unique_data,
operation: None,
operation_state: None,
observed_at: UtcMicros(1),
inspection_digest: zero_digest().expect("inspection digest"),
}
}

#[test]
fn worktree_inspection_roundtrips_its_surface_tag_and_git_operation() {
for operation in [None, Some(GitOperationStateV1::Merge)] {
let mut observation = inspection(WorktreeObservationV1::Yes, WorktreeObservationV1::No);
observation.operation_state = operation;
let result = NativeWorktreeSurfaceResultV1::Inspection(
WorktreeInspectionOutcomeV1::Inspection(Box::new(observation)),
);
let encoded = serde_json::to_vec(&result).unwrap();
let decoded: NativeWorktreeSurfaceResultV1 = serde_json::from_slice(&encoded)
.expect("the operation tag and Git state must both survive the wire");
assert_eq!(decoded, result);
assert_eq!(
serde_json::to_value(result).unwrap()["operation"],
"inspection"
);
}
}

#[test]
fn cleanup_observations_match_real_git_status_and_preserve_blockers() {
let directory = tempfile::tempdir().expect("temporary fixture");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ impl DependencyDepthAuthorityV1 for TraceDecayDependencyDepthAuthorityV1 {
ideal_depth: count(result.ideal_depth),
depth_score: round4(depth_score(result.max_depth, result.ideal_depth)),
chains,
freshness: None,
},
coverage: coverage(count(adjacency.len()), returned, false),
continuation: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3061,6 +3061,20 @@ fn staging_sidecars_share_their_staging_artifact_liveness() {
));
std::fs::write(&orphan_carrying, b"abandoned carry journal").expect("write orphan carry");

let initializing_suffixes = [".staging.initializing", ".staging.initializing-journal"];
for suffix in initializing_suffixes {
std::fs::write(
artifacts_root.join(format!(".text-artifact-{active_digest}{suffix}")),
b"active initialization",
)
.expect("write active initialization");
std::fs::write(
artifacts_root.join(format!(".text-artifact-{}{suffix}", "c".repeat(64))),
b"abandoned initialization",
)
.expect("write abandoned initialization");
}

let report = run_code_generation_retention(
store.path(),
&BTreeSet::new(),
Expand All @@ -3070,7 +3084,7 @@ fn staging_sidecars_share_their_staging_artifact_liveness() {
)
.expect("apply sidecar-aware retention");

assert_eq!(report.deleted_text_artifacts.len(), 4);
assert_eq!(report.deleted_text_artifacts.len(), 6);
assert!(
active_staging.is_file()
&& active_sidecar.is_file()
Expand All @@ -3082,6 +3096,18 @@ fn staging_sidecars_share_their_staging_artifact_liveness() {
assert!(!orphan_sidecar.exists());
assert!(!orphan_compacting.exists());
assert!(!orphan_carrying.exists());
for suffix in initializing_suffixes {
assert!(
artifacts_root
.join(format!(".text-artifact-{active_digest}{suffix}"))
.is_file()
);
assert!(
!artifacts_root
.join(format!(".text-artifact-{}{suffix}", "c".repeat(64)))
.exists()
);
}
}

/// A daemon killed while `VACUUM INTO` writes the compacted rewrite leaves
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,9 @@ pub(super) fn staging_text_artifact_source_digest(file_name: &str) -> Option<&st
/// rewrite while `VACUUM INTO` writes it (`.staging-compacting-journal`, which
/// a kill mid-rewrite leaves behind), and a parent-artifact carry still being
/// copied before its rename onto the staging name (`.staging-carrying` and
/// its `.staging-carrying-journal`). They carry the same source-generation
/// its `.staging-carrying-journal`), and the builder's initialized sibling
/// before atomic publication (`.staging.initializing` and its SQLite journal).
/// They carry the same source-generation
/// digest as their staging file and share its liveness.
pub(super) fn staging_sidecar_text_artifact_source_digest(file_name: &str) -> Option<&str> {
let value = file_name.strip_prefix(".text-artifact-")?;
Expand All @@ -537,7 +539,9 @@ pub(super) fn staging_sidecar_text_artifact_source_digest(file_name: &str) -> Op
.or_else(|| value.strip_suffix(".staging-compacting"))
.or_else(|| value.strip_suffix(".staging-compacting-journal"))
.or_else(|| value.strip_suffix(".staging-carrying"))
.or_else(|| value.strip_suffix(".staging-carrying-journal"))?;
.or_else(|| value.strip_suffix(".staging-carrying-journal"))
.or_else(|| value.strip_suffix(".staging.initializing"))
.or_else(|| value.strip_suffix(".staging.initializing-journal"))?;
is_lowercase_hex(digest, 64).then_some(digest)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -853,17 +853,18 @@ impl CodeIndexSchedulerRegistryV1 {
/// is what starts that decode: it waits for the seat rather than answering
/// the demanding request unavailable, until `deadline`. A seat that does
/// not serve this scope, or no published text owner to decode, ends it.
pub(crate) async fn latest_complete_fresh_for_scope_awaiting_seat(
pub async fn latest_complete_fresh_for_scope_awaiting_seat(
&self,
scope: &tracedecay_contracts::ResolvedScope,
deadline: tokio::time::Instant,
) -> Option<LatestCompleteCodeIndexV1> {
let root = {
let mounted = self.mounted.lock().await;
unique_mounted_for_scope(&mounted, scope)
.unique()?
.0
.clone()
let (root, worktree) = unique_mounted_for_scope(&mounted, scope).unique()?;
if !worktree.graph_activation.policy().is_enabled() {
return None;
}
root.clone()
};
let root = &root;
let slots = || async move {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ impl ProductionCodeIndexQueryOwnersV1 {
families,
coverage,
next_cursor,
freshness: None,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11539,6 +11539,18 @@ async fn pinned_configuration_refuses_native_graph_before_text_serving_swap() {
.is_none(),
"graph-off must leave the complete serving slot empty"
);
assert!(
tokio::time::timeout(
Duration::from_secs(1),
registry.latest_complete_fresh_for_scope_awaiting_seat(
&scope,
tokio::time::Instant::now() + SERVING_SEAT_FAILURE_CEILING,
),
)
.await
.expect("a policy-disabled graph seat must refuse without awaiting its deadline")
.is_none()
);
let indexed_file = latest
.metadata()
.snapshot()
Expand Down
6 changes: 3 additions & 3 deletions crates/tracedecay-contracts/src/git/worktree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ pub struct WorktreeInspectionV1 {
pub locked: WorktreeObservationV1,
pub holder: WorktreeObservationV1,
pub unique_data: WorktreeObservationV1,
pub operation: Option<GitOperationStateV1>,
pub operation_state: Option<GitOperationStateV1>,
pub observed_at: UtcMicros,
pub inspection_digest: ManifestDigest,
}
Expand All @@ -382,7 +382,7 @@ impl WorktreeInspectionV1 {
&& self.locked == WorktreeObservationV1::No
&& self.holder == WorktreeObservationV1::No
&& self.unique_data == WorktreeObservationV1::No
&& self.operation.is_none()
&& self.operation_state.is_none()
}
}

Expand Down Expand Up @@ -655,7 +655,7 @@ pub fn worktree_inspection_digest(
inspection.locked,
inspection.holder,
inspection.unique_data,
&inspection.operation,
&inspection.operation_state,
))
.map_err(|_| WorktreeContractError::Inconsistent {
field: "worktree inspection digest",
Expand Down
Loading
Loading