fix: carry prompt projection source identity

This commit is contained in:
2026-08-19 04:30:00 +09:00
parent 0d011ea0cd
commit 382b5e57f2
3 changed files with 28 additions and 14 deletions
+16 -12
View File
@@ -653,18 +653,22 @@ impl RuntimeWorkerFactory for ProfileRuntimeWorkerFactory {
}; };
if let Some(bundle) = request.config_bundle.as_ref() { if let Some(bundle) = request.config_bundle.as_ref() {
if let Some(prompt_catalog) = bundle.prompt_catalog.clone() { if let Some(prompt_catalog) = bundle.prompt_catalog.clone() {
let source_digest = bundle let source_digest = if prompt_catalog.source_digest.is_empty() {
.metadata bundle
.provenance .metadata
.detail .provenance
.as_deref() .detail
.and_then(|detail| { .as_deref()
detail .and_then(|detail| {
.split(';') detail
.find_map(|part| part.strip_prefix("source_tree_digest=")) .split(';')
}) .find_map(|part| part.strip_prefix("source_tree_digest="))
.unwrap_or(&prompt_catalog.catalog_digest) })
.to_string(); .unwrap_or(&prompt_catalog.catalog_digest)
.to_string()
} else {
prompt_catalog.source_digest.clone()
};
let projection = worker::WorkspacePromptProjection::new( let projection = worker::WorkspacePromptProjection::new(
bundle.metadata.workspace_id.clone(), bundle.metadata.workspace_id.clone(),
source_digest, source_digest,
+8
View File
@@ -31,6 +31,8 @@ const BUILTIN_TOOLCHAIN_FINGERPRINT: &str = "builtin:prompts:decodal-0.4";
pub struct EffectivePromptCatalog { pub struct EffectivePromptCatalog {
pub templates: BTreeMap<String, String>, pub templates: BTreeMap<String, String>,
pub config_revision: u64, pub config_revision: u64,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub source_digest: String,
pub schema_fingerprint: String, pub schema_fingerprint: String,
pub toolchain_fingerprint: String, pub toolchain_fingerprint: String,
pub catalog_digest: String, pub catalog_digest: String,
@@ -48,6 +50,7 @@ impl EffectivePromptCatalog {
Ok(Self { Ok(Self {
templates, templates,
config_revision, config_revision,
source_digest: String::new(),
schema_fingerprint: schema_fingerprint.into(), schema_fingerprint: schema_fingerprint.into(),
toolchain_fingerprint: toolchain_fingerprint.into(), toolchain_fingerprint: toolchain_fingerprint.into(),
catalog_digest, catalog_digest,
@@ -208,6 +211,11 @@ impl WorkspacePromptProjection {
"Workspace Prompt projection digest must not be empty".to_string(), "Workspace Prompt projection digest must not be empty".to_string(),
)); ));
} }
if !catalog.source_digest.is_empty() && catalog.source_digest != source_digest {
return Err(CatalogError::InvalidTemplateCatalog(
"Workspace Prompt projection source digest does not match its catalog".to_string(),
));
}
Ok(Self { Ok(Self {
workspace_id, workspace_id,
config_revision: catalog.config_revision, config_revision: catalog.config_revision,
@@ -215,13 +215,15 @@ pub fn project_prompts_from_workspace_config(
"active Workspace config projection has no prompts namespace".to_string(), "active Workspace config projection has no prompts namespace".to_string(),
) )
})?; })?;
EffectivePromptCatalog::from_projection( let mut catalog = EffectivePromptCatalog::from_projection(
prompts, prompts,
state.snapshot.revision, state.snapshot.revision,
state.contract.schema_bundle.fingerprint.clone(), state.contract.schema_bundle.fingerprint.clone(),
state.contract.fingerprint.clone(), state.contract.fingerprint.clone(),
) )
.map_err(|error| Error::RegistryInconsistency(error.to_string())) .map_err(|error| Error::RegistryInconsistency(error.to_string()))?;
catalog.source_digest = state.snapshot.digest.clone();
Ok(catalog)
} }
pub fn project_workspace_prompt_projection( pub fn project_workspace_prompt_projection(