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
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,11 @@ impl HeldActiveDecodeV1 {
}
}

/// Last validated publication pointer, reused when the on-disk file is unchanged.
/// Last validated publication pointer, reused when the on-disk bytes are unchanged.
///
/// Equal length and mtime are not identity. A same-size rewrite inside one
/// timestamp quantum must still be compared by digest before a compare-and-swap
/// treats the memo as the incumbent pointer.
struct PublicationPointerMemoV1 {
mtime: Option<SystemTime>,
size: u64,
Expand Down Expand Up @@ -1086,19 +1090,6 @@ impl DaemonCodeIndexPublicationStoreV1 {
}
let mtime = metadata.modified().ok();
let size = metadata.len();
{
let memo = self
.pointer_memo
.lock()
.unwrap_or_else(PoisonError::into_inner);
if let Some(memo) = memo.as_ref()
&& memo.size == size
&& memo.mtime.is_some()
&& memo.mtime == mtime
{
return Ok(Some(memo.pointer.clone()));
}
}
let bytes = std::fs::read(&self.active_path).map_err(Self::unavailable)?;
let digest = Self::state_digest(&bytes);
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2510,7 +2510,28 @@ fn publication_over_an_undecodable_active_generation_refuses_a_moved_pointer() {
}

let mut restored = observed.clone();
let moved_metadata = std::fs::metadata(&pointer_path).expect("moved pointer metadata");
let preserved_mtime = moved_metadata.modified().expect("moved pointer mtime");
let moved_len = moved_metadata.len();
write_repaired_pointer(&pointer_path, &mut restored);
filetime::set_file_mtime(
&pointer_path,
filetime::FileTime::from_system_time(preserved_mtime),
)
.expect("preserve the moved pointer mtime on the restored identity");
let restored_metadata = std::fs::metadata(&pointer_path).expect("restored pointer metadata");
assert_eq!(
restored_metadata.len(),
moved_len,
"the restored identity must be invisible to a length check"
);
assert_eq!(
restored_metadata
.modified()
.expect("restored pointer mtime"),
preserved_mtime,
"the restored identity must be invisible to an mtime check"
);
let mut admitting = publication.for_undecoded_active_rebuild(&observed);
admitting
.publish_atomically(&scope, None, seeded)
Expand Down
54 changes: 7 additions & 47 deletions crates/tracedecay-contracts/src/retrieval/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,40 +202,6 @@ fn primitive_read_surfaces(spec: &PrimitiveReadSpec) -> &'static [BindingSurface
}
}

/// Similar/redundancy cut over to the family wire schema. Protocol revisions
/// share one (surface, operation) key; `ProtocolRevisionRange` carries the
/// accepted revisions. Do not mint a second binding for the same spelling;
/// `index_bindings` rejects duplicate surface-operation keys.
fn clone_family_surface_bindings(
capability_id: &CapabilityId,
operation: &str,
surfaces: &[BindingSurface],
) -> Result<(Vec<SurfaceBindingV1>, Vec<BindingId>), ApplicationContractError> {
use crate::surface_binding::surface_name;

let mut bindings = Vec::with_capacity(surfaces.len());
let mut binding_ids = Vec::with_capacity(surfaces.len());
for surface in surfaces.iter().copied() {
let binding_id = BindingId::new(format!(
"binding.{}.{}.v1",
surface_name(surface),
operation
))?;
bindings.push(SurfaceBindingV1::new(SurfaceBindingInputV1 {
binding_id: binding_id.clone(),
capability_id: capability_id.clone(),
surface,
operation: SurfaceOperationName::new(operation)?,
protocol_revisions: ProtocolRevisionRange::new(1, 2)?,
required_features: Vec::new(),
status: BindingStatus::Current,
alias_of: None,
})?);
binding_ids.push(binding_id);
}
Ok((bindings, binding_ids))
}

