feat: discover verified persona repository bindings
This commit is contained in:
parent
d0201ba09f
commit
b0970ed0d2
18 changed files with 417 additions and 15 deletions
|
|
@ -526,6 +526,7 @@ macro_rules! app_invoke_handler {
|
|||
guanghu_living_system::guanghu_living_system_plan,
|
||||
persona_code_channel::prepare_persona_code_channel_wake,
|
||||
persona_code_channel::inspect_persona_code_channel_manifest,
|
||||
persona_code_channel::discover_persona_code_channel_repositories,
|
||||
persona_code_channel::query_persona_code_channel_runtime,
|
||||
persona_code_channel::run_persona_code_channel_fact_task,
|
||||
persona_code_channel::run_persona_code_channel_memory_metabolism,
|
||||
|
|
|
|||
|
|
@ -187,11 +187,40 @@ pub struct PersonaManifestInspectionReceipt {
|
|||
pub brain_entry: String,
|
||||
pub current_checkpoint: String,
|
||||
pub human_responsibility_subject: String,
|
||||
pub cognitive_gravity: PersonaCognitiveGravityEvidence,
|
||||
pub model_provider_id: String,
|
||||
pub model_id: String,
|
||||
pub model_base_url: String,
|
||||
pub git_author_name: String,
|
||||
pub git_author_email: String,
|
||||
pub organ_contracts: Vec<PersonaOrganContract>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PersonaRepositoryDiscoveryInput {
|
||||
pub expected_persona_id: String,
|
||||
pub repository_paths: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PersonaRepositoryDiscoveryFailure {
|
||||
pub repository_path: String,
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PersonaRepositoryDiscoveryReceipt {
|
||||
pub schema: &'static str,
|
||||
pub expected_persona_id: String,
|
||||
pub inspected_repository_count: usize,
|
||||
pub binding_count: usize,
|
||||
pub bindings: Vec<PersonaManifestInspectionReceipt>,
|
||||
pub failures: Vec<PersonaRepositoryDiscoveryFailure>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PersonaRuntimeQueryInput {
|
||||
|
|
@ -906,7 +935,7 @@ fn inspect_manifest_at(
|
|||
validate_git_identity(&manifest.git_identity)?;
|
||||
validate_model_binding(&manifest.model_binding)?;
|
||||
repository_file(&repository, &manifest.brain_entry)?;
|
||||
cognitive_gravity_evidence(&repository, &manifest)?;
|
||||
let cognitive_gravity = cognitive_gravity_evidence(&repository, &manifest)?;
|
||||
repository_file(&repository, &manifest.current_checkpoint)?;
|
||||
let mut contracts = Vec::with_capacity(manifest.organs.len());
|
||||
for organ in &manifest.organs {
|
||||
|
|
@ -927,12 +956,68 @@ fn inspect_manifest_at(
|
|||
brain_entry: manifest.brain_entry,
|
||||
current_checkpoint: manifest.current_checkpoint,
|
||||
human_responsibility_subject: manifest.human_responsibility_subject,
|
||||
cognitive_gravity,
|
||||
model_provider_id: manifest.model_binding.provider_id,
|
||||
model_id: manifest.model_binding.model_id,
|
||||
model_base_url: manifest.model_binding.base_url,
|
||||
git_author_name: manifest.git_identity.author_name,
|
||||
git_author_email: manifest.git_identity.author_email,
|
||||
organ_contracts: contracts,
|
||||
})
|
||||
}
|
||||
|
||||
fn discover_persona_repositories_at(
|
||||
input: PersonaRepositoryDiscoveryInput,
|
||||
) -> Result<PersonaRepositoryDiscoveryReceipt, String> {
|
||||
let expected_persona_id = validated_id("EXPECTED_PERSONA_ID", &input.expected_persona_id)?;
|
||||
if input.repository_paths.len() > 64 {
|
||||
return Err("PERSONA_REPOSITORY_DISCOVERY_LIMIT_EXCEEDED".into());
|
||||
}
|
||||
let mut seen = Vec::<PathBuf>::new();
|
||||
let mut bindings = Vec::new();
|
||||
let mut failures = Vec::new();
|
||||
for raw_path in input.repository_paths {
|
||||
let trimmed = raw_path.trim();
|
||||
if trimmed.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let display_path = trimmed.to_string();
|
||||
let (repository, git_head) = match exact_repository(Path::new(trimmed)) {
|
||||
Ok(value) => value,
|
||||
Err(code) => {
|
||||
failures.push(PersonaRepositoryDiscoveryFailure {
|
||||
repository_path: display_path,
|
||||
code,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if seen.iter().any(|candidate| candidate == &repository) {
|
||||
continue;
|
||||
}
|
||||
seen.push(repository.clone());
|
||||
match inspect_manifest_at(PersonaManifestInspectionInput {
|
||||
repository_path: repository.to_string_lossy().into_owned(),
|
||||
expected_persona_id: expected_persona_id.clone(),
|
||||
expected_head: git_head,
|
||||
}) {
|
||||
Ok(receipt) => bindings.push(receipt),
|
||||
Err(code) => failures.push(PersonaRepositoryDiscoveryFailure {
|
||||
repository_path: repository.to_string_lossy().into_owned(),
|
||||
code,
|
||||
}),
|
||||
}
|
||||
}
|
||||
Ok(PersonaRepositoryDiscoveryReceipt {
|
||||
schema: "hololake.pncc-repository-discovery/v1",
|
||||
expected_persona_id,
|
||||
inspected_repository_count: seen.len(),
|
||||
binding_count: bindings.len(),
|
||||
bindings,
|
||||
failures,
|
||||
})
|
||||
}
|
||||
|
||||
fn hex_digest(bytes: &[u8]) -> String {
|
||||
digest(&SHA256, bytes)
|
||||
.as_ref()
|
||||
|
|
@ -3759,6 +3844,13 @@ pub fn inspect_persona_code_channel_manifest(
|
|||
inspect_manifest_at(input)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn discover_persona_code_channel_repositories(
|
||||
input: PersonaRepositoryDiscoveryInput,
|
||||
) -> Result<PersonaRepositoryDiscoveryReceipt, String> {
|
||||
discover_persona_repositories_at(input)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn query_persona_code_channel_runtime(
|
||||
input: PersonaRuntimeQueryInput,
|
||||
|
|
@ -6266,6 +6358,9 @@ mod tests {
|
|||
let receipt = inspect_manifest_at(manifest_inspection(repo.path())).unwrap();
|
||||
assert_eq!(receipt.persona_id, "ICE-P-ZY001");
|
||||
assert!(receipt.repository_clean);
|
||||
assert_eq!(receipt.model_provider_id, "fixture-provider");
|
||||
assert_eq!(receipt.model_id, "fixture-model");
|
||||
assert_eq!(receipt.cognitive_gravity.subject_persona_id, "ICE-P-ZY001");
|
||||
assert_eq!(receipt.organ_contracts.len(), 1);
|
||||
let contract = &receipt.organ_contracts[0];
|
||||
assert_eq!(contract.kind, PersonaOrganKind::FactSense);
|
||||
|
|
@ -6276,6 +6371,60 @@ mod tests {
|
|||
assert_eq!(contract.implementation_state, "IMPLEMENTED");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discovers_only_verified_persona_repository_bindings() {
|
||||
let persona = persona_repo();
|
||||
let ordinary = tempfile::TempDir::new().unwrap();
|
||||
run_git(ordinary.path(), &["init", "-b", "main"]);
|
||||
run_git(
|
||||
ordinary.path(),
|
||||
&["config", "user.name", "Ordinary Repository"],
|
||||
);
|
||||
run_git(
|
||||
ordinary.path(),
|
||||
&["config", "user.email", "ordinary@example.invalid"],
|
||||
);
|
||||
fs::write(ordinary.path().join("README.md"), "ordinary repository\n").unwrap();
|
||||
run_git(ordinary.path(), &["add", "."]);
|
||||
run_git(ordinary.path(), &["commit", "-m", "ordinary fixture"]);
|
||||
|
||||
let receipt = discover_persona_repositories_at(PersonaRepositoryDiscoveryInput {
|
||||
expected_persona_id: "ICE-P-ZY001".into(),
|
||||
repository_paths: vec![
|
||||
ordinary.path().to_string_lossy().into_owned(),
|
||||
persona.path().to_string_lossy().into_owned(),
|
||||
persona.path().to_string_lossy().into_owned(),
|
||||
],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(receipt.schema, "hololake.pncc-repository-discovery/v1");
|
||||
assert_eq!(receipt.inspected_repository_count, 2);
|
||||
assert_eq!(receipt.binding_count, 1);
|
||||
assert_eq!(receipt.bindings[0].persona_id, "ICE-P-ZY001");
|
||||
assert_eq!(receipt.failures.len(), 1);
|
||||
assert!(
|
||||
receipt.failures[0]
|
||||
.code
|
||||
.starts_with("PERSONA_FILE_UNAVAILABLE: .hololake/persona/manifest.json:"),
|
||||
"unexpected discovery failure: {}",
|
||||
receipt.failures[0].code,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_persona_repository_discovery_is_a_truthful_non_binding_receipt() {
|
||||
let receipt = discover_persona_repositories_at(PersonaRepositoryDiscoveryInput {
|
||||
expected_persona_id: "ICE-P-ZY001".into(),
|
||||
repository_paths: Vec::new(),
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(receipt.inspected_repository_count, 0);
|
||||
assert_eq!(receipt.binding_count, 0);
|
||||
assert!(receipt.bindings.is_empty());
|
||||
assert!(receipt.failures.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn declares_but_refuses_an_execution_limb_without_an_executor() {
|
||||
let repo = persona_repo();
|
||||
|
|
|
|||
Loading…
Reference in a new issue