fn primitive_read_description(operation: &str) -> &'static str {
match operation {
"code_signature_search" => {
Expand Down Expand Up @@ -380,19 +346,13 @@ pub fn primitive_read_contribution() -> Result<CatalogContributionV1, Applicatio
))?;
let surfaces = primitive_read_surfaces(spec);
let (surface_bindings, mut binding_ids) =
if matches!(spec.operation, "similar" | "redundancy") {
clone_family_surface_bindings(&capability_id, spec.operation, surfaces)?
} else {
match ApplicationSurfaceOperation::from_catalog_name(spec.operation) {
Some(operation) => current_application_bindings(
&capability_id,
operation,
surfaces.iter().copied(),
)?,
None => {
current_bindings(&capability_id, spec.operation, surfaces.iter().copied())?
}
}
match ApplicationSurfaceOperation::from_catalog_name(spec.operation) {
Some(operation) => current_application_bindings(
&capability_id,
operation,
surfaces.iter().copied(),
)?,
None => current_bindings(&capability_id, spec.operation, surfaces.iter().copied())?,
};
bindings.extend(surface_bindings);
binding_ids.reserve(primitive_lsp_methods(spec.operation).len());
Expand Down
28 changes: 13 additions & 15 deletions crates/tracedecay-contracts/src/retrieval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,21 @@ pub use ports::{
pub use primitive_surface::{
CalleeV1, CalleesResultV1, CalleesSurfaceRequestV1, ContextCodeBlockV1, ContextModeV1,
ContextResultV1, ContextSearchMatchV1, ContextSurfaceRequestV1, ImpactNodeV1, ImpactResultV1,
ImpactSurfaceRequestV1, LegacyRedundancySurfaceRequestV1, LegacySimilarSurfaceRequestV1,
MAX_REDUNDANCY_FAMILIES_V1, MAX_REDUNDANCY_PULL_REQUEST_PATHS_V1, MAX_REDUNDANCY_WORK_V1,
NodeDepthSurfaceRequestV1, NodeDetailsV1, NodeExpansionCostV1, NodeResultV1,
NodeSurfaceRequestV1, PortCycleAnchorV1, PortCycleFileV1, PortCycleSymbolV1, PortCycleV1,
PortMatchedSymbolV1, PortOrderLevelV1, PortOrderResultV1, PortOrderSurfaceRequestV1,
PortOrderSymbolV1, PortStatusResultV1, PortStatusSurfaceRequestV1, PortTargetOnlySymbolV1,
PortUnmatchedSymbolV1, PrimitiveFreshnessStateV1, PrimitiveIndexingStateV1,
PrimitiveLaneCompleteV1, PrimitiveLaneStateV1, PrimitiveLaneStatusV1, PrimitiveNotFoundV1,
PrimitiveRecallV1, PrimitiveSearchCoverageV1, PrimitiveSearchFreshnessV1,
ImpactSurfaceRequestV1, MAX_REDUNDANCY_FAMILIES_V1, MAX_REDUNDANCY_PULL_REQUEST_PATHS_V1,
MAX_REDUNDANCY_WORK_V1, NodeDepthSurfaceRequestV1, NodeDetailsV1, NodeExpansionCostV1,
NodeResultV1, NodeSurfaceRequestV1, PortCycleAnchorV1, PortCycleFileV1, PortCycleSymbolV1,
PortCycleV1, PortMatchedSymbolV1, PortOrderLevelV1, PortOrderResultV1,
PortOrderSurfaceRequestV1, PortOrderSymbolV1, PortStatusResultV1, PortStatusSurfaceRequestV1,
PortTargetOnlySymbolV1, PortUnmatchedSymbolV1, PrimitiveFreshnessStateV1,
PrimitiveIndexingStateV1, PrimitiveLaneCompleteV1, PrimitiveLaneStateV1, PrimitiveLaneStatusV1,
PrimitiveNotFoundV1, PrimitiveRecallV1, PrimitiveSearchCoverageV1, PrimitiveSearchFreshnessV1,
PrimitiveSymbolLocationV1, PrimitiveUnavailableEvidenceV1, PrimitiveUnavailableStatusV1,
RedundancyCoverageV1, RedundancyFamilyV1, RedundancyPartialReasonV1, RedundancyRankingV1,
RedundancyResultV1, RedundancyScopeV1, RedundancySurfaceRequestV1,
RedundancySurfaceRequestWireV1, RenamePreviewNodeV1, RenamePreviewPrimitiveOutcomeV1,
RenamePreviewPrimitiveRequestV1, RenamePreviewPrimitiveResultV1, RenamePreviewReferenceV1,
RenamePreviewTextOnlyMatchV1, SimilarCoverageV1, SimilarFamilyV1, SimilarMatchClassV1,
SimilarOccurrenceV1, SimilarResultV1, SimilarSurfaceRequestV1, SimilarSurfaceRequestWireV1,
SimilarTargetV1, TodoMarkerV1, TodosResultV1, TodosSurfaceRequestV1,
RedundancyResultV1, RedundancyScopeV1, RedundancySurfaceRequestV1, RenamePreviewNodeV1,
RenamePreviewPrimitiveOutcomeV1, RenamePreviewPrimitiveRequestV1,
RenamePreviewPrimitiveResultV1, RenamePreviewReferenceV1, RenamePreviewTextOnlyMatchV1,
SimilarCoverageV1, SimilarFamilyV1, SimilarMatchClassV1, SimilarOccurrenceV1, SimilarResultV1,
SimilarSurfaceRequestV1, SimilarTargetV1, TodoMarkerV1, TodosResultV1, TodosSurfaceRequestV1,
};
pub use requests::{
AffectedTestAttributionV1, AffectedTestsRequest, AffectedTestsResult, AnchorExpandRequest,
Expand Down
110 changes: 49 additions & 61 deletions crates/tracedecay-contracts/src/retrieval/primitive_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,31 +156,12 @@ pub struct SimilarSurfaceRequestV1 {
pub repository_id: RepositoryId,
pub target: SimilarTargetV1,
pub match_classes: Vec<SimilarMatchClassV1>,
/// Preferred result page size. Accepts legacy `limit` as a wire alias.
#[serde(alias = "limit")]
/// Preferred result page size on the family schema.
pub result_limit: u32,
pub work_limit: u32,
pub cursor: Option<String>,
}

/// Pre-family similar request shape (`{symbol, limit}`) retained for decode
/// so cutover clients get a typed migration error instead of opaque serde noise.
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct LegacySimilarSurfaceRequestV1 {
pub symbol: String,
pub limit: Option<u32>,
}

/// Runtime decode envelope for `tracedecay_similar`: current family schema or
/// the retired `{symbol, limit}` spelling.
#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum SimilarSurfaceRequestWireV1 {
Current(SimilarSurfaceRequestV1),
Legacy(LegacySimilarSurfaceRequestV1),
}

#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RenamePreviewPrimitiveRequestV1 {
Expand Down Expand Up @@ -227,35 +208,13 @@ pub struct RedundancySurfaceRequestV1 {
pub match_classes: Vec<SimilarMatchClassV1>,
pub scope: RedundancyScopeV1,
pub include_generated_paths: bool,
/// Preferred family page size. Accepts legacy `max_pairs` / `limit` aliases.
#[serde(alias = "max_pairs", alias = "limit")]
/// Preferred family page size on the family schema.
pub family_limit: u32,
pub member_limit: u32,
pub work_limit: u32,
pub cursor: Option<String>,
}

/// Pre-family redundancy request shape retained for decode so cutover clients
/// get a typed migration error instead of opaque serde noise.
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct LegacyRedundancySurfaceRequestV1 {
pub path: Option<String>,
pub min_lines: Option<u32>,
pub max_pairs: Option<u32>,
pub similarity_threshold: Option<f64>,
pub include_naming_only: Option<bool>,
pub include_generated_paths: Option<bool>,
}

/// Runtime decode envelope for `tracedecay_redundancy`.
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum RedundancySurfaceRequestWireV1 {
Current(RedundancySurfaceRequestV1),
Legacy(LegacyRedundancySurfaceRequestV1),
}

#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TodosSurfaceRequestV1 {
Expand Down Expand Up @@ -764,7 +723,7 @@ mod tests {
ContextModeV1, ContextResultV1, ContextSurfaceRequestV1, PrimitiveFreshnessStateV1,
PrimitiveIndexingStateV1, PrimitiveLaneCompleteV1, PrimitiveLaneStatusV1,
PrimitiveRecallV1, PrimitiveSearchCoverageV1, PrimitiveSearchFreshnessV1,
RedundancySurfaceRequestWireV1, SimilarSurfaceRequestWireV1,
RedundancySurfaceRequestV1, SimilarSurfaceRequestV1,
};
use crate::memory::{FactSearchGraphCoverageV1, FactSearchGraphDegradationV1};

Expand Down Expand Up @@ -901,11 +860,39 @@ mod tests {
}

#[test]
fn similar_and_redundancy_accept_legacy_request_shapes_on_the_wire() {
fn similar_and_redundancy_reject_retired_request_shapes() {
let legacy_similar = json!({"symbol": "foo", "limit": 5});
let wire: SimilarSurfaceRequestWireV1 =
serde_json::from_value(legacy_similar).expect("legacy similar decodes");
assert!(matches!(wire, SimilarSurfaceRequestWireV1::Legacy(_)));
assert!(
serde_json::from_value::<SimilarSurfaceRequestV1>(legacy_similar).is_err(),
"retired {{symbol, limit}} is not a family-schema request"
);

let alias_similar = json!({
"project_id": "project.demo",
"repository_id": "repo.demo",
"target": {"kind": "symbol_occurrence", "symbol_occurrence_id": "symbol.v1.demo"},
"match_classes": ["conservative_exact"],
"limit": 3,
"work_limit": 100,
"cursor": null
});
assert!(
serde_json::from_value::<SimilarSurfaceRequestV1>(alias_similar).is_err(),
"limit is not an alias for result_limit"
);

let current_similar = json!({
"project_id": "project.demo",
"repository_id": "repo.demo",
"target": {"kind": "symbol_occurrence", "symbol_occurrence_id": "symbol.v1.demo"},
"match_classes": ["conservative_exact"],
"result_limit": 3,
"work_limit": 100,
"cursor": null
});
let request: SimilarSurfaceRequestV1 =
serde_json::from_value(current_similar).expect("family similar schema decodes");
assert_eq!(request.result_limit, 3);

let legacy_redundancy = json!({
"path": "src/",
Expand All @@ -915,24 +902,25 @@ mod tests {
"include_naming_only": false,
"include_generated_paths": true
});
let wire: RedundancySurfaceRequestWireV1 =
serde_json::from_value(legacy_redundancy).expect("legacy redundancy decodes");
assert!(matches!(wire, RedundancySurfaceRequestWireV1::Legacy(_)));
assert!(
serde_json::from_value::<RedundancySurfaceRequestV1>(legacy_redundancy).is_err(),
"retired path/max_pairs shape is not a family-schema request"
);

let current_similar = json!({
let alias_redundancy = json!({
"project_id": "project.demo",
"repository_id": "repo.demo",
"target": {"kind": "symbol_occurrence", "symbol_occurrence_id": "symbol.v1.demo"},
"match_classes": ["conservative_exact"],
"limit": 3,
"work_limit": 100,
"scope": {"kind": "repository"},
"include_generated_paths": false,
"max_pairs": 4,
"member_limit": 2,
"work_limit": 10,
"cursor": null
});
let wire: SimilarSurfaceRequestWireV1 = serde_json::from_value(current_similar)
.expect("current similar decodes with limit alias");
match wire {
SimilarSurfaceRequestWireV1::Current(request) => assert_eq!(request.result_limit, 3),
SimilarSurfaceRequestWireV1::Legacy(_) => panic!("expected current family schema"),
}
assert!(
serde_json::from_value::<RedundancySurfaceRequestV1>(alias_redundancy).is_err(),
"max_pairs is not an alias for family_limit"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ fn verified_graph_mcp_reads_have_application_primitive_admission_identity() {
}

#[test]
fn similar_and_redundancy_cover_protocol_revisions_on_one_surface_operation() {
fn similar_and_redundancy_keep_one_current_protocol_revision() {
use tracedecay_tool_catalog::BindingStatus;

let contribution = primitive_read_contribution().unwrap();
Expand All @@ -208,14 +208,14 @@ fn similar_and_redundancy_cover_protocol_revisions_on_one_surface_operation() {
assert_eq!(binding.alias_of(), None);
assert!(
binding.protocol_revisions().contains(1),
"{operation} must accept protocol revision 1"
"{operation} must accept the family-schema protocol revision"
);
assert!(
binding.protocol_revisions().contains(2),
"{operation} must accept protocol revision 2"
!binding.protocol_revisions().contains(2),
"{operation} must not advertise a retired cutover revision"
);
assert_eq!(binding.protocol_revisions().minimum(), 1);
assert_eq!(binding.protocol_revisions().maximum(), 2);
assert_eq!(binding.protocol_revisions().maximum(), 1);
}
}

Expand Down
7 changes: 0 additions & 7 deletions crates/tracedecay-global-db/src/schema_stages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,13 +833,6 @@ async fn install_registered_schema_stage_sequence(
session_temporal_schema::SessionTemporalSchemaAdmission::Fresh => {
session_temporal_schema::install_session_temporal_schema(transaction).await?;
}
session_temporal_schema::SessionTemporalSchemaAdmission::ReleasedV3 => {
session_temporal_schema::migrate_released_v3_session_temporal_schema(transaction)
.await?;
}
session_temporal_schema::SessionTemporalSchemaAdmission::WithoutReceiptRecovery => {
session_temporal_schema::migrate_session_relation_receipt_recovery(transaction).await?;
}
session_temporal_schema::SessionTemporalSchemaAdmission::Current => {}
}
observation::ensure_observation_schema(transaction).await?;
Expand Down
Loading
Loading